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