1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Graphics Context support for generic rootless X server
3*4882a593Smuzhiyun */
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun * Copyright (c) 2001 Greg Parker. All Rights Reserved.
6*4882a593Smuzhiyun * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
7*4882a593Smuzhiyun * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
10*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
11*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
12*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
14*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
17*4882a593Smuzhiyun * all copies or substantial portions of the Software.
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22*4882a593Smuzhiyun * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23*4882a593Smuzhiyun * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24*4882a593Smuzhiyun * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25*4882a593Smuzhiyun * DEALINGS IN THE SOFTWARE.
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun * Except as contained in this notice, the name(s) of the above copyright
28*4882a593Smuzhiyun * holders shall not be used in advertising or otherwise to promote the sale,
29*4882a593Smuzhiyun * use or other dealings in this Software without prior written authorization.
30*4882a593Smuzhiyun */
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
33*4882a593Smuzhiyun #include <dix-config.h>
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #include <stddef.h> /* For NULL */
37*4882a593Smuzhiyun #include "mi.h"
38*4882a593Smuzhiyun #include "scrnintstr.h"
39*4882a593Smuzhiyun #include "gcstruct.h"
40*4882a593Smuzhiyun #include "pixmapstr.h"
41*4882a593Smuzhiyun #include "windowstr.h"
42*4882a593Smuzhiyun #include "dixfontstr.h"
43*4882a593Smuzhiyun #include "mivalidate.h"
44*4882a593Smuzhiyun #include "fb.h"
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #include <sys/types.h>
47*4882a593Smuzhiyun #include <sys/stat.h>
48*4882a593Smuzhiyun #include <fcntl.h>
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #include "rootlessCommon.h"
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun // GC functions
53*4882a593Smuzhiyun static void RootlessValidateGC(GCPtr pGC, unsigned long changes,
54*4882a593Smuzhiyun DrawablePtr pDrawable);
55*4882a593Smuzhiyun static void RootlessChangeGC(GCPtr pGC, unsigned long mask);
56*4882a593Smuzhiyun static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
57*4882a593Smuzhiyun static void RootlessDestroyGC(GCPtr pGC);
58*4882a593Smuzhiyun static void RootlessChangeClip(GCPtr pGC, int type, void *pvalue, int nrects);
59*4882a593Smuzhiyun static void RootlessDestroyClip(GCPtr pGC);
60*4882a593Smuzhiyun static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun Bool RootlessCreateGC(GCPtr pGC);
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun GCFuncs rootlessGCFuncs = {
65*4882a593Smuzhiyun RootlessValidateGC,
66*4882a593Smuzhiyun RootlessChangeGC,
67*4882a593Smuzhiyun RootlessCopyGC,
68*4882a593Smuzhiyun RootlessDestroyGC,
69*4882a593Smuzhiyun RootlessChangeClip,
70*4882a593Smuzhiyun RootlessDestroyClip,
71*4882a593Smuzhiyun RootlessCopyClip,
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun // GC operations
75*4882a593Smuzhiyun static void RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
76*4882a593Smuzhiyun DDXPointPtr pptInit, int *pwidthInit, int sorted);
77*4882a593Smuzhiyun static void RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
78*4882a593Smuzhiyun DDXPointPtr pptInit, int *pwidthInit,
79*4882a593Smuzhiyun int nspans, int sorted);
80*4882a593Smuzhiyun static void RootlessPutImage(DrawablePtr dst, GCPtr pGC,
81*4882a593Smuzhiyun int depth, int x, int y, int w, int h,
82*4882a593Smuzhiyun int leftPad, int format, char *pBits);
83*4882a593Smuzhiyun static RegionPtr RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
84*4882a593Smuzhiyun int srcx, int srcy, int w, int h,
85*4882a593Smuzhiyun int dstx, int dsty);
86*4882a593Smuzhiyun static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
87*4882a593Smuzhiyun GCPtr pGC, int srcx, int srcy,
88*4882a593Smuzhiyun int w, int h, int dstx, int dsty,
89*4882a593Smuzhiyun unsigned long plane);
90*4882a593Smuzhiyun static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
91*4882a593Smuzhiyun int mode, int npt, DDXPointPtr pptInit);
92*4882a593Smuzhiyun static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
93*4882a593Smuzhiyun int mode, int npt, DDXPointPtr pptInit);
94*4882a593Smuzhiyun static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
95*4882a593Smuzhiyun int nseg, xSegment * pSeg);
96*4882a593Smuzhiyun static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
97*4882a593Smuzhiyun int nRects, xRectangle *pRects);
98*4882a593Smuzhiyun static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs,
99*4882a593Smuzhiyun xArc * parcs);
100*4882a593Smuzhiyun static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC, int shape, int mode,
101*4882a593Smuzhiyun int count, DDXPointPtr pptInit);
102*4882a593Smuzhiyun static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC, int nRectsInit,
103*4882a593Smuzhiyun xRectangle *pRectsInit);
104*4882a593Smuzhiyun static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, int narcsInit,
105*4882a593Smuzhiyun xArc * parcsInit);
106*4882a593Smuzhiyun static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC, int x, int y,
107*4882a593Smuzhiyun int count, char *chars);
108*4882a593Smuzhiyun static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC, int x, int y,
109*4882a593Smuzhiyun int count, unsigned short *chars);
110*4882a593Smuzhiyun static void RootlessImageText8(DrawablePtr dst, GCPtr pGC, int x, int y,
111*4882a593Smuzhiyun int count, char *chars);
112*4882a593Smuzhiyun static void RootlessImageText16(DrawablePtr dst, GCPtr pGC, int x, int y,
113*4882a593Smuzhiyun int count, unsigned short *chars);
114*4882a593Smuzhiyun static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC, int x, int y,
115*4882a593Smuzhiyun unsigned int nglyphInit,
116*4882a593Smuzhiyun CharInfoPtr * ppciInit, void *unused);
117*4882a593Smuzhiyun static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, int x, int y,
118*4882a593Smuzhiyun unsigned int nglyph, CharInfoPtr * ppci,
119*4882a593Smuzhiyun void *pglyphBase);
120*4882a593Smuzhiyun static void RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
121*4882a593Smuzhiyun int dx, int dy, int xOrg, int yOrg);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun static GCOps rootlessGCOps = {
124*4882a593Smuzhiyun RootlessFillSpans,
125*4882a593Smuzhiyun RootlessSetSpans,
126*4882a593Smuzhiyun RootlessPutImage,
127*4882a593Smuzhiyun RootlessCopyArea,
128*4882a593Smuzhiyun RootlessCopyPlane,
129*4882a593Smuzhiyun RootlessPolyPoint,
130*4882a593Smuzhiyun RootlessPolylines,
131*4882a593Smuzhiyun RootlessPolySegment,
132*4882a593Smuzhiyun RootlessPolyRectangle,
133*4882a593Smuzhiyun RootlessPolyArc,
134*4882a593Smuzhiyun RootlessFillPolygon,
135*4882a593Smuzhiyun RootlessPolyFillRect,
136*4882a593Smuzhiyun RootlessPolyFillArc,
137*4882a593Smuzhiyun RootlessPolyText8,
138*4882a593Smuzhiyun RootlessPolyText16,
139*4882a593Smuzhiyun RootlessImageText8,
140*4882a593Smuzhiyun RootlessImageText16,
141*4882a593Smuzhiyun RootlessImageGlyphBlt,
142*4882a593Smuzhiyun RootlessPolyGlyphBlt,
143*4882a593Smuzhiyun RootlessPushPixels
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /*
147*4882a593Smuzhiyun If ROOTLESS_PROTECT_ALPHA is set, we have to make sure that the alpha
148*4882a593Smuzhiyun channel of the on screen windows is always opaque. fb makes this harder
149*4882a593Smuzhiyun than it would otherwise be by noticing that a planemask of 0x00ffffff
150*4882a593Smuzhiyun includes all bits when depth==24, and so it "optimizes" the planemask to
151*4882a593Smuzhiyun 0xffffffff. We work around this by temporarily setting depth=bpp while
152*4882a593Smuzhiyun changing the GC.
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun So the normal situation (in 32 bit mode) is that the planemask is
155*4882a593Smuzhiyun 0x00ffffff and thus fb leaves the alpha channel alone. The rootless
156*4882a593Smuzhiyun implementation is responsible for setting the alpha channel opaque
157*4882a593Smuzhiyun initially.
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun Unfortunately drawing with a planemask that doesn't have all bits set
160*4882a593Smuzhiyun normally causes fb to fall off its fastest paths when blitting and
161*4882a593Smuzhiyun filling. So we try to recognize when we can relax the planemask back to
162*4882a593Smuzhiyun 0xffffffff, and do that for the duration of the drawing operation,
163*4882a593Smuzhiyun setting the alpha channel in fg/bg pixels to opaque at the same time. We
164*4882a593Smuzhiyun can do this when drawing op is GXcopy. We can also do this when copying
165*4882a593Smuzhiyun from another window since its alpha channel must also be opaque.
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun The three macros below are used to implement this. Drawing ops that can
168*4882a593Smuzhiyun potentially have their planemask relaxed look like:
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun OP {
171*4882a593Smuzhiyun GC_SAVE(gc);
172*4882a593Smuzhiyun GCOP_UNWRAP(gc);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun ...
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun if (canAccelxxx(..) && otherwise-suitable)
177*4882a593Smuzhiyun GC_UNSET_PM(gc, dst);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun gc->funcs->OP(gc, ...);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun GC_RESTORE(gc, dst);
182*4882a593Smuzhiyun GCOP_WRAP(gc);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun */
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun #define GC_SAVE(pGC) \
188*4882a593Smuzhiyun unsigned long _save_fg = (pGC)->fgPixel; \
189*4882a593Smuzhiyun unsigned long _save_bg = (pGC)->bgPixel; \
190*4882a593Smuzhiyun unsigned long _save_pm = (pGC)->planemask; \
191*4882a593Smuzhiyun Bool _changed = FALSE
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun #define GC_RESTORE(pGC, pDraw) \
194*4882a593Smuzhiyun do { \
195*4882a593Smuzhiyun if (_changed) { \
196*4882a593Smuzhiyun unsigned int depth = (pDraw)->depth; \
197*4882a593Smuzhiyun (pGC)->fgPixel = _save_fg; \
198*4882a593Smuzhiyun (pGC)->bgPixel = _save_bg; \
199*4882a593Smuzhiyun (pGC)->planemask = _save_pm; \
200*4882a593Smuzhiyun (pDraw)->depth = (pDraw)->bitsPerPixel; \
201*4882a593Smuzhiyun VALIDATE_GC(pGC, GCForeground | GCBackground | \
202*4882a593Smuzhiyun GCPlaneMask, pDraw); \
203*4882a593Smuzhiyun (pDraw)->depth = depth; \
204*4882a593Smuzhiyun } \
205*4882a593Smuzhiyun } while (0)
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun #define GC_UNSET_PM(pGC, pDraw) \
208*4882a593Smuzhiyun do { \
209*4882a593Smuzhiyun unsigned int mask = RootlessAlphaMask ((pDraw)->bitsPerPixel); \
210*4882a593Smuzhiyun if (((pGC)->planemask & mask) != mask) { \
211*4882a593Smuzhiyun unsigned int depth = (pDraw)->depth; \
212*4882a593Smuzhiyun (pGC)->fgPixel |= mask; \
213*4882a593Smuzhiyun (pGC)->bgPixel |= mask; \
214*4882a593Smuzhiyun (pGC)->planemask |= mask; \
215*4882a593Smuzhiyun (pDraw)->depth = (pDraw)->bitsPerPixel; \
216*4882a593Smuzhiyun VALIDATE_GC(pGC, GCForeground | \
217*4882a593Smuzhiyun GCBackground | GCPlaneMask, pDraw); \
218*4882a593Smuzhiyun (pDraw)->depth = depth; \
219*4882a593Smuzhiyun _changed = TRUE; \
220*4882a593Smuzhiyun } \
221*4882a593Smuzhiyun } while (0)
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun #define VALIDATE_GC(pGC, changes, pDrawable) \
224*4882a593Smuzhiyun do { \
225*4882a593Smuzhiyun pGC->funcs->ValidateGC(pGC, changes, pDrawable); \
226*4882a593Smuzhiyun if (((WindowPtr) pDrawable)->viewable) { \
227*4882a593Smuzhiyun gcrec->originalOps = pGC->ops; \
228*4882a593Smuzhiyun } \
229*4882a593Smuzhiyun } while(0)
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun static RootlessWindowRec *
canAccelBlit(DrawablePtr pDraw,GCPtr pGC)232*4882a593Smuzhiyun canAccelBlit(DrawablePtr pDraw, GCPtr pGC)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun WindowPtr pTop;
235*4882a593Smuzhiyun RootlessWindowRec *winRec;
236*4882a593Smuzhiyun unsigned int pm;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun if (pGC->alu != GXcopy)
239*4882a593Smuzhiyun return NULL;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun if (pDraw->type != DRAWABLE_WINDOW)
242*4882a593Smuzhiyun return NULL;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun pm = ~RootlessAlphaMask(pDraw->bitsPerPixel);
245*4882a593Smuzhiyun if ((pGC->planemask & pm) != pm)
246*4882a593Smuzhiyun return NULL;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun pTop = TopLevelParent((WindowPtr) pDraw);
249*4882a593Smuzhiyun if (pTop == NULL)
250*4882a593Smuzhiyun return NULL;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun winRec = WINREC(pTop);
253*4882a593Smuzhiyun if (winRec == NULL)
254*4882a593Smuzhiyun return NULL;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun return winRec;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun static inline RootlessWindowRec *
canAccelFill(DrawablePtr pDraw,GCPtr pGC)260*4882a593Smuzhiyun canAccelFill(DrawablePtr pDraw, GCPtr pGC)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun if (pGC->fillStyle != FillSolid)
263*4882a593Smuzhiyun return NULL;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun return canAccelBlit(pDraw, pGC);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun /*
269*4882a593Smuzhiyun * Screen function to create a graphics context
270*4882a593Smuzhiyun */
271*4882a593Smuzhiyun Bool
RootlessCreateGC(GCPtr pGC)272*4882a593Smuzhiyun RootlessCreateGC(GCPtr pGC)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun RootlessGCRec *gcrec;
275*4882a593Smuzhiyun RootlessScreenRec *s;
276*4882a593Smuzhiyun Bool result;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun SCREEN_UNWRAP(pGC->pScreen, CreateGC);
279*4882a593Smuzhiyun s = SCREENREC(pGC->pScreen);
280*4882a593Smuzhiyun result = s->CreateGC(pGC);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun gcrec = (RootlessGCRec *)
283*4882a593Smuzhiyun dixLookupPrivate(&pGC->devPrivates, rootlessGCPrivateKey);
284*4882a593Smuzhiyun gcrec->originalOps = NULL; // don't wrap ops yet
285*4882a593Smuzhiyun gcrec->originalFuncs = pGC->funcs;
286*4882a593Smuzhiyun pGC->funcs = &rootlessGCFuncs;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun SCREEN_WRAP(pGC->pScreen, CreateGC);
289*4882a593Smuzhiyun return result;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /*
293*4882a593Smuzhiyun * GC funcs
294*4882a593Smuzhiyun *
295*4882a593Smuzhiyun * These wrap lower level GC funcs.
296*4882a593Smuzhiyun * ValidateGC wraps the GC ops iff dest is viewable.
297*4882a593Smuzhiyun * All the others just unwrap and call.
298*4882a593Smuzhiyun */
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun // GCFUNC_UNRAP assumes funcs have been wrapped and
301*4882a593Smuzhiyun // does not assume ops have been wrapped
302*4882a593Smuzhiyun #define GCFUNC_UNWRAP(pGC) \
303*4882a593Smuzhiyun RootlessGCRec *gcrec = (RootlessGCRec *) \
304*4882a593Smuzhiyun dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \
305*4882a593Smuzhiyun (pGC)->funcs = gcrec->originalFuncs; \
306*4882a593Smuzhiyun if (gcrec->originalOps) { \
307*4882a593Smuzhiyun (pGC)->ops = gcrec->originalOps; \
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun #define GCFUNC_WRAP(pGC) \
311*4882a593Smuzhiyun gcrec->originalFuncs = (pGC)->funcs; \
312*4882a593Smuzhiyun (pGC)->funcs = &rootlessGCFuncs; \
313*4882a593Smuzhiyun if (gcrec->originalOps) { \
314*4882a593Smuzhiyun gcrec->originalOps = (pGC)->ops; \
315*4882a593Smuzhiyun (pGC)->ops = &rootlessGCOps; \
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun static void
RootlessValidateGC(GCPtr pGC,unsigned long changes,DrawablePtr pDrawable)319*4882a593Smuzhiyun RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun GCFUNC_UNWRAP(pGC);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun gcrec->originalOps = NULL;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (pDrawable->type == DRAWABLE_WINDOW) {
326*4882a593Smuzhiyun #ifdef ROOTLESS_PROTECT_ALPHA
327*4882a593Smuzhiyun unsigned int depth = pDrawable->depth;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun // We force a planemask so fb doesn't overwrite the alpha channel.
330*4882a593Smuzhiyun // Left to its own devices, fb will optimize away the planemask.
331*4882a593Smuzhiyun pDrawable->depth = pDrawable->bitsPerPixel;
332*4882a593Smuzhiyun pGC->planemask &= ~RootlessAlphaMask(pDrawable->bitsPerPixel);
333*4882a593Smuzhiyun VALIDATE_GC(pGC, changes | GCPlaneMask, pDrawable);
334*4882a593Smuzhiyun pDrawable->depth = depth;
335*4882a593Smuzhiyun #else
336*4882a593Smuzhiyun VALIDATE_GC(pGC, changes, pDrawable);
337*4882a593Smuzhiyun #endif
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun else {
340*4882a593Smuzhiyun pGC->funcs->ValidateGC(pGC, changes, pDrawable);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun GCFUNC_WRAP(pGC);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun static void
RootlessChangeGC(GCPtr pGC,unsigned long mask)347*4882a593Smuzhiyun RootlessChangeGC(GCPtr pGC, unsigned long mask)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun GCFUNC_UNWRAP(pGC);
350*4882a593Smuzhiyun pGC->funcs->ChangeGC(pGC, mask);
351*4882a593Smuzhiyun GCFUNC_WRAP(pGC);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun static void
RootlessCopyGC(GCPtr pGCSrc,unsigned long mask,GCPtr pGCDst)355*4882a593Smuzhiyun RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun GCFUNC_UNWRAP(pGCDst);
358*4882a593Smuzhiyun pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst);
359*4882a593Smuzhiyun GCFUNC_WRAP(pGCDst);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun static void
RootlessDestroyGC(GCPtr pGC)363*4882a593Smuzhiyun RootlessDestroyGC(GCPtr pGC)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun GCFUNC_UNWRAP(pGC);
366*4882a593Smuzhiyun pGC->funcs->DestroyGC(pGC);
367*4882a593Smuzhiyun GCFUNC_WRAP(pGC);
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun static void
RootlessChangeClip(GCPtr pGC,int type,void * pvalue,int nrects)371*4882a593Smuzhiyun RootlessChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun GCFUNC_UNWRAP(pGC);
374*4882a593Smuzhiyun pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
375*4882a593Smuzhiyun GCFUNC_WRAP(pGC);
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun static void
RootlessDestroyClip(GCPtr pGC)379*4882a593Smuzhiyun RootlessDestroyClip(GCPtr pGC)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun GCFUNC_UNWRAP(pGC);
382*4882a593Smuzhiyun pGC->funcs->DestroyClip(pGC);
383*4882a593Smuzhiyun GCFUNC_WRAP(pGC);
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun static void
RootlessCopyClip(GCPtr pgcDst,GCPtr pgcSrc)387*4882a593Smuzhiyun RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun GCFUNC_UNWRAP(pgcDst);
390*4882a593Smuzhiyun pgcDst->funcs->CopyClip(pgcDst, pgcSrc);
391*4882a593Smuzhiyun GCFUNC_WRAP(pgcDst);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun /*
395*4882a593Smuzhiyun * GC ops
396*4882a593Smuzhiyun *
397*4882a593Smuzhiyun * We can't use shadowfb because shadowfb assumes one pixmap
398*4882a593Smuzhiyun * and our root window is a special case.
399*4882a593Smuzhiyun * However, much of this code is copied from shadowfb.
400*4882a593Smuzhiyun */
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun // assumes both funcs and ops are wrapped
403*4882a593Smuzhiyun #define GCOP_UNWRAP(pGC) \
404*4882a593Smuzhiyun RootlessGCRec *gcrec = (RootlessGCRec *) \
405*4882a593Smuzhiyun dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \
406*4882a593Smuzhiyun const GCFuncs *saveFuncs = pGC->funcs; \
407*4882a593Smuzhiyun (pGC)->funcs = gcrec->originalFuncs; \
408*4882a593Smuzhiyun (pGC)->ops = gcrec->originalOps;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun #define GCOP_WRAP(pGC) \
411*4882a593Smuzhiyun gcrec->originalOps = (pGC)->ops; \
412*4882a593Smuzhiyun (pGC)->funcs = saveFuncs; \
413*4882a593Smuzhiyun (pGC)->ops = &rootlessGCOps;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun static void
RootlessFillSpans(DrawablePtr dst,GCPtr pGC,int nInit,DDXPointPtr pptInit,int * pwidthInit,int sorted)416*4882a593Smuzhiyun RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
417*4882a593Smuzhiyun DDXPointPtr pptInit, int *pwidthInit, int sorted)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun GC_SAVE(pGC);
420*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
421*4882a593Smuzhiyun RL_DEBUG_MSG("fill spans start ");
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun if (nInit <= 0) {
424*4882a593Smuzhiyun pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun else {
427*4882a593Smuzhiyun DDXPointPtr ppt = pptInit;
428*4882a593Smuzhiyun int *pwidth = pwidthInit;
429*4882a593Smuzhiyun int i = nInit;
430*4882a593Smuzhiyun BoxRec box;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun box.x1 = ppt->x;
433*4882a593Smuzhiyun box.x2 = box.x1 + *pwidth;
434*4882a593Smuzhiyun box.y2 = box.y1 = ppt->y;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun while (--i) {
437*4882a593Smuzhiyun ppt++;
438*4882a593Smuzhiyun pwidth++;
439*4882a593Smuzhiyun if (box.x1 > ppt->x)
440*4882a593Smuzhiyun box.x1 = ppt->x;
441*4882a593Smuzhiyun if (box.x2 < (ppt->x + *pwidth))
442*4882a593Smuzhiyun box.x2 = ppt->x + *pwidth;
443*4882a593Smuzhiyun if (box.y1 > ppt->y)
444*4882a593Smuzhiyun box.y1 = ppt->y;
445*4882a593Smuzhiyun else if (box.y2 < ppt->y)
446*4882a593Smuzhiyun box.y2 = ppt->y;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun box.y2++;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun if (canAccelFill(dst, pGC)) {
454*4882a593Smuzhiyun GC_UNSET_PM(pGC, dst);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
460*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
461*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun GC_RESTORE(pGC, dst);
465*4882a593Smuzhiyun GCOP_WRAP(pGC);
466*4882a593Smuzhiyun RL_DEBUG_MSG("fill spans end\n");
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun static void
RootlessSetSpans(DrawablePtr dst,GCPtr pGC,char * pSrc,DDXPointPtr pptInit,int * pwidthInit,int nspans,int sorted)470*4882a593Smuzhiyun RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
471*4882a593Smuzhiyun DDXPointPtr pptInit, int *pwidthInit, int nspans, int sorted)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
474*4882a593Smuzhiyun RL_DEBUG_MSG("set spans start ");
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun if (nspans <= 0) {
477*4882a593Smuzhiyun pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun else {
480*4882a593Smuzhiyun DDXPointPtr ppt = pptInit;
481*4882a593Smuzhiyun int *pwidth = pwidthInit;
482*4882a593Smuzhiyun int i = nspans;
483*4882a593Smuzhiyun BoxRec box;
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun box.x1 = ppt->x;
486*4882a593Smuzhiyun box.x2 = box.x1 + *pwidth;
487*4882a593Smuzhiyun box.y2 = box.y1 = ppt->y;
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun while (--i) {
490*4882a593Smuzhiyun ppt++;
491*4882a593Smuzhiyun pwidth++;
492*4882a593Smuzhiyun if (box.x1 > ppt->x)
493*4882a593Smuzhiyun box.x1 = ppt->x;
494*4882a593Smuzhiyun if (box.x2 < (ppt->x + *pwidth))
495*4882a593Smuzhiyun box.x2 = ppt->x + *pwidth;
496*4882a593Smuzhiyun if (box.y1 > ppt->y)
497*4882a593Smuzhiyun box.y1 = ppt->y;
498*4882a593Smuzhiyun else if (box.y2 < ppt->y)
499*4882a593Smuzhiyun box.y2 = ppt->y;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun box.y2++;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
505*4882a593Smuzhiyun pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted);
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
508*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
509*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun GCOP_WRAP(pGC);
512*4882a593Smuzhiyun RL_DEBUG_MSG("set spans end\n");
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun static void
RootlessPutImage(DrawablePtr dst,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * pBits)516*4882a593Smuzhiyun RootlessPutImage(DrawablePtr dst, GCPtr pGC,
517*4882a593Smuzhiyun int depth, int x, int y, int w, int h,
518*4882a593Smuzhiyun int leftPad, int format, char *pBits)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun BoxRec box;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
523*4882a593Smuzhiyun RL_DEBUG_MSG("put image start ");
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
526*4882a593Smuzhiyun pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits);
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun box.x1 = x + dst->x;
529*4882a593Smuzhiyun box.x2 = box.x1 + w;
530*4882a593Smuzhiyun box.y1 = y + dst->y;
531*4882a593Smuzhiyun box.y2 = box.y1 + h;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun TRIM_BOX(box, pGC);
534*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
535*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun GCOP_WRAP(pGC);
538*4882a593Smuzhiyun RL_DEBUG_MSG("put image end\n");
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun /* changed area is *dest* rect */
542*4882a593Smuzhiyun static RegionPtr
RootlessCopyArea(DrawablePtr pSrc,DrawablePtr dst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty)543*4882a593Smuzhiyun RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
544*4882a593Smuzhiyun int srcx, int srcy, int w, int h, int dstx, int dsty)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun RegionPtr result;
547*4882a593Smuzhiyun BoxRec box;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun GC_SAVE(pGC);
550*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) {
555*4882a593Smuzhiyun /* If both source and dest are windows, and we're doing
556*4882a593Smuzhiyun a simple copy operation, we can remove the alpha-protecting
557*4882a593Smuzhiyun planemask (since source has opaque alpha as well) */
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun if (canAccelBlit(pSrc, pGC)) {
560*4882a593Smuzhiyun GC_UNSET_PM(pGC, dst);
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) pSrc);
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
566*4882a593Smuzhiyun result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty);
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun box.x1 = dstx + dst->x;
569*4882a593Smuzhiyun box.x2 = box.x1 + w;
570*4882a593Smuzhiyun box.y1 = dsty + dst->y;
571*4882a593Smuzhiyun box.y2 = box.y1 + h;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun TRIM_BOX(box, pGC);
574*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
575*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun GC_RESTORE(pGC, dst);
578*4882a593Smuzhiyun GCOP_WRAP(pGC);
579*4882a593Smuzhiyun RL_DEBUG_MSG("copy area end\n");
580*4882a593Smuzhiyun return result;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun /* changed area is *dest* rect */
584*4882a593Smuzhiyun static RegionPtr
RootlessCopyPlane(DrawablePtr pSrc,DrawablePtr dst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty,unsigned long plane)585*4882a593Smuzhiyun RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
586*4882a593Smuzhiyun GCPtr pGC, int srcx, int srcy,
587*4882a593Smuzhiyun int w, int h, int dstx, int dsty, unsigned long plane)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun RegionPtr result;
590*4882a593Smuzhiyun BoxRec box;
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun RL_DEBUG_MSG("copy plane start ");
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) {
597*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) pSrc);
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
600*4882a593Smuzhiyun result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h,
601*4882a593Smuzhiyun dstx, dsty, plane);
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun box.x1 = dstx + dst->x;
604*4882a593Smuzhiyun box.x2 = box.x1 + w;
605*4882a593Smuzhiyun box.y1 = dsty + dst->y;
606*4882a593Smuzhiyun box.y2 = box.y1 + h;
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun TRIM_BOX(box, pGC);
609*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
610*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun GCOP_WRAP(pGC);
613*4882a593Smuzhiyun RL_DEBUG_MSG("copy plane end\n");
614*4882a593Smuzhiyun return result;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun // Options for size of changed area:
618*4882a593Smuzhiyun // 0 = box per point
619*4882a593Smuzhiyun // 1 = big box around all points
620*4882a593Smuzhiyun // 2 = accumulate point in 20 pixel radius
621*4882a593Smuzhiyun #define ROOTLESS_CHANGED_AREA 1
622*4882a593Smuzhiyun #define abs(a) ((a) > 0 ? (a) : -(a))
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun /* changed area is box around all points */
625*4882a593Smuzhiyun static void
RootlessPolyPoint(DrawablePtr dst,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)626*4882a593Smuzhiyun RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
627*4882a593Smuzhiyun int mode, int npt, DDXPointPtr pptInit)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
630*4882a593Smuzhiyun RL_DEBUG_MSG("polypoint start ");
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
633*4882a593Smuzhiyun pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun if (npt > 0) {
636*4882a593Smuzhiyun #if ROOTLESS_CHANGED_AREA==0
637*4882a593Smuzhiyun // box per point
638*4882a593Smuzhiyun BoxRec box;
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun while (npt) {
641*4882a593Smuzhiyun box.x1 = pptInit->x;
642*4882a593Smuzhiyun box.y1 = pptInit->y;
643*4882a593Smuzhiyun box.x2 = box.x1 + 1;
644*4882a593Smuzhiyun box.y2 = box.y1 + 1;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
647*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
648*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun npt--;
651*4882a593Smuzhiyun pptInit++;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun #elif ROOTLESS_CHANGED_AREA==1
655*4882a593Smuzhiyun // one big box
656*4882a593Smuzhiyun BoxRec box;
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun box.x2 = box.x1 = pptInit->x;
659*4882a593Smuzhiyun box.y2 = box.y1 = pptInit->y;
660*4882a593Smuzhiyun while (--npt) {
661*4882a593Smuzhiyun pptInit++;
662*4882a593Smuzhiyun if (box.x1 > pptInit->x)
663*4882a593Smuzhiyun box.x1 = pptInit->x;
664*4882a593Smuzhiyun else if (box.x2 < pptInit->x)
665*4882a593Smuzhiyun box.x2 = pptInit->x;
666*4882a593Smuzhiyun if (box.y1 > pptInit->y)
667*4882a593Smuzhiyun box.y1 = pptInit->y;
668*4882a593Smuzhiyun else if (box.y2 < pptInit->y)
669*4882a593Smuzhiyun box.y2 = pptInit->y;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun box.x2++;
673*4882a593Smuzhiyun box.y2++;
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
676*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
677*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun #elif ROOTLESS_CHANGED_AREA==2
680*4882a593Smuzhiyun // clever(?) method: accumulate point in 20-pixel radius
681*4882a593Smuzhiyun BoxRec box;
682*4882a593Smuzhiyun int firstx, firsty;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun box.x2 = box.x1 = firstx = pptInit->x;
685*4882a593Smuzhiyun box.y2 = box.y1 = firsty = pptInit->y;
686*4882a593Smuzhiyun while (--npt) {
687*4882a593Smuzhiyun pptInit++;
688*4882a593Smuzhiyun if (abs(pptInit->x - firstx) > 20 || abs(pptInit->y - firsty) > 20) {
689*4882a593Smuzhiyun box.x2++;
690*4882a593Smuzhiyun box.y2++;
691*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
692*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
693*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
694*4882a593Smuzhiyun box.x2 = box.x1 = firstx = pptInit->x;
695*4882a593Smuzhiyun box.y2 = box.y1 = firsty = pptInit->y;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun else {
698*4882a593Smuzhiyun if (box.x1 > pptInit->x)
699*4882a593Smuzhiyun box.x1 = pptInit->x;
700*4882a593Smuzhiyun else if (box.x2 < pptInit->x)
701*4882a593Smuzhiyun box.x2 = pptInit->x;
702*4882a593Smuzhiyun if (box.y1 > pptInit->y)
703*4882a593Smuzhiyun box.y1 = pptInit->y;
704*4882a593Smuzhiyun else if (box.y2 < pptInit->y)
705*4882a593Smuzhiyun box.y2 = pptInit->y;
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun box.x2++;
709*4882a593Smuzhiyun box.y2++;
710*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
711*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
712*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
713*4882a593Smuzhiyun #endif /* ROOTLESS_CHANGED_AREA */
714*4882a593Smuzhiyun }
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun GCOP_WRAP(pGC);
717*4882a593Smuzhiyun RL_DEBUG_MSG("polypoint end\n");
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun #undef ROOTLESS_CHANGED_AREA
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun /* changed area is box around each line */
723*4882a593Smuzhiyun static void
RootlessPolylines(DrawablePtr dst,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)724*4882a593Smuzhiyun RootlessPolylines(DrawablePtr dst, GCPtr pGC,
725*4882a593Smuzhiyun int mode, int npt, DDXPointPtr pptInit)
726*4882a593Smuzhiyun {
727*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
728*4882a593Smuzhiyun RL_DEBUG_MSG("poly lines start ");
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
731*4882a593Smuzhiyun pGC->ops->Polylines(dst, pGC, mode, npt, pptInit);
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun if (npt > 0) {
734*4882a593Smuzhiyun BoxRec box;
735*4882a593Smuzhiyun int extra = pGC->lineWidth >> 1;
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun box.x2 = box.x1 = pptInit->x;
738*4882a593Smuzhiyun box.y2 = box.y1 = pptInit->y;
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun if (npt > 1) {
741*4882a593Smuzhiyun if (pGC->joinStyle == JoinMiter)
742*4882a593Smuzhiyun extra = 6 * pGC->lineWidth;
743*4882a593Smuzhiyun else if (pGC->capStyle == CapProjecting)
744*4882a593Smuzhiyun extra = pGC->lineWidth;
745*4882a593Smuzhiyun }
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun if (mode == CoordModePrevious) {
748*4882a593Smuzhiyun int x = box.x1;
749*4882a593Smuzhiyun int y = box.y1;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun while (--npt) {
752*4882a593Smuzhiyun pptInit++;
753*4882a593Smuzhiyun x += pptInit->x;
754*4882a593Smuzhiyun y += pptInit->y;
755*4882a593Smuzhiyun if (box.x1 > x)
756*4882a593Smuzhiyun box.x1 = x;
757*4882a593Smuzhiyun else if (box.x2 < x)
758*4882a593Smuzhiyun box.x2 = x;
759*4882a593Smuzhiyun if (box.y1 > y)
760*4882a593Smuzhiyun box.y1 = y;
761*4882a593Smuzhiyun else if (box.y2 < y)
762*4882a593Smuzhiyun box.y2 = y;
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun else {
766*4882a593Smuzhiyun while (--npt) {
767*4882a593Smuzhiyun pptInit++;
768*4882a593Smuzhiyun if (box.x1 > pptInit->x)
769*4882a593Smuzhiyun box.x1 = pptInit->x;
770*4882a593Smuzhiyun else if (box.x2 < pptInit->x)
771*4882a593Smuzhiyun box.x2 = pptInit->x;
772*4882a593Smuzhiyun if (box.y1 > pptInit->y)
773*4882a593Smuzhiyun box.y1 = pptInit->y;
774*4882a593Smuzhiyun else if (box.y2 < pptInit->y)
775*4882a593Smuzhiyun box.y2 = pptInit->y;
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun box.x2++;
780*4882a593Smuzhiyun box.y2++;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun if (extra) {
783*4882a593Smuzhiyun box.x1 -= extra;
784*4882a593Smuzhiyun box.x2 += extra;
785*4882a593Smuzhiyun box.y1 -= extra;
786*4882a593Smuzhiyun box.y2 += extra;
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
790*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
791*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun GCOP_WRAP(pGC);
795*4882a593Smuzhiyun RL_DEBUG_MSG("poly lines end\n");
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /* changed area is box around each line segment */
799*4882a593Smuzhiyun static void
RootlessPolySegment(DrawablePtr dst,GCPtr pGC,int nseg,xSegment * pSeg)800*4882a593Smuzhiyun RootlessPolySegment(DrawablePtr dst, GCPtr pGC, int nseg, xSegment * pSeg)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
803*4882a593Smuzhiyun RL_DEBUG_MSG("poly segment start (win 0x%x)", dst);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
806*4882a593Smuzhiyun pGC->ops->PolySegment(dst, pGC, nseg, pSeg);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun if (nseg > 0) {
809*4882a593Smuzhiyun BoxRec box;
810*4882a593Smuzhiyun int extra = pGC->lineWidth;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if (pGC->capStyle != CapProjecting)
813*4882a593Smuzhiyun extra >>= 1;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun if (pSeg->x2 > pSeg->x1) {
816*4882a593Smuzhiyun box.x1 = pSeg->x1;
817*4882a593Smuzhiyun box.x2 = pSeg->x2;
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun else {
820*4882a593Smuzhiyun box.x2 = pSeg->x1;
821*4882a593Smuzhiyun box.x1 = pSeg->x2;
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun if (pSeg->y2 > pSeg->y1) {
825*4882a593Smuzhiyun box.y1 = pSeg->y1;
826*4882a593Smuzhiyun box.y2 = pSeg->y2;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun else {
829*4882a593Smuzhiyun box.y2 = pSeg->y1;
830*4882a593Smuzhiyun box.y1 = pSeg->y2;
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun while (--nseg) {
834*4882a593Smuzhiyun pSeg++;
835*4882a593Smuzhiyun if (pSeg->x2 > pSeg->x1) {
836*4882a593Smuzhiyun if (pSeg->x1 < box.x1)
837*4882a593Smuzhiyun box.x1 = pSeg->x1;
838*4882a593Smuzhiyun if (pSeg->x2 > box.x2)
839*4882a593Smuzhiyun box.x2 = pSeg->x2;
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun else {
842*4882a593Smuzhiyun if (pSeg->x2 < box.x1)
843*4882a593Smuzhiyun box.x1 = pSeg->x2;
844*4882a593Smuzhiyun if (pSeg->x1 > box.x2)
845*4882a593Smuzhiyun box.x2 = pSeg->x1;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun if (pSeg->y2 > pSeg->y1) {
848*4882a593Smuzhiyun if (pSeg->y1 < box.y1)
849*4882a593Smuzhiyun box.y1 = pSeg->y1;
850*4882a593Smuzhiyun if (pSeg->y2 > box.y2)
851*4882a593Smuzhiyun box.y2 = pSeg->y2;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun else {
854*4882a593Smuzhiyun if (pSeg->y2 < box.y1)
855*4882a593Smuzhiyun box.y1 = pSeg->y2;
856*4882a593Smuzhiyun if (pSeg->y1 > box.y2)
857*4882a593Smuzhiyun box.y2 = pSeg->y1;
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun box.x2++;
862*4882a593Smuzhiyun box.y2++;
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun if (extra) {
865*4882a593Smuzhiyun box.x1 -= extra;
866*4882a593Smuzhiyun box.x2 += extra;
867*4882a593Smuzhiyun box.y1 -= extra;
868*4882a593Smuzhiyun box.y2 += extra;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
872*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
873*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
874*4882a593Smuzhiyun }
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun GCOP_WRAP(pGC);
877*4882a593Smuzhiyun RL_DEBUG_MSG("poly segment end\n");
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun /* changed area is box around each line (not entire rects) */
881*4882a593Smuzhiyun static void
RootlessPolyRectangle(DrawablePtr dst,GCPtr pGC,int nRects,xRectangle * pRects)882*4882a593Smuzhiyun RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
883*4882a593Smuzhiyun int nRects, xRectangle *pRects)
884*4882a593Smuzhiyun {
885*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
886*4882a593Smuzhiyun RL_DEBUG_MSG("poly rectangle start ");
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
889*4882a593Smuzhiyun pGC->ops->PolyRectangle(dst, pGC, nRects, pRects);
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun if (nRects > 0) {
892*4882a593Smuzhiyun BoxRec box;
893*4882a593Smuzhiyun int offset1, offset2, offset3;
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun offset2 = pGC->lineWidth;
896*4882a593Smuzhiyun if (!offset2)
897*4882a593Smuzhiyun offset2 = 1;
898*4882a593Smuzhiyun offset1 = offset2 >> 1;
899*4882a593Smuzhiyun offset3 = offset2 - offset1;
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun while (nRects--) {
902*4882a593Smuzhiyun box.x1 = pRects->x - offset1;
903*4882a593Smuzhiyun box.y1 = pRects->y - offset1;
904*4882a593Smuzhiyun box.x2 = box.x1 + pRects->width + offset2;
905*4882a593Smuzhiyun box.y2 = box.y1 + offset2;
906*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
907*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
908*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun box.x1 = pRects->x - offset1;
911*4882a593Smuzhiyun box.y1 = pRects->y + offset3;
912*4882a593Smuzhiyun box.x2 = box.x1 + offset2;
913*4882a593Smuzhiyun box.y2 = box.y1 + pRects->height - offset2;
914*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
915*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
916*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun box.x1 = pRects->x + pRects->width - offset1;
919*4882a593Smuzhiyun box.y1 = pRects->y + offset3;
920*4882a593Smuzhiyun box.x2 = box.x1 + offset2;
921*4882a593Smuzhiyun box.y2 = box.y1 + pRects->height - offset2;
922*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
923*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
924*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun box.x1 = pRects->x - offset1;
927*4882a593Smuzhiyun box.y1 = pRects->y + pRects->height - offset1;
928*4882a593Smuzhiyun box.x2 = box.x1 + pRects->width + offset2;
929*4882a593Smuzhiyun box.y2 = box.y1 + offset2;
930*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
931*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
932*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun pRects++;
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun GCOP_WRAP(pGC);
939*4882a593Smuzhiyun RL_DEBUG_MSG("poly rectangle end\n");
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun /* changed area is box around each arc (assumes all arcs are 360 degrees) */
943*4882a593Smuzhiyun static void
RootlessPolyArc(DrawablePtr dst,GCPtr pGC,int narcs,xArc * parcs)944*4882a593Smuzhiyun RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc * parcs)
945*4882a593Smuzhiyun {
946*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
947*4882a593Smuzhiyun RL_DEBUG_MSG("poly arc start ");
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
950*4882a593Smuzhiyun pGC->ops->PolyArc(dst, pGC, narcs, parcs);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun if (narcs > 0) {
953*4882a593Smuzhiyun int extra = pGC->lineWidth >> 1;
954*4882a593Smuzhiyun BoxRec box;
955*4882a593Smuzhiyun
956*4882a593Smuzhiyun box.x1 = parcs->x;
957*4882a593Smuzhiyun box.x2 = box.x1 + parcs->width;
958*4882a593Smuzhiyun box.y1 = parcs->y;
959*4882a593Smuzhiyun box.y2 = box.y1 + parcs->height;
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun /* should I break these up instead ? */
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun while (--narcs) {
964*4882a593Smuzhiyun parcs++;
965*4882a593Smuzhiyun if (box.x1 > parcs->x)
966*4882a593Smuzhiyun box.x1 = parcs->x;
967*4882a593Smuzhiyun if (box.x2 < (parcs->x + parcs->width))
968*4882a593Smuzhiyun box.x2 = parcs->x + parcs->width;
969*4882a593Smuzhiyun if (box.y1 > parcs->y)
970*4882a593Smuzhiyun box.y1 = parcs->y;
971*4882a593Smuzhiyun if (box.y2 < (parcs->y + parcs->height))
972*4882a593Smuzhiyun box.y2 = parcs->y + parcs->height;
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun if (extra) {
976*4882a593Smuzhiyun box.x1 -= extra;
977*4882a593Smuzhiyun box.x2 += extra;
978*4882a593Smuzhiyun box.y1 -= extra;
979*4882a593Smuzhiyun box.y2 += extra;
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun box.x2++;
983*4882a593Smuzhiyun box.y2++;
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
986*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
987*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
988*4882a593Smuzhiyun }
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun GCOP_WRAP(pGC);
991*4882a593Smuzhiyun RL_DEBUG_MSG("poly arc end\n");
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun /* changed area is box around each poly */
995*4882a593Smuzhiyun static void
RootlessFillPolygon(DrawablePtr dst,GCPtr pGC,int shape,int mode,int count,DDXPointPtr pptInit)996*4882a593Smuzhiyun RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
997*4882a593Smuzhiyun int shape, int mode, int count, DDXPointPtr pptInit)
998*4882a593Smuzhiyun {
999*4882a593Smuzhiyun GC_SAVE(pGC);
1000*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1001*4882a593Smuzhiyun RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)", dst,
1002*4882a593Smuzhiyun pGC->fillStyle);
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun if (count <= 2) {
1005*4882a593Smuzhiyun pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
1006*4882a593Smuzhiyun }
1007*4882a593Smuzhiyun else {
1008*4882a593Smuzhiyun DDXPointPtr ppt = pptInit;
1009*4882a593Smuzhiyun int i = count;
1010*4882a593Smuzhiyun BoxRec box;
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun box.x2 = box.x1 = ppt->x;
1013*4882a593Smuzhiyun box.y2 = box.y1 = ppt->y;
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun if (mode != CoordModeOrigin) {
1016*4882a593Smuzhiyun int x = box.x1;
1017*4882a593Smuzhiyun int y = box.y1;
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun while (--i) {
1020*4882a593Smuzhiyun ppt++;
1021*4882a593Smuzhiyun x += ppt->x;
1022*4882a593Smuzhiyun y += ppt->y;
1023*4882a593Smuzhiyun if (box.x1 > x)
1024*4882a593Smuzhiyun box.x1 = x;
1025*4882a593Smuzhiyun else if (box.x2 < x)
1026*4882a593Smuzhiyun box.x2 = x;
1027*4882a593Smuzhiyun if (box.y1 > y)
1028*4882a593Smuzhiyun box.y1 = y;
1029*4882a593Smuzhiyun else if (box.y2 < y)
1030*4882a593Smuzhiyun box.y2 = y;
1031*4882a593Smuzhiyun }
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun else {
1034*4882a593Smuzhiyun while (--i) {
1035*4882a593Smuzhiyun ppt++;
1036*4882a593Smuzhiyun if (box.x1 > ppt->x)
1037*4882a593Smuzhiyun box.x1 = ppt->x;
1038*4882a593Smuzhiyun else if (box.x2 < ppt->x)
1039*4882a593Smuzhiyun box.x2 = ppt->x;
1040*4882a593Smuzhiyun if (box.y1 > ppt->y)
1041*4882a593Smuzhiyun box.y1 = ppt->y;
1042*4882a593Smuzhiyun else if (box.y2 < ppt->y)
1043*4882a593Smuzhiyun box.y2 = ppt->y;
1044*4882a593Smuzhiyun }
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun box.x2++;
1048*4882a593Smuzhiyun box.y2++;
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun if (canAccelFill(dst, pGC)) {
1053*4882a593Smuzhiyun GC_UNSET_PM(pGC, dst);
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
1059*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1060*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun GC_RESTORE(pGC, dst);
1064*4882a593Smuzhiyun GCOP_WRAP(pGC);
1065*4882a593Smuzhiyun RL_DEBUG_MSG("fill poly end\n");
1066*4882a593Smuzhiyun }
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun /* changed area is the rects */
1069*4882a593Smuzhiyun static void
RootlessPolyFillRect(DrawablePtr dst,GCPtr pGC,int nRectsInit,xRectangle * pRectsInit)1070*4882a593Smuzhiyun RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
1071*4882a593Smuzhiyun int nRectsInit, xRectangle *pRectsInit)
1072*4882a593Smuzhiyun {
1073*4882a593Smuzhiyun GC_SAVE(pGC);
1074*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1075*4882a593Smuzhiyun RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)", dst,
1076*4882a593Smuzhiyun pGC->fillStyle);
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun if (nRectsInit <= 0) {
1079*4882a593Smuzhiyun pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun else {
1082*4882a593Smuzhiyun BoxRec box;
1083*4882a593Smuzhiyun xRectangle *pRects = pRectsInit;
1084*4882a593Smuzhiyun int nRects = nRectsInit;
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun box.x1 = pRects->x;
1087*4882a593Smuzhiyun box.x2 = box.x1 + pRects->width;
1088*4882a593Smuzhiyun box.y1 = pRects->y;
1089*4882a593Smuzhiyun box.y2 = box.y1 + pRects->height;
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun while (--nRects) {
1092*4882a593Smuzhiyun pRects++;
1093*4882a593Smuzhiyun if (box.x1 > pRects->x)
1094*4882a593Smuzhiyun box.x1 = pRects->x;
1095*4882a593Smuzhiyun if (box.x2 < (pRects->x + pRects->width))
1096*4882a593Smuzhiyun box.x2 = pRects->x + pRects->width;
1097*4882a593Smuzhiyun if (box.y1 > pRects->y)
1098*4882a593Smuzhiyun box.y1 = pRects->y;
1099*4882a593Smuzhiyun if (box.y2 < (pRects->y + pRects->height))
1100*4882a593Smuzhiyun box.y2 = pRects->y + pRects->height;
1101*4882a593Smuzhiyun }
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun if (canAccelFill(dst, pGC)) {
1106*4882a593Smuzhiyun GC_UNSET_PM(pGC, dst);
1107*4882a593Smuzhiyun }
1108*4882a593Smuzhiyun
1109*4882a593Smuzhiyun pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
1112*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1113*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun GC_RESTORE(pGC, dst);
1117*4882a593Smuzhiyun GCOP_WRAP(pGC);
1118*4882a593Smuzhiyun RL_DEBUG_MSG("fill rect end\n");
1119*4882a593Smuzhiyun }
1120*4882a593Smuzhiyun
1121*4882a593Smuzhiyun /* changed area is box around each arc (assuming arcs are all 360 degrees) */
1122*4882a593Smuzhiyun static void
RootlessPolyFillArc(DrawablePtr dst,GCPtr pGC,int narcsInit,xArc * parcsInit)1123*4882a593Smuzhiyun RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, int narcsInit, xArc * parcsInit)
1124*4882a593Smuzhiyun {
1125*4882a593Smuzhiyun GC_SAVE(pGC);
1126*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1127*4882a593Smuzhiyun RL_DEBUG_MSG("fill arc start ");
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun if (narcsInit > 0) {
1130*4882a593Smuzhiyun BoxRec box;
1131*4882a593Smuzhiyun int narcs = narcsInit;
1132*4882a593Smuzhiyun xArc *parcs = parcsInit;
1133*4882a593Smuzhiyun
1134*4882a593Smuzhiyun box.x1 = parcs->x;
1135*4882a593Smuzhiyun box.x2 = box.x1 + parcs->width;
1136*4882a593Smuzhiyun box.y1 = parcs->y;
1137*4882a593Smuzhiyun box.y2 = box.y1 + parcs->height;
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun /* should I break these up instead ? */
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun while (--narcs) {
1142*4882a593Smuzhiyun parcs++;
1143*4882a593Smuzhiyun if (box.x1 > parcs->x)
1144*4882a593Smuzhiyun box.x1 = parcs->x;
1145*4882a593Smuzhiyun if (box.x2 < (parcs->x + parcs->width))
1146*4882a593Smuzhiyun box.x2 = parcs->x + parcs->width;
1147*4882a593Smuzhiyun if (box.y1 > parcs->y)
1148*4882a593Smuzhiyun box.y1 = parcs->y;
1149*4882a593Smuzhiyun if (box.y2 < (parcs->y + parcs->height))
1150*4882a593Smuzhiyun box.y2 = parcs->y + parcs->height;
1151*4882a593Smuzhiyun }
1152*4882a593Smuzhiyun
1153*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun if (canAccelFill(dst, pGC)) {
1156*4882a593Smuzhiyun GC_UNSET_PM(pGC, dst);
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit);
1160*4882a593Smuzhiyun
1161*4882a593Smuzhiyun TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
1162*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1163*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun else {
1166*4882a593Smuzhiyun pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit);
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun GC_RESTORE(pGC, dst);
1170*4882a593Smuzhiyun GCOP_WRAP(pGC);
1171*4882a593Smuzhiyun RL_DEBUG_MSG("fill arc end\n");
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun
1174*4882a593Smuzhiyun static void
RootlessImageText8(DrawablePtr dst,GCPtr pGC,int x,int y,int count,char * chars)1175*4882a593Smuzhiyun RootlessImageText8(DrawablePtr dst, GCPtr pGC,
1176*4882a593Smuzhiyun int x, int y, int count, char *chars)
1177*4882a593Smuzhiyun {
1178*4882a593Smuzhiyun GC_SAVE(pGC);
1179*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1180*4882a593Smuzhiyun RL_DEBUG_MSG("imagetext8 start ");
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun if (count > 0) {
1183*4882a593Smuzhiyun int top, bot, Min, Max;
1184*4882a593Smuzhiyun BoxRec box;
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
1187*4882a593Smuzhiyun bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
1188*4882a593Smuzhiyun
1189*4882a593Smuzhiyun Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
1190*4882a593Smuzhiyun if (Min > 0)
1191*4882a593Smuzhiyun Min = 0;
1192*4882a593Smuzhiyun Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
1193*4882a593Smuzhiyun if (Max < 0)
1194*4882a593Smuzhiyun Max = 0;
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun /* ugh */
1197*4882a593Smuzhiyun box.x1 = dst->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing);
1198*4882a593Smuzhiyun box.x2 = dst->x + x + Max + FONTMAXBOUNDS(pGC->font, rightSideBearing);
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun box.y1 = dst->y + y - top;
1201*4882a593Smuzhiyun box.y2 = dst->y + y + bot;
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1204*4882a593Smuzhiyun
1205*4882a593Smuzhiyun if (canAccelFill(dst, pGC)) {
1206*4882a593Smuzhiyun GC_UNSET_PM(pGC, dst);
1207*4882a593Smuzhiyun }
1208*4882a593Smuzhiyun
1209*4882a593Smuzhiyun pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun TRIM_BOX(box, pGC);
1212*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1213*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1214*4882a593Smuzhiyun }
1215*4882a593Smuzhiyun else {
1216*4882a593Smuzhiyun pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun GC_RESTORE(pGC, dst);
1220*4882a593Smuzhiyun GCOP_WRAP(pGC);
1221*4882a593Smuzhiyun RL_DEBUG_MSG("imagetext8 end\n");
1222*4882a593Smuzhiyun }
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun static int
RootlessPolyText8(DrawablePtr dst,GCPtr pGC,int x,int y,int count,char * chars)1225*4882a593Smuzhiyun RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
1226*4882a593Smuzhiyun int x, int y, int count, char *chars)
1227*4882a593Smuzhiyun {
1228*4882a593Smuzhiyun int width; // the result, sorta
1229*4882a593Smuzhiyun
1230*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun RL_DEBUG_MSG("polytext8 start ");
1233*4882a593Smuzhiyun
1234*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1235*4882a593Smuzhiyun width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars);
1236*4882a593Smuzhiyun width -= x;
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun if (width > 0) {
1239*4882a593Smuzhiyun BoxRec box;
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun /* ugh */
1242*4882a593Smuzhiyun box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
1243*4882a593Smuzhiyun box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun if (count > 1) {
1246*4882a593Smuzhiyun if (width > 0)
1247*4882a593Smuzhiyun box.x2 += width;
1248*4882a593Smuzhiyun else
1249*4882a593Smuzhiyun box.x1 += width;
1250*4882a593Smuzhiyun }
1251*4882a593Smuzhiyun
1252*4882a593Smuzhiyun box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
1253*4882a593Smuzhiyun box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
1254*4882a593Smuzhiyun
1255*4882a593Smuzhiyun TRIM_BOX(box, pGC);
1256*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1257*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun GCOP_WRAP(pGC);
1261*4882a593Smuzhiyun RL_DEBUG_MSG("polytext8 end\n");
1262*4882a593Smuzhiyun return width + x;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun
1265*4882a593Smuzhiyun static void
RootlessImageText16(DrawablePtr dst,GCPtr pGC,int x,int y,int count,unsigned short * chars)1266*4882a593Smuzhiyun RootlessImageText16(DrawablePtr dst, GCPtr pGC,
1267*4882a593Smuzhiyun int x, int y, int count, unsigned short *chars)
1268*4882a593Smuzhiyun {
1269*4882a593Smuzhiyun GC_SAVE(pGC);
1270*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1271*4882a593Smuzhiyun RL_DEBUG_MSG("imagetext16 start ");
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun if (count > 0) {
1274*4882a593Smuzhiyun int top, bot, Min, Max;
1275*4882a593Smuzhiyun BoxRec box;
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
1278*4882a593Smuzhiyun bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
1281*4882a593Smuzhiyun if (Min > 0)
1282*4882a593Smuzhiyun Min = 0;
1283*4882a593Smuzhiyun Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
1284*4882a593Smuzhiyun if (Max < 0)
1285*4882a593Smuzhiyun Max = 0;
1286*4882a593Smuzhiyun
1287*4882a593Smuzhiyun /* ugh */
1288*4882a593Smuzhiyun box.x1 = dst->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing);
1289*4882a593Smuzhiyun box.x2 = dst->x + x + Max + FONTMAXBOUNDS(pGC->font, rightSideBearing);
1290*4882a593Smuzhiyun
1291*4882a593Smuzhiyun box.y1 = dst->y + y - top;
1292*4882a593Smuzhiyun box.y2 = dst->y + y + bot;
1293*4882a593Smuzhiyun
1294*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun if (canAccelFill(dst, pGC)) {
1297*4882a593Smuzhiyun GC_UNSET_PM(pGC, dst);
1298*4882a593Smuzhiyun }
1299*4882a593Smuzhiyun
1300*4882a593Smuzhiyun pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
1301*4882a593Smuzhiyun
1302*4882a593Smuzhiyun TRIM_BOX(box, pGC);
1303*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1304*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun else {
1307*4882a593Smuzhiyun pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
1308*4882a593Smuzhiyun }
1309*4882a593Smuzhiyun
1310*4882a593Smuzhiyun GC_RESTORE(pGC, dst);
1311*4882a593Smuzhiyun GCOP_WRAP(pGC);
1312*4882a593Smuzhiyun RL_DEBUG_MSG("imagetext16 end\n");
1313*4882a593Smuzhiyun }
1314*4882a593Smuzhiyun
1315*4882a593Smuzhiyun static int
RootlessPolyText16(DrawablePtr dst,GCPtr pGC,int x,int y,int count,unsigned short * chars)1316*4882a593Smuzhiyun RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
1317*4882a593Smuzhiyun int x, int y, int count, unsigned short *chars)
1318*4882a593Smuzhiyun {
1319*4882a593Smuzhiyun int width; // the result, sorta
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1322*4882a593Smuzhiyun
1323*4882a593Smuzhiyun RL_DEBUG_MSG("polytext16 start ");
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1326*4882a593Smuzhiyun width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars);
1327*4882a593Smuzhiyun width -= x;
1328*4882a593Smuzhiyun
1329*4882a593Smuzhiyun if (width > 0) {
1330*4882a593Smuzhiyun BoxRec box;
1331*4882a593Smuzhiyun
1332*4882a593Smuzhiyun /* ugh */
1333*4882a593Smuzhiyun box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
1334*4882a593Smuzhiyun box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
1335*4882a593Smuzhiyun
1336*4882a593Smuzhiyun if (count > 1) {
1337*4882a593Smuzhiyun if (width > 0)
1338*4882a593Smuzhiyun box.x2 += width;
1339*4882a593Smuzhiyun else
1340*4882a593Smuzhiyun box.x1 += width;
1341*4882a593Smuzhiyun }
1342*4882a593Smuzhiyun
1343*4882a593Smuzhiyun box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
1344*4882a593Smuzhiyun box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
1345*4882a593Smuzhiyun
1346*4882a593Smuzhiyun TRIM_BOX(box, pGC);
1347*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1348*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1349*4882a593Smuzhiyun }
1350*4882a593Smuzhiyun
1351*4882a593Smuzhiyun GCOP_WRAP(pGC);
1352*4882a593Smuzhiyun RL_DEBUG_MSG("polytext16 end\n");
1353*4882a593Smuzhiyun return width + x;
1354*4882a593Smuzhiyun }
1355*4882a593Smuzhiyun
1356*4882a593Smuzhiyun static void
RootlessImageGlyphBlt(DrawablePtr dst,GCPtr pGC,int x,int y,unsigned int nglyphInit,CharInfoPtr * ppciInit,void * unused)1357*4882a593Smuzhiyun RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
1358*4882a593Smuzhiyun int x, int y, unsigned int nglyphInit,
1359*4882a593Smuzhiyun CharInfoPtr * ppciInit, void *unused)
1360*4882a593Smuzhiyun {
1361*4882a593Smuzhiyun GC_SAVE(pGC);
1362*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1363*4882a593Smuzhiyun RL_DEBUG_MSG("imageglyph start ");
1364*4882a593Smuzhiyun
1365*4882a593Smuzhiyun if (nglyphInit > 0) {
1366*4882a593Smuzhiyun int top, bot, width = 0;
1367*4882a593Smuzhiyun BoxRec box;
1368*4882a593Smuzhiyun unsigned int nglyph = nglyphInit;
1369*4882a593Smuzhiyun CharInfoPtr *ppci = ppciInit;
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
1372*4882a593Smuzhiyun bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
1373*4882a593Smuzhiyun
1374*4882a593Smuzhiyun box.x1 = ppci[0]->metrics.leftSideBearing;
1375*4882a593Smuzhiyun if (box.x1 > 0)
1376*4882a593Smuzhiyun box.x1 = 0;
1377*4882a593Smuzhiyun box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
1378*4882a593Smuzhiyun ppci[nglyph - 1]->metrics.characterWidth;
1379*4882a593Smuzhiyun if (box.x2 < 0)
1380*4882a593Smuzhiyun box.x2 = 0;
1381*4882a593Smuzhiyun
1382*4882a593Smuzhiyun box.x2 += dst->x + x;
1383*4882a593Smuzhiyun box.x1 += dst->x + x;
1384*4882a593Smuzhiyun
1385*4882a593Smuzhiyun while (nglyph--) {
1386*4882a593Smuzhiyun width += (*ppci)->metrics.characterWidth;
1387*4882a593Smuzhiyun ppci++;
1388*4882a593Smuzhiyun }
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun if (width > 0)
1391*4882a593Smuzhiyun box.x2 += width;
1392*4882a593Smuzhiyun else
1393*4882a593Smuzhiyun box.x1 += width;
1394*4882a593Smuzhiyun
1395*4882a593Smuzhiyun box.y1 = dst->y + y - top;
1396*4882a593Smuzhiyun box.y2 = dst->y + y + bot;
1397*4882a593Smuzhiyun
1398*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1399*4882a593Smuzhiyun
1400*4882a593Smuzhiyun if (canAccelFill(dst, pGC)) {
1401*4882a593Smuzhiyun GC_UNSET_PM(pGC, dst);
1402*4882a593Smuzhiyun }
1403*4882a593Smuzhiyun
1404*4882a593Smuzhiyun pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused);
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun TRIM_BOX(box, pGC);
1407*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1408*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1409*4882a593Smuzhiyun }
1410*4882a593Smuzhiyun else {
1411*4882a593Smuzhiyun pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused);
1412*4882a593Smuzhiyun }
1413*4882a593Smuzhiyun
1414*4882a593Smuzhiyun GC_RESTORE(pGC, dst);
1415*4882a593Smuzhiyun GCOP_WRAP(pGC);
1416*4882a593Smuzhiyun RL_DEBUG_MSG("imageglyph end\n");
1417*4882a593Smuzhiyun }
1418*4882a593Smuzhiyun
1419*4882a593Smuzhiyun static void
RootlessPolyGlyphBlt(DrawablePtr dst,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,void * pglyphBase)1420*4882a593Smuzhiyun RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
1421*4882a593Smuzhiyun int x, int y, unsigned int nglyph,
1422*4882a593Smuzhiyun CharInfoPtr * ppci, void *pglyphBase)
1423*4882a593Smuzhiyun {
1424*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1425*4882a593Smuzhiyun RL_DEBUG_MSG("polyglyph start ");
1426*4882a593Smuzhiyun
1427*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1428*4882a593Smuzhiyun pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase);
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun if (nglyph > 0) {
1431*4882a593Smuzhiyun BoxRec box;
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun /* ugh */
1434*4882a593Smuzhiyun box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing;
1435*4882a593Smuzhiyun box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun if (nglyph > 1) {
1438*4882a593Smuzhiyun int width = 0;
1439*4882a593Smuzhiyun
1440*4882a593Smuzhiyun while (--nglyph) {
1441*4882a593Smuzhiyun width += (*ppci)->metrics.characterWidth;
1442*4882a593Smuzhiyun ppci++;
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun
1445*4882a593Smuzhiyun if (width > 0)
1446*4882a593Smuzhiyun box.x2 += width;
1447*4882a593Smuzhiyun else
1448*4882a593Smuzhiyun box.x1 += width;
1449*4882a593Smuzhiyun }
1450*4882a593Smuzhiyun
1451*4882a593Smuzhiyun box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
1452*4882a593Smuzhiyun box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
1453*4882a593Smuzhiyun
1454*4882a593Smuzhiyun TRIM_BOX(box, pGC);
1455*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1456*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1457*4882a593Smuzhiyun }
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun GCOP_WRAP(pGC);
1460*4882a593Smuzhiyun RL_DEBUG_MSG("polyglyph end\n");
1461*4882a593Smuzhiyun }
1462*4882a593Smuzhiyun
1463*4882a593Smuzhiyun /* changed area is in dest */
1464*4882a593Smuzhiyun static void
RootlessPushPixels(GCPtr pGC,PixmapPtr pBitMap,DrawablePtr dst,int dx,int dy,int xOrg,int yOrg)1465*4882a593Smuzhiyun RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
1466*4882a593Smuzhiyun int dx, int dy, int xOrg, int yOrg)
1467*4882a593Smuzhiyun {
1468*4882a593Smuzhiyun BoxRec box;
1469*4882a593Smuzhiyun
1470*4882a593Smuzhiyun GCOP_UNWRAP(pGC);
1471*4882a593Smuzhiyun RL_DEBUG_MSG("push pixels start ");
1472*4882a593Smuzhiyun
1473*4882a593Smuzhiyun RootlessStartDrawing((WindowPtr) dst);
1474*4882a593Smuzhiyun pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg);
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun box.x1 = xOrg + dst->x;
1477*4882a593Smuzhiyun box.x2 = box.x1 + dx;
1478*4882a593Smuzhiyun box.y1 = yOrg + dst->y;
1479*4882a593Smuzhiyun box.y2 = box.y1 + dy;
1480*4882a593Smuzhiyun
1481*4882a593Smuzhiyun TRIM_BOX(box, pGC);
1482*4882a593Smuzhiyun if (BOX_NOT_EMPTY(box))
1483*4882a593Smuzhiyun RootlessDamageBox((WindowPtr) dst, &box);
1484*4882a593Smuzhiyun
1485*4882a593Smuzhiyun GCOP_WRAP(pGC);
1486*4882a593Smuzhiyun RL_DEBUG_MSG("push pixels end\n");
1487*4882a593Smuzhiyun }
1488