1 /*
2 
3 Copyright 1993 by Davor Matic
4 
5 Permission to use, copy, modify, distribute, and sell this software
6 and its documentation for any purpose is hereby granted without fee,
7 provided that the above copyright notice appear in all copies and that
8 both that copyright notice and this permission notice appear in
9 supporting documentation.  Davor Matic makes no representations about
10 the suitability of this software for any purpose.  It is provided "as
11 is" 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 
38 DevPrivateKeyRec xnestGCPrivateKeyRec;
39 
40 static GCFuncs xnestFuncs = {
41     xnestValidateGC,
42     xnestChangeGC,
43     xnestCopyGC,
44     xnestDestroyGC,
45     xnestChangeClip,
46     xnestDestroyClip,
47     xnestCopyClip,
48 };
49 
50 static 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 
73 Bool
xnestCreateGC(GCPtr pGC)74 xnestCreateGC(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 
85     return True;
86 }
87 
88 void
xnestValidateGC(GCPtr pGC,unsigned long changes,DrawablePtr pDrawable)89 xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
90 {
91 }
92 
93 void
xnestChangeGC(GCPtr pGC,unsigned long mask)94 xnestChangeGC(GCPtr pGC, unsigned long mask)
95 {
96     XGCValues values;
97 
98     if (mask & GCFunction)
99         values.function = pGC->alu;
100 
101     if (mask & GCPlaneMask)
102         values.plane_mask = pGC->planemask;
103 
104     if (mask & GCForeground)
105         values.foreground = xnestPixel(pGC->fgPixel);
106 
107     if (mask & GCBackground)
108         values.background = xnestPixel(pGC->bgPixel);
109 
110     if (mask & GCLineWidth)
111         values.line_width = pGC->lineWidth;
112 
113     if (mask & GCLineStyle)
114         values.line_style = pGC->lineStyle;
115 
116     if (mask & GCCapStyle)
117         values.cap_style = pGC->capStyle;
118 
119     if (mask & GCJoinStyle)
120         values.join_style = pGC->joinStyle;
121 
122     if (mask & GCFillStyle)
123         values.fill_style = pGC->fillStyle;
124 
125     if (mask & GCFillRule)
126         values.fill_rule = pGC->fillRule;
127 
128     if (mask & GCTile) {
129         if (pGC->tileIsPixel)
130             mask &= ~GCTile;
131         else
132             values.tile = xnestPixmap(pGC->tile.pixmap);
133     }
134 
135     if (mask & GCStipple)
136         values.stipple = xnestPixmap(pGC->stipple);
137 
138     if (mask & GCTileStipXOrigin)
139         values.ts_x_origin = pGC->patOrg.x;
140 
141     if (mask & GCTileStipYOrigin)
142         values.ts_y_origin = pGC->patOrg.y;
143 
144     if (mask & GCFont)
145         values.font = xnestFont(pGC->font);
146 
147     if (mask & GCSubwindowMode)
148         values.subwindow_mode = pGC->subWindowMode;
149 
150     if (mask & GCGraphicsExposures)
151         values.graphics_exposures = pGC->graphicsExposures;
152 
153     if (mask & GCClipXOrigin)
154         values.clip_x_origin = pGC->clipOrg.x;
155 
156     if (mask & GCClipYOrigin)
157         values.clip_y_origin = pGC->clipOrg.y;
158 
159     if (mask & GCClipMask)      /* this is handled in change clip */
160         mask &= ~GCClipMask;
161 
162     if (mask & GCDashOffset)
163         values.dash_offset = pGC->dashOffset;
164 
165     if (mask & GCDashList) {
166         mask &= ~GCDashList;
167         XSetDashes(xnestDisplay, xnestGC(pGC),
168                    pGC->dashOffset, (char *) pGC->dash, pGC->numInDashList);
169     }
170 
171     if (mask & GCArcMode)
172         values.arc_mode = pGC->arcMode;
173 
174     if (mask)
175         XChangeGC(xnestDisplay, xnestGC(pGC), mask, &values);
176 }
177 
178 void
xnestCopyGC(GCPtr pGCSrc,unsigned long mask,GCPtr pGCDst)179 xnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
180 {
181     XCopyGC(xnestDisplay, xnestGC(pGCSrc), mask, xnestGC(pGCDst));
182 }
183 
184 void
xnestDestroyGC(GCPtr pGC)185 xnestDestroyGC(GCPtr pGC)
186 {
187     XFreeGC(xnestDisplay, xnestGC(pGC));
188 }
189 
190 void
xnestChangeClip(GCPtr pGC,int type,void * pValue,int nRects)191 xnestChangeClip(GCPtr pGC, int type, void *pValue, int nRects)
192 {
193     int i;
194     BoxPtr pBox;
195     XRectangle *pRects;
196 
197     xnestDestroyClip(pGC);
198 
199     switch (type) {
200     case CT_NONE:
201         XSetClipMask(xnestDisplay, xnestGC(pGC), None);
202         pValue = NULL;
203         break;
204 
205     case CT_REGION:
206         nRects = RegionNumRects((RegionPtr) pValue);
207         pRects = xallocarray(nRects, sizeof(*pRects));
208         pBox = RegionRects((RegionPtr) pValue);
209         for (i = nRects; i-- > 0;) {
210             pRects[i].x = pBox[i].x1;
211             pRects[i].y = pBox[i].y1;
212             pRects[i].width = pBox[i].x2 - pBox[i].x1;
213             pRects[i].height = pBox[i].y2 - pBox[i].y1;
214         }
215         XSetClipRectangles(xnestDisplay, xnestGC(pGC), 0, 0,
216                            pRects, nRects, Unsorted);
217         free((char *) pRects);
218         break;
219 
220     case CT_PIXMAP:
221         XSetClipMask(xnestDisplay, xnestGC(pGC),
222                      xnestPixmap((PixmapPtr) pValue));
223         /*
224          * Need to change into region, so subsequent uses are with
225          * current pixmap contents.
226          */
227         pGC->clientClip = (*pGC->pScreen->BitmapToRegion) ((PixmapPtr) pValue);
228         (*pGC->pScreen->DestroyPixmap) ((PixmapPtr) pValue);
229         pValue = pGC->clientClip;
230         break;
231 
232     case CT_UNSORTED:
233         XSetClipRectangles(xnestDisplay, xnestGC(pGC),
234                            pGC->clipOrg.x, pGC->clipOrg.y,
235                            (XRectangle *) pValue, nRects, Unsorted);
236         break;
237 
238     case CT_YSORTED:
239         XSetClipRectangles(xnestDisplay, xnestGC(pGC),
240                            pGC->clipOrg.x, pGC->clipOrg.y,
241                            (XRectangle *) pValue, nRects, YSorted);
242         break;
243 
244     case CT_YXSORTED:
245         XSetClipRectangles(xnestDisplay, xnestGC(pGC),
246                            pGC->clipOrg.x, pGC->clipOrg.y,
247                            (XRectangle *) pValue, nRects, YXSorted);
248         break;
249 
250     case CT_YXBANDED:
251         XSetClipRectangles(xnestDisplay, xnestGC(pGC),
252                            pGC->clipOrg.x, pGC->clipOrg.y,
253                            (XRectangle *) pValue, nRects, YXBanded);
254         break;
255     }
256 
257     switch (type) {
258     default:
259         break;
260 
261     case CT_UNSORTED:
262     case CT_YSORTED:
263     case CT_YXSORTED:
264     case CT_YXBANDED:
265         /* server clip representation is a region */
266         pGC->clientClip = RegionFromRects(nRects, (xRectangle *) pValue, type);
267         free(pValue);
268         pValue = pGC->clientClip;
269         break;
270     }
271 
272     pGC->clientClip = pValue;
273 }
274 
275 void
xnestDestroyClip(GCPtr pGC)276 xnestDestroyClip(GCPtr pGC)
277 {
278     if (pGC->clientClip) {
279         RegionDestroy(pGC->clientClip);
280         XSetClipMask(xnestDisplay, xnestGC(pGC), None);
281         pGC->clientClip = NULL;
282     }
283 }
284 
285 void
xnestCopyClip(GCPtr pGCDst,GCPtr pGCSrc)286 xnestCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
287 {
288     if (pGCSrc->clientClip) {
289         RegionPtr pRgn = RegionCreate(NULL, 1);
290         RegionCopy(pRgn, pGCSrc->clientClip);
291         xnestChangeClip(pGCDst, CT_REGION, pRgn, 0);
292     } else {
293         xnestDestroyClip(pGCDst);
294     }
295 }
296