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