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