xref: /OK3568_Linux_fs/external/xserver/miext/rootless/rootlessGC.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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