GC.c revision 35c4bbdf
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
85    return True;
86}
87
88void
89xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
90{
91}
92
93void
94xnestChangeGC(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
178void
179xnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
180{
181    XCopyGC(xnestDisplay, xnestGC(pGCSrc), mask, xnestGC(pGCDst));
182}
183
184void
185xnestDestroyGC(GCPtr pGC)
186{
187    XFreeGC(xnestDisplay, xnestGC(pGC));
188}
189
190void
191xnestChangeClip(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
275void
276xnestDestroyClip(GCPtr pGC)
277{
278    if (pGC->clientClip) {
279        RegionDestroy(pGC->clientClip);
280        XSetClipMask(xnestDisplay, xnestGC(pGC), None);
281        pGC->clientClip = NULL;
282    }
283}
284
285void
286xnestCopyClip(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