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