GC.c revision 05b261ec
1/* 2 3Copyright 1993 by Davor Matic 4 5Permission to use, copy, modify, distribute, and sell this software 6and its documentation for any purpose is hereby granted without fee, 7provided that the above copyright notice appear in all copies and that 8both that copyright notice and this permission notice appear in 9supporting documentation. Davor Matic makes no representations about 10the suitability of this software for any purpose. It is provided "as 11is" without express or implied warranty. 12 13*/ 14 15#ifdef HAVE_XNEST_CONFIG_H 16#include <xnest-config.h> 17#endif 18 19#include <X11/X.h> 20#include <X11/Xproto.h> 21#include "gcstruct.h" 22#include "windowstr.h" 23#include "pixmapstr.h" 24#include "scrnintstr.h" 25#include <X11/fonts/fontstruct.h> 26#include "mistruct.h" 27#include "region.h" 28 29#include "Xnest.h" 30 31#include "Display.h" 32#include "XNGC.h" 33#include "GCOps.h" 34#include "Drawable.h" 35#include "XNFont.h" 36#include "Color.h" 37 38int xnestGCPrivateIndex; 39 40static GCFuncs xnestFuncs = { 41 xnestValidateGC, 42 xnestChangeGC, 43 xnestCopyGC, 44 xnestDestroyGC, 45 xnestChangeClip, 46 xnestDestroyClip, 47 xnestCopyClip, 48}; 49 50static GCOps xnestOps = { 51 xnestFillSpans, 52 xnestSetSpans, 53 xnestPutImage, 54 xnestCopyArea, 55 xnestCopyPlane, 56 xnestPolyPoint, 57 xnestPolylines, 58 xnestPolySegment, 59 xnestPolyRectangle, 60 xnestPolyArc, 61 xnestFillPolygon, 62 xnestPolyFillRect, 63 xnestPolyFillArc, 64 xnestPolyText8, 65 xnestPolyText16, 66 xnestImageText8, 67 xnestImageText16, 68 xnestImageGlyphBlt, 69 xnestPolyGlyphBlt, 70 xnestPushPixels 71}; 72 73Bool 74xnestCreateGC(GCPtr pGC) 75{ 76 pGC->clientClipType = CT_NONE; 77 pGC->clientClip = NULL; 78 79 pGC->funcs = &xnestFuncs; 80 pGC->ops = &xnestOps; 81 82 pGC->miTranslate = 1; 83 84 xnestGCPriv(pGC)->gc = XCreateGC(xnestDisplay, 85 xnestDefaultDrawables[pGC->depth], 86 0L, NULL); 87 xnestGCPriv(pGC)->nClipRects = 0; 88 89 return True; 90} 91 92void 93xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 94{ 95 pGC->lastWinOrg.x = pDrawable->x; 96 pGC->lastWinOrg.y = pDrawable->y; 97} 98 99void 100xnestChangeGC(GCPtr pGC, unsigned long mask) 101{ 102 XGCValues values; 103 104 if (mask & GCFunction) 105 values.function = pGC->alu; 106 107 if (mask & GCPlaneMask) 108 values.plane_mask = pGC->planemask; 109 110 if (mask & GCForeground) 111 values.foreground = xnestPixel(pGC->fgPixel); 112 113 if (mask & GCBackground) 114 values.background = xnestPixel(pGC->bgPixel); 115 116 if (mask & GCLineWidth) 117 values.line_width = pGC->lineWidth; 118 119 if (mask & GCLineStyle) 120 values.line_style = pGC->lineStyle; 121 122 if (mask & GCCapStyle) 123 values.cap_style = pGC->capStyle; 124 125 if (mask & GCJoinStyle) 126 values.join_style = pGC->joinStyle; 127 128 if (mask & GCFillStyle) 129 values.fill_style = pGC->fillStyle; 130 131 if (mask & GCFillRule) 132 values.fill_rule = pGC->fillRule; 133 134 if (mask & GCTile) { 135 if (pGC->tileIsPixel) 136 mask &= ~GCTile; 137 else 138 values.tile = xnestPixmap(pGC->tile.pixmap); 139 } 140 141 if (mask & GCStipple) 142 values.stipple = xnestPixmap(pGC->stipple); 143 144 if (mask & GCTileStipXOrigin) 145 values.ts_x_origin = pGC->patOrg.x; 146 147 if (mask & GCTileStipYOrigin) 148 values.ts_y_origin = pGC->patOrg.y; 149 150 if (mask & GCFont) 151 values.font = xnestFont(pGC->font); 152 153 if (mask & GCSubwindowMode) 154 values.subwindow_mode = pGC->subWindowMode; 155 156 if (mask & GCGraphicsExposures) 157 values.graphics_exposures = pGC->graphicsExposures; 158 159 if (mask & GCClipXOrigin) 160 values.clip_x_origin = pGC->clipOrg.x; 161 162 if (mask & GCClipYOrigin) 163 values.clip_y_origin = pGC->clipOrg.y; 164 165 if (mask & GCClipMask) /* this is handled in change clip */ 166 mask &= ~GCClipMask; 167 168 if (mask & GCDashOffset) 169 values.dash_offset = pGC->dashOffset; 170 171 if (mask & GCDashList) { 172 mask &= ~GCDashList; 173 XSetDashes(xnestDisplay, xnestGC(pGC), 174 pGC->dashOffset, (char *)pGC->dash, pGC->numInDashList); 175 } 176 177 if (mask & GCArcMode) 178 values.arc_mode = pGC->arcMode; 179 180 if (mask) 181 XChangeGC(xnestDisplay, xnestGC(pGC), mask, &values); 182} 183 184void 185xnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) 186{ 187 XCopyGC(xnestDisplay, xnestGC(pGCSrc), mask, xnestGC(pGCDst)); 188} 189 190void 191xnestDestroyGC(GCPtr pGC) 192{ 193 XFreeGC(xnestDisplay, xnestGC(pGC)); 194} 195 196void 197xnestChangeClip(GCPtr pGC, int type, pointer pValue, int nRects) 198{ 199 int i, size; 200 BoxPtr pBox; 201 XRectangle *pRects; 202 203 xnestDestroyClipHelper(pGC); 204 205 switch(type) 206 { 207 case CT_NONE: 208 XSetClipMask(xnestDisplay, xnestGC(pGC), None); 209 break; 210 211 case CT_REGION: 212 nRects = REGION_NUM_RECTS((RegionPtr)pValue); 213 size = nRects * sizeof(*pRects); 214 pRects = (XRectangle *) xalloc(size); 215 pBox = REGION_RECTS((RegionPtr)pValue); 216 for (i = nRects; i-- > 0; ) { 217 pRects[i].x = pBox[i].x1; 218 pRects[i].y = pBox[i].y1; 219 pRects[i].width = pBox[i].x2 - pBox[i].x1; 220 pRects[i].height = pBox[i].y2 - pBox[i].y1; 221 } 222 XSetClipRectangles(xnestDisplay, xnestGC(pGC), 0, 0, 223 pRects, nRects, Unsorted); 224 xfree((char *) pRects); 225 break; 226 227 case CT_PIXMAP: 228 XSetClipMask(xnestDisplay, xnestGC(pGC), 229 xnestPixmap((PixmapPtr)pValue)); 230 /* 231 * Need to change into region, so subsequent uses are with 232 * current pixmap contents. 233 */ 234 pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr)pValue); 235 (*pGC->pScreen->DestroyPixmap)((PixmapPtr)pValue); 236 pValue = pGC->clientClip; 237 type = CT_REGION; 238 break; 239 240 case CT_UNSORTED: 241 XSetClipRectangles(xnestDisplay, xnestGC(pGC), 242 pGC->clipOrg.x, pGC->clipOrg.y, 243 (XRectangle *)pValue, nRects, Unsorted); 244 break; 245 246 case CT_YSORTED: 247 XSetClipRectangles(xnestDisplay, xnestGC(pGC), 248 pGC->clipOrg.x, pGC->clipOrg.y, 249 (XRectangle *)pValue, nRects, YSorted); 250 break; 251 252 case CT_YXSORTED: 253 XSetClipRectangles(xnestDisplay, xnestGC(pGC), 254 pGC->clipOrg.x, pGC->clipOrg.y, 255 (XRectangle *)pValue, nRects, YXSorted); 256 break; 257 258 case CT_YXBANDED: 259 XSetClipRectangles(xnestDisplay, xnestGC(pGC), 260 pGC->clipOrg.x, pGC->clipOrg.y, 261 (XRectangle *)pValue, nRects, YXBanded); 262 break; 263 } 264 265 switch(type) 266 { 267 default: 268 break; 269 270 case CT_UNSORTED: 271 case CT_YSORTED: 272 case CT_YXSORTED: 273 case CT_YXBANDED: 274 275 /* 276 * other parts of server can only deal with CT_NONE, 277 * CT_PIXMAP and CT_REGION client clips. 278 */ 279 pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nRects, 280 (xRectangle *)pValue, type); 281 xfree(pValue); 282 pValue = pGC->clientClip; 283 type = CT_REGION; 284 285 break; 286 } 287 288 pGC->clientClipType = type; 289 pGC->clientClip = pValue; 290 xnestGCPriv(pGC)->nClipRects = nRects; 291} 292 293void 294xnestDestroyClip(GCPtr pGC) 295{ 296 xnestDestroyClipHelper(pGC); 297 298 XSetClipMask(xnestDisplay, xnestGC(pGC), None); 299 300 pGC->clientClipType = CT_NONE; 301 pGC->clientClip = NULL; 302 xnestGCPriv(pGC)->nClipRects = 0; 303} 304 305void 306xnestDestroyClipHelper(GCPtr pGC) 307{ 308 switch (pGC->clientClipType) 309 { 310 default: 311 case CT_NONE: 312 break; 313 314 case CT_REGION: 315 REGION_DESTROY(pGC->pScreen, pGC->clientClip); 316 break; 317 } 318} 319 320void 321xnestCopyClip(GCPtr pGCDst, GCPtr pGCSrc) 322{ 323 RegionPtr pRgn; 324 325 switch (pGCSrc->clientClipType) 326 { 327 default: 328 case CT_NONE: 329 xnestDestroyClip(pGCDst); 330 break; 331 332 case CT_REGION: 333 pRgn = REGION_CREATE(pGCDst->pScreen, NULL, 1); 334 REGION_COPY(pGCDst->pScreen, pRgn, pGCSrc->clientClip); 335 xnestChangeClip(pGCDst, CT_REGION, pRgn, 0); 336 break; 337 } 338} 339