Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | Copyright (C) 1999. The XFree86 Project Inc. | |
3 | ||
4 | Written by Mark Vojkovich (mvojkovi@ucsd.edu) | |
5 | ||
6 | Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com) | |
7 | */ | |
8 | ||
9 | #ifdef HAVE_XORG_CONFIG_H | |
10 | #include <xorg-config.h> | |
11 | #endif | |
12 | ||
13 | #include <X11/X.h> | |
14 | #include <X11/Xproto.h> | |
15 | #include "misc.h" | |
16 | #include "pixmapstr.h" | |
17 | #include "input.h" | |
18 | #include <X11/fonts/font.h> | |
19 | #include "mi.h" | |
20 | #include "scrnintstr.h" | |
21 | #include "windowstr.h" | |
22 | #include "gcstruct.h" | |
23 | #include "dixfontstr.h" | |
24 | #include <X11/fonts/fontstruct.h> | |
25 | #include "xf86.h" | |
26 | #include "xf86str.h" | |
27 | #include "shadowfb.h" | |
28 | ||
29 | #include "picturestr.h" | |
30 | ||
31 | static Bool ShadowCloseScreen(ScreenPtr pScreen); | |
32 | static void ShadowCopyWindow(WindowPtr pWin, | |
33 | DDXPointRec ptOldOrg, RegionPtr prgn); | |
34 | static Bool ShadowCreateGC(GCPtr pGC); | |
35 | ||
36 | static Bool ShadowEnterVT(ScrnInfoPtr pScrn); | |
37 | static void ShadowLeaveVT(ScrnInfoPtr pScrn); | |
38 | ||
39 | static void ShadowComposite(CARD8 op, | |
40 | PicturePtr pSrc, | |
41 | PicturePtr pMask, | |
42 | PicturePtr pDst, | |
43 | INT16 xSrc, | |
44 | INT16 ySrc, | |
45 | INT16 xMask, | |
46 | INT16 yMask, | |
47 | INT16 xDst, | |
48 | INT16 yDst, CARD16 width, CARD16 height); | |
49 | ||
50 | typedef struct { | |
51 | ScrnInfoPtr pScrn; | |
52 | RefreshAreaFuncPtr preRefresh; | |
53 | RefreshAreaFuncPtr postRefresh; | |
54 | CloseScreenProcPtr CloseScreen; | |
55 | CopyWindowProcPtr CopyWindow; | |
56 | CreateGCProcPtr CreateGC; | |
57 | ModifyPixmapHeaderProcPtr ModifyPixmapHeader; | |
58 | CompositeProcPtr Composite; | |
59 | Bool (*EnterVT) (ScrnInfoPtr); | |
60 | void (*LeaveVT) (ScrnInfoPtr); | |
61 | Bool vtSema; | |
62 | } ShadowScreenRec, *ShadowScreenPtr; | |
63 | ||
64 | typedef struct { | |
65 | GCOps *ops; | |
66 | GCFuncs *funcs; | |
67 | } ShadowGCRec, *ShadowGCPtr; | |
68 | ||
69 | static DevPrivateKeyRec ShadowScreenKeyRec; | |
70 | ||
71 | #define ShadowScreenKey (&ShadowScreenKeyRec) | |
72 | ||
73 | static DevPrivateKeyRec ShadowGCKeyRec; | |
74 | ||
75 | #define ShadowGCKey (&ShadowGCKeyRec) | |
76 | ||
77 | #define GET_SCREEN_PRIVATE(pScreen) \ | |
78 | (ShadowScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, ShadowScreenKey) | |
79 | #define GET_GC_PRIVATE(pGC) \ | |
80 | (ShadowGCPtr)dixLookupPrivate(&(pGC)->devPrivates, ShadowGCKey) | |
81 | ||
82 | #define SHADOW_GC_FUNC_PROLOGUE(pGC)\ | |
83 | ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\ | |
84 | (pGC)->funcs = pGCPriv->funcs;\ | |
85 | if(pGCPriv->ops)\ | |
86 | (pGC)->ops = pGCPriv->ops | |
87 | ||
88 | #define SHADOW_GC_FUNC_EPILOGUE(pGC)\ | |
89 | pGCPriv->funcs = (pGC)->funcs;\ | |
90 | (pGC)->funcs = &ShadowGCFuncs;\ | |
91 | if(pGCPriv->ops) {\ | |
92 | pGCPriv->ops = (pGC)->ops;\ | |
93 | (pGC)->ops = &ShadowGCOps;\ | |
94 | } | |
95 | ||
96 | #define SHADOW_GC_OP_PROLOGUE(pGC)\ | |
97 | ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pGC->pScreen); \ | |
98 | ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\ | |
99 | GCFuncs *oldFuncs = pGC->funcs;\ | |
100 | pGC->funcs = pGCPriv->funcs;\ | |
101 | pGC->ops = pGCPriv->ops | |
102 | ||
103 | #define SHADOW_GC_OP_EPILOGUE(pGC)\ | |
104 | pGCPriv->ops = pGC->ops;\ | |
105 | pGC->funcs = oldFuncs;\ | |
106 | pGC->ops = &ShadowGCOps | |
107 | ||
108 | #define IS_VISIBLE(pWin) (pPriv->vtSema && \ | |
109 | (((WindowPtr)pWin)->visibility != VisibilityFullyObscured)) | |
110 | ||
111 | #define TRIM_BOX(box, pGC) { \ | |
112 | BoxPtr extents = &pGC->pCompositeClip->extents;\ | |
113 | if(box.x1 < extents->x1) box.x1 = extents->x1; \ | |
114 | if(box.x2 > extents->x2) box.x2 = extents->x2; \ | |
115 | if(box.y1 < extents->y1) box.y1 = extents->y1; \ | |
116 | if(box.y2 > extents->y2) box.y2 = extents->y2; \ | |
117 | } | |
118 | ||
119 | #define TRANSLATE_BOX(box, pDraw) { \ | |
120 | box.x1 += pDraw->x; \ | |
121 | box.x2 += pDraw->x; \ | |
122 | box.y1 += pDraw->y; \ | |
123 | box.y2 += pDraw->y; \ | |
124 | } | |
125 | ||
126 | #define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \ | |
127 | TRANSLATE_BOX(box, pDraw); \ | |
128 | TRIM_BOX(box, pGC); \ | |
129 | } | |
130 | ||
131 | #define BOX_NOT_EMPTY(box) \ | |
132 | (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) | |
133 | ||
134 | Bool | |
135 | ShadowFBInit2(ScreenPtr pScreen, | |
136 | RefreshAreaFuncPtr preRefreshArea, | |
137 | RefreshAreaFuncPtr postRefreshArea) | |
138 | { | |
139 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
140 | ShadowScreenPtr pPriv; | |
141 | PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); | |
142 | ||
143 | if (!preRefreshArea && !postRefreshArea) | |
144 | return FALSE; | |
145 | ||
146 | if (!dixRegisterPrivateKey(&ShadowScreenKeyRec, PRIVATE_SCREEN, 0)) | |
147 | return FALSE; | |
148 | ||
149 | if (!dixRegisterPrivateKey | |
150 | (&ShadowGCKeyRec, PRIVATE_GC, sizeof(ShadowGCRec))) | |
151 | return FALSE; | |
152 | ||
153 | if (!(pPriv = (ShadowScreenPtr) malloc(sizeof(ShadowScreenRec)))) | |
154 | return FALSE; | |
155 | ||
156 | dixSetPrivate(&pScreen->devPrivates, ShadowScreenKey, pPriv); | |
157 | ||
158 | pPriv->pScrn = pScrn; | |
159 | pPriv->preRefresh = preRefreshArea; | |
160 | pPriv->postRefresh = postRefreshArea; | |
161 | pPriv->vtSema = TRUE; | |
162 | ||
163 | pPriv->CloseScreen = pScreen->CloseScreen; | |
164 | pPriv->CopyWindow = pScreen->CopyWindow; | |
165 | pPriv->CreateGC = pScreen->CreateGC; | |
166 | pPriv->ModifyPixmapHeader = pScreen->ModifyPixmapHeader; | |
167 | ||
168 | pPriv->EnterVT = pScrn->EnterVT; | |
169 | pPriv->LeaveVT = pScrn->LeaveVT; | |
170 | ||
171 | pScreen->CloseScreen = ShadowCloseScreen; | |
172 | pScreen->CopyWindow = ShadowCopyWindow; | |
173 | pScreen->CreateGC = ShadowCreateGC; | |
174 | ||
175 | pScrn->EnterVT = ShadowEnterVT; | |
176 | pScrn->LeaveVT = ShadowLeaveVT; | |
177 | ||
178 | if (ps) { | |
179 | pPriv->Composite = ps->Composite; | |
180 | ps->Composite = ShadowComposite; | |
181 | } | |
182 | ||
183 | return TRUE; | |
184 | } | |
185 | ||
186 | Bool | |
187 | ShadowFBInit(ScreenPtr pScreen, RefreshAreaFuncPtr refreshArea) | |
188 | { | |
189 | return ShadowFBInit2(pScreen, NULL, refreshArea); | |
190 | } | |
191 | ||
192 | /**********************************************************/ | |
193 | ||
194 | static Bool | |
195 | ShadowEnterVT(ScrnInfoPtr pScrn) | |
196 | { | |
197 | Bool ret; | |
198 | ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen); | |
199 | ||
200 | pScrn->EnterVT = pPriv->EnterVT; | |
201 | ret = (*pPriv->EnterVT) (pScrn); | |
202 | pPriv->EnterVT = pScrn->EnterVT; | |
203 | pScrn->EnterVT = ShadowEnterVT; | |
204 | if (ret) { | |
205 | pPriv->vtSema = TRUE; | |
206 | return TRUE; | |
207 | } | |
208 | ||
209 | return FALSE; | |
210 | } | |
211 | ||
212 | static void | |
213 | ShadowLeaveVT(ScrnInfoPtr pScrn) | |
214 | { | |
215 | ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen); | |
216 | ||
217 | pPriv->vtSema = FALSE; | |
218 | ||
219 | pScrn->LeaveVT = pPriv->LeaveVT; | |
220 | (*pPriv->LeaveVT) (pScrn); | |
221 | pPriv->LeaveVT = pScrn->LeaveVT; | |
222 | pScrn->LeaveVT = ShadowLeaveVT; | |
223 | } | |
224 | ||
225 | /**********************************************************/ | |
226 | ||
227 | static Bool | |
228 | ShadowCloseScreen(ScreenPtr pScreen) | |
229 | { | |
230 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
231 | ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); | |
232 | PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); | |
233 | ||
234 | pScreen->CloseScreen = pPriv->CloseScreen; | |
235 | pScreen->CopyWindow = pPriv->CopyWindow; | |
236 | pScreen->CreateGC = pPriv->CreateGC; | |
237 | pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader; | |
238 | ||
239 | pScrn->EnterVT = pPriv->EnterVT; | |
240 | pScrn->LeaveVT = pPriv->LeaveVT; | |
241 | ||
242 | if (ps) { | |
243 | ps->Composite = pPriv->Composite; | |
244 | } | |
245 | ||
246 | free((pointer) pPriv); | |
247 | ||
248 | return (*pScreen->CloseScreen) (pScreen); | |
249 | } | |
250 | ||
251 | static void | |
252 | ShadowCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgn) | |
253 | { | |
254 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
255 | ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); | |
256 | int num = 0; | |
257 | RegionRec rgnDst; | |
258 | ||
259 | if (pPriv->vtSema) { | |
260 | RegionNull(&rgnDst); | |
261 | RegionCopy(&rgnDst, prgn); | |
262 | ||
263 | RegionTranslate(&rgnDst, | |
264 | pWin->drawable.x - ptOldOrg.x, | |
265 | pWin->drawable.y - ptOldOrg.y); | |
266 | RegionIntersect(&rgnDst, &pWin->borderClip, &rgnDst); | |
267 | if ((num = RegionNumRects(&rgnDst))) { | |
268 | if (pPriv->preRefresh) | |
269 | (*pPriv->preRefresh) (pPriv->pScrn, num, RegionRects(&rgnDst)); | |
270 | } | |
271 | else { | |
272 | RegionUninit(&rgnDst); | |
273 | } | |
274 | } | |
275 | ||
276 | pScreen->CopyWindow = pPriv->CopyWindow; | |
277 | (*pScreen->CopyWindow) (pWin, ptOldOrg, prgn); | |
278 | pScreen->CopyWindow = ShadowCopyWindow; | |
279 | ||
280 | if (num) { | |
281 | if (pPriv->postRefresh) | |
282 | (*pPriv->postRefresh) (pPriv->pScrn, num, RegionRects(&rgnDst)); | |
283 | RegionUninit(&rgnDst); | |
284 | } | |
285 | } | |
286 | ||
287 | static void | |
288 | ShadowComposite(CARD8 op, | |
289 | PicturePtr pSrc, | |
290 | PicturePtr pMask, | |
291 | PicturePtr pDst, | |
292 | INT16 xSrc, | |
293 | INT16 ySrc, | |
294 | INT16 xMask, | |
295 | INT16 yMask, | |
296 | INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) | |
297 | { | |
298 | ScreenPtr pScreen = pDst->pDrawable->pScreen; | |
299 | ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); | |
300 | PictureScreenPtr ps = GetPictureScreen(pScreen); | |
301 | BoxRec box; | |
302 | BoxPtr extents; | |
303 | Bool boxNotEmpty = FALSE; | |
304 | ||
305 | if (pPriv->vtSema && pDst->pDrawable->type == DRAWABLE_WINDOW) { | |
306 | ||
307 | box.x1 = pDst->pDrawable->x + xDst; | |
308 | box.y1 = pDst->pDrawable->y + yDst; | |
309 | box.x2 = box.x1 + width; | |
310 | box.y2 = box.y1 + height; | |
311 | ||
312 | extents = &pDst->pCompositeClip->extents; | |
313 | if (box.x1 < extents->x1) | |
314 | box.x1 = extents->x1; | |
315 | if (box.x2 > extents->x2) | |
316 | box.x2 = extents->x2; | |
317 | if (box.y1 < extents->y1) | |
318 | box.y1 = extents->y1; | |
319 | if (box.y2 > extents->y2) | |
320 | box.y2 = extents->y2; | |
321 | ||
322 | if (BOX_NOT_EMPTY(box)) { | |
323 | if (pPriv->preRefresh) | |
324 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
325 | boxNotEmpty = TRUE; | |
326 | } | |
327 | } | |
328 | ||
329 | ps->Composite = pPriv->Composite; | |
330 | (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, | |
331 | xMask, yMask, xDst, yDst, width, height); | |
332 | ps->Composite = ShadowComposite; | |
333 | ||
334 | if (pPriv->postRefresh && boxNotEmpty) { | |
335 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
336 | } | |
337 | } | |
338 | ||
339 | /**********************************************************/ | |
340 | ||
341 | static void ShadowValidateGC(GCPtr, unsigned long, DrawablePtr); | |
342 | static void ShadowChangeGC(GCPtr, unsigned long); | |
343 | static void ShadowCopyGC(GCPtr, unsigned long, GCPtr); | |
344 | static void ShadowDestroyGC(GCPtr); | |
345 | static void ShadowChangeClip(GCPtr, int, pointer, int); | |
346 | static void ShadowDestroyClip(GCPtr); | |
347 | static void ShadowCopyClip(GCPtr, GCPtr); | |
348 | ||
349 | GCFuncs ShadowGCFuncs = { | |
350 | ShadowValidateGC, ShadowChangeGC, ShadowCopyGC, ShadowDestroyGC, | |
351 | ShadowChangeClip, ShadowDestroyClip, ShadowCopyClip | |
352 | }; | |
353 | ||
354 | extern GCOps ShadowGCOps; | |
355 | ||
356 | static Bool | |
357 | ShadowCreateGC(GCPtr pGC) | |
358 | { | |
359 | ScreenPtr pScreen = pGC->pScreen; | |
360 | ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); | |
361 | ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC); | |
362 | Bool ret; | |
363 | ||
364 | pScreen->CreateGC = pPriv->CreateGC; | |
365 | if ((ret = (*pScreen->CreateGC) (pGC))) { | |
366 | pGCPriv->ops = NULL; | |
367 | pGCPriv->funcs = pGC->funcs; | |
368 | pGC->funcs = &ShadowGCFuncs; | |
369 | } | |
370 | pScreen->CreateGC = ShadowCreateGC; | |
371 | ||
372 | return ret; | |
373 | } | |
374 | ||
375 | static void | |
376 | ShadowValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) | |
377 | { | |
378 | SHADOW_GC_FUNC_PROLOGUE(pGC); | |
379 | (*pGC->funcs->ValidateGC) (pGC, changes, pDraw); | |
380 | if (pDraw->type == DRAWABLE_WINDOW) | |
381 | pGCPriv->ops = pGC->ops; /* just so it's not NULL */ | |
382 | else | |
383 | pGCPriv->ops = NULL; | |
384 | SHADOW_GC_FUNC_EPILOGUE(pGC); | |
385 | } | |
386 | ||
387 | static void | |
388 | ShadowDestroyGC(GCPtr pGC) | |
389 | { | |
390 | SHADOW_GC_FUNC_PROLOGUE(pGC); | |
391 | (*pGC->funcs->DestroyGC) (pGC); | |
392 | SHADOW_GC_FUNC_EPILOGUE(pGC); | |
393 | } | |
394 | ||
395 | static void | |
396 | ShadowChangeGC(GCPtr pGC, unsigned long mask) | |
397 | { | |
398 | SHADOW_GC_FUNC_PROLOGUE(pGC); | |
399 | (*pGC->funcs->ChangeGC) (pGC, mask); | |
400 | SHADOW_GC_FUNC_EPILOGUE(pGC); | |
401 | } | |
402 | ||
403 | static void | |
404 | ShadowCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) | |
405 | { | |
406 | SHADOW_GC_FUNC_PROLOGUE(pGCDst); | |
407 | (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); | |
408 | SHADOW_GC_FUNC_EPILOGUE(pGCDst); | |
409 | } | |
410 | ||
411 | static void | |
412 | ShadowChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects) | |
413 | { | |
414 | SHADOW_GC_FUNC_PROLOGUE(pGC); | |
415 | (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); | |
416 | SHADOW_GC_FUNC_EPILOGUE(pGC); | |
417 | } | |
418 | ||
419 | static void | |
420 | ShadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc) | |
421 | { | |
422 | SHADOW_GC_FUNC_PROLOGUE(pgcDst); | |
423 | (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc); | |
424 | SHADOW_GC_FUNC_EPILOGUE(pgcDst); | |
425 | } | |
426 | ||
427 | static void | |
428 | ShadowDestroyClip(GCPtr pGC) | |
429 | { | |
430 | SHADOW_GC_FUNC_PROLOGUE(pGC); | |
431 | (*pGC->funcs->DestroyClip) (pGC); | |
432 | SHADOW_GC_FUNC_EPILOGUE(pGC); | |
433 | } | |
434 | ||
435 | /**********************************************************/ | |
436 | ||
437 | static void | |
438 | ShadowFillSpans(DrawablePtr pDraw, | |
439 | GC * pGC, | |
440 | int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted) | |
441 | { | |
442 | SHADOW_GC_OP_PROLOGUE(pGC); | |
443 | ||
444 | if (IS_VISIBLE(pDraw) && nInit) { | |
445 | DDXPointPtr ppt = pptInit; | |
446 | int *pwidth = pwidthInit; | |
447 | int i = nInit; | |
448 | BoxRec box; | |
449 | Bool boxNotEmpty = FALSE; | |
450 | ||
451 | box.x1 = ppt->x; | |
452 | box.x2 = box.x1 + *pwidth; | |
453 | box.y2 = box.y1 = ppt->y; | |
454 | ||
455 | while (--i) { | |
456 | ppt++; | |
457 | pwidth++; | |
458 | if (box.x1 > ppt->x) | |
459 | box.x1 = ppt->x; | |
460 | if (box.x2 < (ppt->x + *pwidth)) | |
461 | box.x2 = ppt->x + *pwidth; | |
462 | if (box.y1 > ppt->y) | |
463 | box.y1 = ppt->y; | |
464 | else if (box.y2 < ppt->y) | |
465 | box.y2 = ppt->y; | |
466 | } | |
467 | ||
468 | box.y2++; | |
469 | ||
470 | if (!pGC->miTranslate) { | |
471 | TRANSLATE_BOX(box, pDraw); | |
472 | } | |
473 | TRIM_BOX(box, pGC); | |
474 | ||
475 | if (BOX_NOT_EMPTY(box)) { | |
476 | if (pPriv->preRefresh) | |
477 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
478 | boxNotEmpty = TRUE; | |
479 | } | |
480 | ||
481 | (*pGC->ops->FillSpans) (pDraw, pGC, nInit, pptInit, pwidthInit, | |
482 | fSorted); | |
483 | ||
484 | if (boxNotEmpty && pPriv->postRefresh) | |
485 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
486 | } | |
487 | else | |
488 | (*pGC->ops->FillSpans) (pDraw, pGC, nInit, pptInit, pwidthInit, | |
489 | fSorted); | |
490 | ||
491 | SHADOW_GC_OP_EPILOGUE(pGC); | |
492 | } | |
493 | ||
494 | static void | |
495 | ShadowSetSpans(DrawablePtr pDraw, | |
496 | GCPtr pGC, | |
497 | char *pcharsrc, | |
498 | DDXPointPtr pptInit, int *pwidthInit, int nspans, int fSorted) | |
499 | { | |
500 | SHADOW_GC_OP_PROLOGUE(pGC); | |
501 | ||
502 | if (IS_VISIBLE(pDraw) && nspans) { | |
503 | DDXPointPtr ppt = pptInit; | |
504 | int *pwidth = pwidthInit; | |
505 | int i = nspans; | |
506 | BoxRec box; | |
507 | Bool boxNotEmpty = FALSE; | |
508 | ||
509 | box.x1 = ppt->x; | |
510 | box.x2 = box.x1 + *pwidth; | |
511 | box.y2 = box.y1 = ppt->y; | |
512 | ||
513 | while (--i) { | |
514 | ppt++; | |
515 | pwidth++; | |
516 | if (box.x1 > ppt->x) | |
517 | box.x1 = ppt->x; | |
518 | if (box.x2 < (ppt->x + *pwidth)) | |
519 | box.x2 = ppt->x + *pwidth; | |
520 | if (box.y1 > ppt->y) | |
521 | box.y1 = ppt->y; | |
522 | else if (box.y2 < ppt->y) | |
523 | box.y2 = ppt->y; | |
524 | } | |
525 | ||
526 | box.y2++; | |
527 | ||
528 | if (!pGC->miTranslate) { | |
529 | TRANSLATE_BOX(box, pDraw); | |
530 | } | |
531 | TRIM_BOX(box, pGC); | |
532 | ||
533 | if (BOX_NOT_EMPTY(box)) { | |
534 | if (pPriv->preRefresh) | |
535 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
536 | boxNotEmpty = TRUE; | |
537 | } | |
538 | ||
539 | (*pGC->ops->SetSpans) (pDraw, pGC, pcharsrc, pptInit, | |
540 | pwidthInit, nspans, fSorted); | |
541 | ||
542 | if (boxNotEmpty && pPriv->postRefresh) | |
543 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
544 | } | |
545 | else | |
546 | (*pGC->ops->SetSpans) (pDraw, pGC, pcharsrc, pptInit, | |
547 | pwidthInit, nspans, fSorted); | |
548 | ||
549 | SHADOW_GC_OP_EPILOGUE(pGC); | |
550 | } | |
551 | ||
552 | static void | |
553 | ShadowPutImage(DrawablePtr pDraw, | |
554 | GCPtr pGC, | |
555 | int depth, | |
556 | int x, int y, int w, int h, | |
557 | int leftPad, int format, char *pImage) | |
558 | { | |
559 | BoxRec box; | |
560 | Bool boxNotEmpty = FALSE; | |
561 | ||
562 | SHADOW_GC_OP_PROLOGUE(pGC); | |
563 | ||
564 | if (IS_VISIBLE(pDraw)) { | |
565 | box.x1 = x + pDraw->x; | |
566 | box.x2 = box.x1 + w; | |
567 | box.y1 = y + pDraw->y; | |
568 | box.y2 = box.y1 + h; | |
569 | ||
570 | TRIM_BOX(box, pGC); | |
571 | if (BOX_NOT_EMPTY(box)) { | |
572 | if (pPriv->preRefresh) | |
573 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
574 | boxNotEmpty = TRUE; | |
575 | } | |
576 | } | |
577 | ||
578 | (*pGC->ops->PutImage) (pDraw, pGC, depth, x, y, w, h, | |
579 | leftPad, format, pImage); | |
580 | ||
581 | if (boxNotEmpty && pPriv->postRefresh) | |
582 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
583 | ||
584 | SHADOW_GC_OP_EPILOGUE(pGC); | |
585 | ||
586 | } | |
587 | ||
588 | static RegionPtr | |
589 | ShadowCopyArea(DrawablePtr pSrc, | |
590 | DrawablePtr pDst, | |
591 | GC * pGC, | |
592 | int srcx, int srcy, int width, int height, int dstx, int dsty) | |
593 | { | |
594 | RegionPtr ret; | |
595 | BoxRec box; | |
596 | Bool boxNotEmpty = FALSE; | |
597 | ||
598 | SHADOW_GC_OP_PROLOGUE(pGC); | |
599 | ||
600 | if (IS_VISIBLE(pDst)) { | |
601 | box.x1 = dstx + pDst->x; | |
602 | box.x2 = box.x1 + width; | |
603 | box.y1 = dsty + pDst->y; | |
604 | box.y2 = box.y1 + height; | |
605 | ||
606 | TRIM_BOX(box, pGC); | |
607 | if (BOX_NOT_EMPTY(box)) { | |
608 | if (pPriv->preRefresh) | |
609 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
610 | boxNotEmpty = TRUE; | |
611 | } | |
612 | } | |
613 | ||
614 | ret = (*pGC->ops->CopyArea) (pSrc, pDst, | |
615 | pGC, srcx, srcy, width, height, dstx, dsty); | |
616 | ||
617 | if (boxNotEmpty && pPriv->postRefresh) | |
618 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
619 | ||
620 | SHADOW_GC_OP_EPILOGUE(pGC); | |
621 | ||
622 | return ret; | |
623 | } | |
624 | ||
625 | static RegionPtr | |
626 | ShadowCopyPlane(DrawablePtr pSrc, | |
627 | DrawablePtr pDst, | |
628 | GCPtr pGC, | |
629 | int srcx, int srcy, | |
630 | int width, int height, | |
631 | int dstx, int dsty, unsigned long bitPlane) | |
632 | { | |
633 | RegionPtr ret; | |
634 | BoxRec box; | |
635 | Bool boxNotEmpty = FALSE; | |
636 | ||
637 | SHADOW_GC_OP_PROLOGUE(pGC); | |
638 | ||
639 | if (IS_VISIBLE(pDst)) { | |
640 | box.x1 = dstx + pDst->x; | |
641 | box.x2 = box.x1 + width; | |
642 | box.y1 = dsty + pDst->y; | |
643 | box.y2 = box.y1 + height; | |
644 | ||
645 | TRIM_BOX(box, pGC); | |
646 | if (BOX_NOT_EMPTY(box)) { | |
647 | if (pPriv->preRefresh) | |
648 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
649 | boxNotEmpty = TRUE; | |
650 | } | |
651 | } | |
652 | ||
653 | ret = (*pGC->ops->CopyPlane) (pSrc, pDst, | |
654 | pGC, srcx, srcy, width, height, dstx, dsty, | |
655 | bitPlane); | |
656 | ||
657 | if (boxNotEmpty && pPriv->postRefresh) | |
658 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
659 | ||
660 | SHADOW_GC_OP_EPILOGUE(pGC); | |
661 | ||
662 | return ret; | |
663 | } | |
664 | ||
665 | static void | |
666 | ShadowPolyPoint(DrawablePtr pDraw, | |
667 | GCPtr pGC, int mode, int nptInit, xPoint * pptInit) | |
668 | { | |
669 | BoxRec box; | |
670 | Bool boxNotEmpty = FALSE; | |
671 | ||
672 | SHADOW_GC_OP_PROLOGUE(pGC); | |
673 | ||
674 | if (IS_VISIBLE(pDraw) && nptInit) { | |
675 | xPoint *ppt = pptInit; | |
676 | int npt = nptInit; | |
677 | ||
678 | box.x2 = box.x1 = pptInit->x; | |
679 | box.y2 = box.y1 = pptInit->y; | |
680 | ||
681 | /* this could be slow if the points were spread out */ | |
682 | ||
683 | while (--npt) { | |
684 | ppt++; | |
685 | if (box.x1 > ppt->x) | |
686 | box.x1 = ppt->x; | |
687 | else if (box.x2 < ppt->x) | |
688 | box.x2 = ppt->x; | |
689 | if (box.y1 > ppt->y) | |
690 | box.y1 = ppt->y; | |
691 | else if (box.y2 < ppt->y) | |
692 | box.y2 = ppt->y; | |
693 | } | |
694 | ||
695 | box.x2++; | |
696 | box.y2++; | |
697 | ||
698 | TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); | |
699 | if (BOX_NOT_EMPTY(box)) { | |
700 | if (pPriv->preRefresh) | |
701 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
702 | boxNotEmpty = TRUE; | |
703 | } | |
704 | } | |
705 | ||
706 | (*pGC->ops->PolyPoint) (pDraw, pGC, mode, nptInit, pptInit); | |
707 | ||
708 | if (boxNotEmpty && pPriv->postRefresh) | |
709 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
710 | ||
711 | SHADOW_GC_OP_EPILOGUE(pGC); | |
712 | } | |
713 | ||
714 | static void | |
715 | ShadowPolylines(DrawablePtr pDraw, | |
716 | GCPtr pGC, int mode, int nptInit, DDXPointPtr pptInit) | |
717 | { | |
718 | BoxRec box; | |
719 | Bool boxNotEmpty = FALSE; | |
720 | ||
721 | SHADOW_GC_OP_PROLOGUE(pGC); | |
722 | ||
723 | if (IS_VISIBLE(pDraw) && nptInit) { | |
724 | DDXPointPtr ppt = pptInit; | |
725 | int npt = nptInit; | |
726 | int extra = pGC->lineWidth >> 1; | |
727 | ||
728 | box.x2 = box.x1 = pptInit->x; | |
729 | box.y2 = box.y1 = pptInit->y; | |
730 | ||
731 | if (npt > 1) { | |
732 | if (pGC->joinStyle == JoinMiter) | |
733 | extra = 6 * pGC->lineWidth; | |
734 | else if (pGC->capStyle == CapProjecting) | |
735 | extra = pGC->lineWidth; | |
736 | } | |
737 | ||
738 | if (mode == CoordModePrevious) { | |
739 | int x = box.x1; | |
740 | int y = box.y1; | |
741 | ||
742 | while (--npt) { | |
743 | ppt++; | |
744 | x += ppt->x; | |
745 | y += ppt->y; | |
746 | if (box.x1 > x) | |
747 | box.x1 = x; | |
748 | else if (box.x2 < x) | |
749 | box.x2 = x; | |
750 | if (box.y1 > y) | |
751 | box.y1 = y; | |
752 | else if (box.y2 < y) | |
753 | box.y2 = y; | |
754 | } | |
755 | } | |
756 | else { | |
757 | while (--npt) { | |
758 | ppt++; | |
759 | if (box.x1 > ppt->x) | |
760 | box.x1 = ppt->x; | |
761 | else if (box.x2 < ppt->x) | |
762 | box.x2 = ppt->x; | |
763 | if (box.y1 > ppt->y) | |
764 | box.y1 = ppt->y; | |
765 | else if (box.y2 < ppt->y) | |
766 | box.y2 = ppt->y; | |
767 | } | |
768 | } | |
769 | ||
770 | box.x2++; | |
771 | box.y2++; | |
772 | ||
773 | if (extra) { | |
774 | box.x1 -= extra; | |
775 | box.x2 += extra; | |
776 | box.y1 -= extra; | |
777 | box.y2 += extra; | |
778 | } | |
779 | ||
780 | TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); | |
781 | if (BOX_NOT_EMPTY(box)) { | |
782 | if (pPriv->preRefresh) | |
783 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
784 | boxNotEmpty = TRUE; | |
785 | } | |
786 | } | |
787 | ||
788 | (*pGC->ops->Polylines) (pDraw, pGC, mode, nptInit, pptInit); | |
789 | ||
790 | if (boxNotEmpty && pPriv->postRefresh) | |
791 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
792 | ||
793 | SHADOW_GC_OP_EPILOGUE(pGC); | |
794 | } | |
795 | ||
796 | static void | |
797 | ShadowPolySegment(DrawablePtr pDraw, | |
798 | GCPtr pGC, int nsegInit, xSegment * pSegInit) | |
799 | { | |
800 | BoxRec box; | |
801 | Bool boxNotEmpty = FALSE; | |
802 | ||
803 | SHADOW_GC_OP_PROLOGUE(pGC); | |
804 | ||
805 | if (IS_VISIBLE(pDraw) && nsegInit) { | |
806 | int extra = pGC->lineWidth; | |
807 | xSegment *pSeg = pSegInit; | |
808 | int nseg = nsegInit; | |
809 | ||
810 | if (pGC->capStyle != CapProjecting) | |
811 | extra >>= 1; | |
812 | ||
813 | if (pSeg->x2 > pSeg->x1) { | |
814 | box.x1 = pSeg->x1; | |
815 | box.x2 = pSeg->x2; | |
816 | } | |
817 | else { | |
818 | box.x2 = pSeg->x1; | |
819 | box.x1 = pSeg->x2; | |
820 | } | |
821 | ||
822 | if (pSeg->y2 > pSeg->y1) { | |
823 | box.y1 = pSeg->y1; | |
824 | box.y2 = pSeg->y2; | |
825 | } | |
826 | else { | |
827 | box.y2 = pSeg->y1; | |
828 | box.y1 = pSeg->y2; | |
829 | } | |
830 | ||
831 | while (--nseg) { | |
832 | pSeg++; | |
833 | if (pSeg->x2 > pSeg->x1) { | |
834 | if (pSeg->x1 < box.x1) | |
835 | box.x1 = pSeg->x1; | |
836 | if (pSeg->x2 > box.x2) | |
837 | box.x2 = pSeg->x2; | |
838 | } | |
839 | else { | |
840 | if (pSeg->x2 < box.x1) | |
841 | box.x1 = pSeg->x2; | |
842 | if (pSeg->x1 > box.x2) | |
843 | box.x2 = pSeg->x1; | |
844 | } | |
845 | if (pSeg->y2 > pSeg->y1) { | |
846 | if (pSeg->y1 < box.y1) | |
847 | box.y1 = pSeg->y1; | |
848 | if (pSeg->y2 > box.y2) | |
849 | box.y2 = pSeg->y2; | |
850 | } | |
851 | else { | |
852 | if (pSeg->y2 < box.y1) | |
853 | box.y1 = pSeg->y2; | |
854 | if (pSeg->y1 > box.y2) | |
855 | box.y2 = pSeg->y1; | |
856 | } | |
857 | } | |
858 | ||
859 | box.x2++; | |
860 | box.y2++; | |
861 | ||
862 | if (extra) { | |
863 | box.x1 -= extra; | |
864 | box.x2 += extra; | |
865 | box.y1 -= extra; | |
866 | box.y2 += extra; | |
867 | } | |
868 | ||
869 | TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); | |
870 | if (BOX_NOT_EMPTY(box)) { | |
871 | if (pPriv->preRefresh) | |
872 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
873 | boxNotEmpty = TRUE; | |
874 | } | |
875 | } | |
876 | ||
877 | (*pGC->ops->PolySegment) (pDraw, pGC, nsegInit, pSegInit); | |
878 | ||
879 | if (boxNotEmpty && pPriv->postRefresh) | |
880 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
881 | ||
882 | SHADOW_GC_OP_EPILOGUE(pGC); | |
883 | } | |
884 | ||
885 | static void | |
886 | ShadowPolyRectangle(DrawablePtr pDraw, | |
887 | GCPtr pGC, int nRectsInit, xRectangle *pRectsInit) | |
888 | { | |
889 | BoxRec box; | |
890 | BoxPtr pBoxInit = NULL; | |
891 | Bool boxNotEmpty = FALSE; | |
892 | int num = 0; | |
893 | ||
894 | SHADOW_GC_OP_PROLOGUE(pGC); | |
895 | ||
896 | if (IS_VISIBLE(pDraw) && nRectsInit) { | |
897 | xRectangle *pRects = pRectsInit; | |
898 | int nRects = nRectsInit; | |
899 | ||
900 | if (nRects >= 32) { | |
901 | int extra = pGC->lineWidth >> 1; | |
902 | ||
903 | box.x1 = pRects->x; | |
904 | box.x2 = box.x1 + pRects->width; | |
905 | box.y1 = pRects->y; | |
906 | box.y2 = box.y1 + pRects->height; | |
907 | ||
908 | while (--nRects) { | |
909 | pRects++; | |
910 | if (box.x1 > pRects->x) | |
911 | box.x1 = pRects->x; | |
912 | if (box.x2 < (pRects->x + pRects->width)) | |
913 | box.x2 = pRects->x + pRects->width; | |
914 | if (box.y1 > pRects->y) | |
915 | box.y1 = pRects->y; | |
916 | if (box.y2 < (pRects->y + pRects->height)) | |
917 | box.y2 = pRects->y + pRects->height; | |
918 | } | |
919 | ||
920 | if (extra) { | |
921 | box.x1 -= extra; | |
922 | box.x2 += extra; | |
923 | box.y1 -= extra; | |
924 | box.y2 += extra; | |
925 | } | |
926 | ||
927 | box.x2++; | |
928 | box.y2++; | |
929 | ||
930 | TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); | |
931 | if (BOX_NOT_EMPTY(box)) { | |
932 | if (pPriv->preRefresh) | |
933 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
934 | boxNotEmpty = TRUE; | |
935 | } | |
936 | } | |
937 | else { | |
938 | BoxPtr pbox; | |
939 | int offset1, offset2, offset3; | |
940 | ||
941 | offset2 = pGC->lineWidth; | |
942 | if (!offset2) | |
943 | offset2 = 1; | |
944 | offset1 = offset2 >> 1; | |
945 | offset3 = offset2 - offset1; | |
946 | ||
947 | pBoxInit = (BoxPtr) malloc(nRects * 4 * sizeof(BoxRec)); | |
948 | pbox = pBoxInit; | |
949 | ||
950 | while (nRects--) { | |
951 | pbox->x1 = pRects->x - offset1; | |
952 | pbox->y1 = pRects->y - offset1; | |
953 | pbox->x2 = pbox->x1 + pRects->width + offset2; | |
954 | pbox->y2 = pbox->y1 + offset2; | |
955 | TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); | |
956 | if (BOX_NOT_EMPTY((*pbox))) { | |
957 | num++; | |
958 | pbox++; | |
959 | } | |
960 | ||
961 | pbox->x1 = pRects->x - offset1; | |
962 | pbox->y1 = pRects->y + offset3; | |
963 | pbox->x2 = pbox->x1 + offset2; | |
964 | pbox->y2 = pbox->y1 + pRects->height - offset2; | |
965 | TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); | |
966 | if (BOX_NOT_EMPTY((*pbox))) { | |
967 | num++; | |
968 | pbox++; | |
969 | } | |
970 | ||
971 | pbox->x1 = pRects->x + pRects->width - offset1; | |
972 | pbox->y1 = pRects->y + offset3; | |
973 | pbox->x2 = pbox->x1 + offset2; | |
974 | pbox->y2 = pbox->y1 + pRects->height - offset2; | |
975 | TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); | |
976 | if (BOX_NOT_EMPTY((*pbox))) { | |
977 | num++; | |
978 | pbox++; | |
979 | } | |
980 | ||
981 | pbox->x1 = pRects->x - offset1; | |
982 | pbox->y1 = pRects->y + pRects->height - offset1; | |
983 | pbox->x2 = pbox->x1 + pRects->width + offset2; | |
984 | pbox->y2 = pbox->y1 + offset2; | |
985 | TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); | |
986 | if (BOX_NOT_EMPTY((*pbox))) { | |
987 | num++; | |
988 | pbox++; | |
989 | } | |
990 | ||
991 | pRects++; | |
992 | } | |
993 | ||
994 | if (num) { | |
995 | if (pPriv->preRefresh) | |
996 | (*pPriv->preRefresh) (pPriv->pScrn, num, pBoxInit); | |
997 | } | |
998 | else { | |
999 | free(pBoxInit); | |
1000 | } | |
1001 | } | |
1002 | } | |
1003 | ||
1004 | (*pGC->ops->PolyRectangle) (pDraw, pGC, nRectsInit, pRectsInit); | |
1005 | ||
1006 | if (boxNotEmpty && pPriv->postRefresh) { | |
1007 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1008 | } | |
1009 | else if (num) { | |
1010 | if (pPriv->postRefresh) | |
1011 | (*pPriv->postRefresh) (pPriv->pScrn, num, pBoxInit); | |
1012 | free(pBoxInit); | |
1013 | } | |
1014 | ||
1015 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1016 | ||
1017 | } | |
1018 | ||
1019 | static void | |
1020 | ShadowPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcsInit, xArc * parcsInit) | |
1021 | { | |
1022 | BoxRec box; | |
1023 | Bool boxNotEmpty = FALSE; | |
1024 | ||
1025 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1026 | ||
1027 | if (IS_VISIBLE(pDraw) && narcsInit) { | |
1028 | int narcs = narcsInit; | |
1029 | xArc *parcs = parcsInit; | |
1030 | int extra = pGC->lineWidth >> 1; | |
1031 | ||
1032 | box.x1 = parcs->x; | |
1033 | box.x2 = box.x1 + parcs->width; | |
1034 | box.y1 = parcs->y; | |
1035 | box.y2 = box.y1 + parcs->height; | |
1036 | ||
1037 | /* should I break these up instead ? */ | |
1038 | ||
1039 | while (--narcs) { | |
1040 | parcs++; | |
1041 | if (box.x1 > parcs->x) | |
1042 | box.x1 = parcs->x; | |
1043 | if (box.x2 < (parcs->x + parcs->width)) | |
1044 | box.x2 = parcs->x + parcs->width; | |
1045 | if (box.y1 > parcs->y) | |
1046 | box.y1 = parcs->y; | |
1047 | if (box.y2 < (parcs->y + parcs->height)) | |
1048 | box.y2 = parcs->y + parcs->height; | |
1049 | } | |
1050 | ||
1051 | if (extra) { | |
1052 | box.x1 -= extra; | |
1053 | box.x2 += extra; | |
1054 | box.y1 -= extra; | |
1055 | box.y2 += extra; | |
1056 | } | |
1057 | ||
1058 | box.x2++; | |
1059 | box.y2++; | |
1060 | ||
1061 | TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); | |
1062 | if (BOX_NOT_EMPTY(box)) { | |
1063 | if (pPriv->preRefresh) | |
1064 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1065 | boxNotEmpty = TRUE; | |
1066 | } | |
1067 | } | |
1068 | ||
1069 | (*pGC->ops->PolyArc) (pDraw, pGC, narcsInit, parcsInit); | |
1070 | ||
1071 | if (boxNotEmpty && pPriv->postRefresh) | |
1072 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1073 | ||
1074 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1075 | ||
1076 | } | |
1077 | ||
1078 | static void | |
1079 | ShadowFillPolygon(DrawablePtr pDraw, | |
1080 | GCPtr pGC, | |
1081 | int shape, int mode, int count, DDXPointPtr pptInit) | |
1082 | { | |
1083 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1084 | ||
1085 | if (IS_VISIBLE(pDraw) && (count > 2)) { | |
1086 | DDXPointPtr ppt = pptInit; | |
1087 | int i = count; | |
1088 | BoxRec box; | |
1089 | Bool boxNotEmpty = FALSE; | |
1090 | ||
1091 | box.x2 = box.x1 = ppt->x; | |
1092 | box.y2 = box.y1 = ppt->y; | |
1093 | ||
1094 | if (mode != CoordModeOrigin) { | |
1095 | int x = box.x1; | |
1096 | int y = box.y1; | |
1097 | ||
1098 | while (--i) { | |
1099 | ppt++; | |
1100 | x += ppt->x; | |
1101 | y += ppt->y; | |
1102 | if (box.x1 > x) | |
1103 | box.x1 = x; | |
1104 | else if (box.x2 < x) | |
1105 | box.x2 = x; | |
1106 | if (box.y1 > y) | |
1107 | box.y1 = y; | |
1108 | else if (box.y2 < y) | |
1109 | box.y2 = y; | |
1110 | } | |
1111 | } | |
1112 | else { | |
1113 | while (--i) { | |
1114 | ppt++; | |
1115 | if (box.x1 > ppt->x) | |
1116 | box.x1 = ppt->x; | |
1117 | else if (box.x2 < ppt->x) | |
1118 | box.x2 = ppt->x; | |
1119 | if (box.y1 > ppt->y) | |
1120 | box.y1 = ppt->y; | |
1121 | else if (box.y2 < ppt->y) | |
1122 | box.y2 = ppt->y; | |
1123 | } | |
1124 | } | |
1125 | ||
1126 | box.x2++; | |
1127 | box.y2++; | |
1128 | ||
1129 | TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); | |
1130 | if (BOX_NOT_EMPTY(box)) { | |
1131 | if (pPriv->preRefresh) | |
1132 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1133 | boxNotEmpty = TRUE; | |
1134 | } | |
1135 | ||
1136 | (*pGC->ops->FillPolygon) (pDraw, pGC, shape, mode, count, pptInit); | |
1137 | ||
1138 | if (boxNotEmpty && pPriv->postRefresh) | |
1139 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1140 | } | |
1141 | else | |
1142 | (*pGC->ops->FillPolygon) (pDraw, pGC, shape, mode, count, pptInit); | |
1143 | ||
1144 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1145 | } | |
1146 | ||
1147 | static void | |
1148 | ShadowPolyFillRect(DrawablePtr pDraw, | |
1149 | GCPtr pGC, int nRectsInit, xRectangle *pRectsInit) | |
1150 | { | |
1151 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1152 | ||
1153 | if (IS_VISIBLE(pDraw) && nRectsInit) { | |
1154 | BoxRec box; | |
1155 | Bool boxNotEmpty = FALSE; | |
1156 | xRectangle *pRects = pRectsInit; | |
1157 | int nRects = nRectsInit; | |
1158 | ||
1159 | box.x1 = pRects->x; | |
1160 | box.x2 = box.x1 + pRects->width; | |
1161 | box.y1 = pRects->y; | |
1162 | box.y2 = box.y1 + pRects->height; | |
1163 | ||
1164 | while (--nRects) { | |
1165 | pRects++; | |
1166 | if (box.x1 > pRects->x) | |
1167 | box.x1 = pRects->x; | |
1168 | if (box.x2 < (pRects->x + pRects->width)) | |
1169 | box.x2 = pRects->x + pRects->width; | |
1170 | if (box.y1 > pRects->y) | |
1171 | box.y1 = pRects->y; | |
1172 | if (box.y2 < (pRects->y + pRects->height)) | |
1173 | box.y2 = pRects->y + pRects->height; | |
1174 | } | |
1175 | ||
1176 | /* cfb messes with the pRectsInit so we have to do our | |
1177 | calculations first */ | |
1178 | ||
1179 | TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); | |
1180 | if (BOX_NOT_EMPTY(box)) { | |
1181 | if (pPriv->preRefresh) | |
1182 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1183 | boxNotEmpty = TRUE; | |
1184 | } | |
1185 | ||
1186 | (*pGC->ops->PolyFillRect) (pDraw, pGC, nRectsInit, pRectsInit); | |
1187 | ||
1188 | if (boxNotEmpty && pPriv->postRefresh) | |
1189 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1190 | } | |
1191 | else | |
1192 | (*pGC->ops->PolyFillRect) (pDraw, pGC, nRectsInit, pRectsInit); | |
1193 | ||
1194 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1195 | } | |
1196 | ||
1197 | static void | |
1198 | ShadowPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcsInit, xArc * parcsInit) | |
1199 | { | |
1200 | BoxRec box; | |
1201 | Bool boxNotEmpty = FALSE; | |
1202 | ||
1203 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1204 | ||
1205 | if (IS_VISIBLE(pDraw) && narcsInit) { | |
1206 | xArc *parcs = parcsInit; | |
1207 | int narcs = narcsInit; | |
1208 | ||
1209 | box.x1 = parcs->x; | |
1210 | box.x2 = box.x1 + parcs->width; | |
1211 | box.y1 = parcs->y; | |
1212 | box.y2 = box.y1 + parcs->height; | |
1213 | ||
1214 | /* should I break these up instead ? */ | |
1215 | ||
1216 | while (--narcs) { | |
1217 | parcs++; | |
1218 | if (box.x1 > parcs->x) | |
1219 | box.x1 = parcs->x; | |
1220 | if (box.x2 < (parcs->x + parcs->width)) | |
1221 | box.x2 = parcs->x + parcs->width; | |
1222 | if (box.y1 > parcs->y) | |
1223 | box.y1 = parcs->y; | |
1224 | if (box.y2 < (parcs->y + parcs->height)) | |
1225 | box.y2 = parcs->y + parcs->height; | |
1226 | } | |
1227 | ||
1228 | TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); | |
1229 | if (BOX_NOT_EMPTY(box)) { | |
1230 | if (pPriv->preRefresh) | |
1231 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1232 | boxNotEmpty = TRUE; | |
1233 | } | |
1234 | } | |
1235 | ||
1236 | (*pGC->ops->PolyFillArc) (pDraw, pGC, narcsInit, parcsInit); | |
1237 | ||
1238 | if (boxNotEmpty && pPriv->postRefresh) | |
1239 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1240 | ||
1241 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1242 | } | |
1243 | ||
1244 | static void | |
1245 | ShadowTextExtent(FontPtr pFont, int count, char *chars, | |
1246 | FontEncoding fontEncoding, BoxPtr box) | |
1247 | { | |
1248 | unsigned long n, i; | |
1249 | int w; | |
1250 | CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ | |
1251 | ||
1252 | GetGlyphs(pFont, (unsigned long) count, (unsigned char *) chars, | |
1253 | fontEncoding, &n, charinfo); | |
1254 | w = 0; | |
1255 | for (i = 0; i < n; i++) { | |
1256 | w += charinfo[i]->metrics.characterWidth; | |
1257 | } | |
1258 | if (i) { | |
1259 | w += charinfo[i - 1]->metrics.rightSideBearing; | |
1260 | } | |
1261 | ||
1262 | box->x1 = 0; | |
1263 | if (n) { | |
1264 | if (charinfo[0]->metrics.leftSideBearing < 0) { | |
1265 | box->x1 = charinfo[0]->metrics.leftSideBearing; | |
1266 | } | |
1267 | } | |
1268 | box->x2 = w; | |
1269 | box->y1 = -FONTMAXBOUNDS(pFont, ascent); | |
1270 | box->y2 = FONTMAXBOUNDS(pFont, descent); | |
1271 | } | |
1272 | ||
1273 | static void | |
1274 | ShadowFontToBox(BoxPtr BB, DrawablePtr pDrawable, GCPtr pGC, int x, int y, | |
1275 | int count, char *chars, int wide) | |
1276 | { | |
1277 | FontPtr pFont; | |
1278 | ||
1279 | pFont = pGC->font; | |
1280 | if (pFont->info.constantWidth) { | |
1281 | int ascent, descent, left, right = 0; | |
1282 | ||
1283 | ascent = max(pFont->info.fontAscent, pFont->info.maxbounds.ascent); | |
1284 | descent = max(pFont->info.fontDescent, pFont->info.maxbounds.descent); | |
1285 | left = pFont->info.maxbounds.leftSideBearing; | |
1286 | if (count > 0) { | |
1287 | right = (count - 1) * pFont->info.maxbounds.characterWidth; | |
1288 | } | |
1289 | right += pFont->info.maxbounds.rightSideBearing; | |
1290 | BB->x1 = | |
1291 | max(pDrawable->x + x - left, | |
1292 | RegionExtents(&((WindowPtr) pDrawable)->winSize)->x1); | |
1293 | BB->y1 = | |
1294 | max(pDrawable->y + y - ascent, | |
1295 | RegionExtents(&((WindowPtr) pDrawable)->winSize)->y1); | |
1296 | BB->x2 = | |
1297 | min(pDrawable->x + x + right, | |
1298 | RegionExtents(&((WindowPtr) pDrawable)->winSize)->x2); | |
1299 | BB->y2 = | |
1300 | min(pDrawable->y + y + descent, | |
1301 | RegionExtents(&((WindowPtr) pDrawable)->winSize)->y2); | |
1302 | } | |
1303 | else { | |
1304 | ShadowTextExtent(pFont, count, chars, wide ? (FONTLASTROW(pFont) == 0) | |
1305 | ? Linear16Bit : TwoD16Bit : Linear8Bit, BB); | |
1306 | BB->x1 = | |
1307 | max(pDrawable->x + x + BB->x1, | |
1308 | RegionExtents(&((WindowPtr) pDrawable)->winSize)->x1); | |
1309 | BB->y1 = | |
1310 | max(pDrawable->y + y + BB->y1, | |
1311 | RegionExtents(&((WindowPtr) pDrawable)->winSize)->y1); | |
1312 | BB->x2 = | |
1313 | min(pDrawable->x + x + BB->x2, | |
1314 | RegionExtents(&((WindowPtr) pDrawable)->winSize)->x2); | |
1315 | BB->y2 = | |
1316 | min(pDrawable->y + y + BB->y2, | |
1317 | RegionExtents(&((WindowPtr) pDrawable)->winSize)->y2); | |
1318 | } | |
1319 | } | |
1320 | ||
1321 | static int | |
1322 | ShadowPolyText8(DrawablePtr pDraw, | |
1323 | GCPtr pGC, int x, int y, int count, char *chars) | |
1324 | { | |
1325 | int width; | |
1326 | BoxRec box; | |
1327 | Bool boxNotEmpty = FALSE; | |
1328 | ||
1329 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1330 | ||
1331 | if (IS_VISIBLE(pDraw)) { | |
1332 | ShadowFontToBox(&box, pDraw, pGC, x, y, count, chars, 0); | |
1333 | ||
1334 | TRIM_BOX(box, pGC); | |
1335 | if (BOX_NOT_EMPTY(box)) { | |
1336 | if (pPriv->preRefresh) | |
1337 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1338 | boxNotEmpty = TRUE; | |
1339 | } | |
1340 | } | |
1341 | ||
1342 | width = (*pGC->ops->PolyText8) (pDraw, pGC, x, y, count, chars); | |
1343 | ||
1344 | if (boxNotEmpty && pPriv->postRefresh) | |
1345 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1346 | ||
1347 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1348 | ||
1349 | return width; | |
1350 | } | |
1351 | ||
1352 | static int | |
1353 | ShadowPolyText16(DrawablePtr pDraw, | |
1354 | GCPtr pGC, int x, int y, int count, unsigned short *chars) | |
1355 | { | |
1356 | int width; | |
1357 | BoxRec box; | |
1358 | Bool boxNotEmpty = FALSE; | |
1359 | ||
1360 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1361 | ||
1362 | if (IS_VISIBLE(pDraw)) { | |
1363 | ShadowFontToBox(&box, pDraw, pGC, x, y, count, (char *) chars, 1); | |
1364 | ||
1365 | TRIM_BOX(box, pGC); | |
1366 | if (BOX_NOT_EMPTY(box)) { | |
1367 | if (pPriv->preRefresh) | |
1368 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1369 | boxNotEmpty = TRUE; | |
1370 | } | |
1371 | } | |
1372 | ||
1373 | width = (*pGC->ops->PolyText16) (pDraw, pGC, x, y, count, chars); | |
1374 | ||
1375 | if (boxNotEmpty && pPriv->postRefresh) | |
1376 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1377 | ||
1378 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1379 | ||
1380 | return width; | |
1381 | } | |
1382 | ||
1383 | static void | |
1384 | ShadowImageText8(DrawablePtr pDraw, | |
1385 | GCPtr pGC, int x, int y, int count, char *chars) | |
1386 | { | |
1387 | BoxRec box; | |
1388 | Bool boxNotEmpty = FALSE; | |
1389 | ||
1390 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1391 | ||
1392 | if (IS_VISIBLE(pDraw) && count) { | |
1393 | int top, bot, Min, Max; | |
1394 | ||
1395 | top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); | |
1396 | bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); | |
1397 | ||
1398 | Min = count * FONTMINBOUNDS(pGC->font, characterWidth); | |
1399 | if (Min > 0) | |
1400 | Min = 0; | |
1401 | Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); | |
1402 | if (Max < 0) | |
1403 | Max = 0; | |
1404 | ||
1405 | /* ugh */ | |
1406 | box.x1 = pDraw->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing); | |
1407 | box.x2 = pDraw->x + x + Max + | |
1408 | FONTMAXBOUNDS(pGC->font, rightSideBearing); | |
1409 | ||
1410 | box.y1 = pDraw->y + y - top; | |
1411 | box.y2 = pDraw->y + y + bot; | |
1412 | ||
1413 | TRIM_BOX(box, pGC); | |
1414 | if (BOX_NOT_EMPTY(box)) { | |
1415 | if (pPriv->preRefresh) | |
1416 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1417 | boxNotEmpty = TRUE; | |
1418 | } | |
1419 | } | |
1420 | ||
1421 | (*pGC->ops->ImageText8) (pDraw, pGC, x, y, count, chars); | |
1422 | ||
1423 | if (boxNotEmpty && pPriv->postRefresh) | |
1424 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1425 | ||
1426 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1427 | } | |
1428 | ||
1429 | static void | |
1430 | ShadowImageText16(DrawablePtr pDraw, | |
1431 | GCPtr pGC, int x, int y, int count, unsigned short *chars) | |
1432 | { | |
1433 | BoxRec box; | |
1434 | Bool boxNotEmpty = FALSE; | |
1435 | ||
1436 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1437 | ||
1438 | if (IS_VISIBLE(pDraw) && count) { | |
1439 | int top, bot, Min, Max; | |
1440 | ||
1441 | top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); | |
1442 | bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); | |
1443 | ||
1444 | Min = count * FONTMINBOUNDS(pGC->font, characterWidth); | |
1445 | if (Min > 0) | |
1446 | Min = 0; | |
1447 | Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); | |
1448 | if (Max < 0) | |
1449 | Max = 0; | |
1450 | ||
1451 | /* ugh */ | |
1452 | box.x1 = pDraw->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing); | |
1453 | box.x2 = pDraw->x + x + Max + | |
1454 | FONTMAXBOUNDS(pGC->font, rightSideBearing); | |
1455 | ||
1456 | box.y1 = pDraw->y + y - top; | |
1457 | box.y2 = pDraw->y + y + bot; | |
1458 | ||
1459 | TRIM_BOX(box, pGC); | |
1460 | if (BOX_NOT_EMPTY(box)) { | |
1461 | if (pPriv->preRefresh) | |
1462 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1463 | boxNotEmpty = TRUE; | |
1464 | } | |
1465 | } | |
1466 | ||
1467 | (*pGC->ops->ImageText16) (pDraw, pGC, x, y, count, chars); | |
1468 | ||
1469 | if (boxNotEmpty && pPriv->postRefresh) | |
1470 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1471 | ||
1472 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1473 | } | |
1474 | ||
1475 | static void | |
1476 | ShadowImageGlyphBlt(DrawablePtr pDraw, | |
1477 | GCPtr pGC, | |
1478 | int x, int y, | |
1479 | unsigned int nglyphInit, | |
1480 | CharInfoPtr * ppciInit, pointer pglyphBase) | |
1481 | { | |
1482 | BoxRec box; | |
1483 | Bool boxNotEmpty = FALSE; | |
1484 | ||
1485 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1486 | ||
1487 | if (IS_VISIBLE(pDraw) && nglyphInit) { | |
1488 | CharInfoPtr *ppci = ppciInit; | |
1489 | unsigned int nglyph = nglyphInit; | |
1490 | int top, bot, width = 0; | |
1491 | ||
1492 | top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); | |
1493 | bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); | |
1494 | ||
1495 | box.x1 = ppci[0]->metrics.leftSideBearing; | |
1496 | if (box.x1 > 0) | |
1497 | box.x1 = 0; | |
1498 | box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - | |
1499 | ppci[nglyph - 1]->metrics.characterWidth; | |
1500 | if (box.x2 < 0) | |
1501 | box.x2 = 0; | |
1502 | ||
1503 | box.x2 += pDraw->x + x; | |
1504 | box.x1 += pDraw->x + x; | |
1505 | ||
1506 | while (nglyph--) { | |
1507 | width += (*ppci)->metrics.characterWidth; | |
1508 | ppci++; | |
1509 | } | |
1510 | ||
1511 | if (width > 0) | |
1512 | box.x2 += width; | |
1513 | else | |
1514 | box.x1 += width; | |
1515 | ||
1516 | box.y1 = pDraw->y + y - top; | |
1517 | box.y2 = pDraw->y + y + bot; | |
1518 | ||
1519 | TRIM_BOX(box, pGC); | |
1520 | if (BOX_NOT_EMPTY(box)) { | |
1521 | if (pPriv->preRefresh) | |
1522 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1523 | boxNotEmpty = TRUE; | |
1524 | } | |
1525 | } | |
1526 | ||
1527 | (*pGC->ops->ImageGlyphBlt) (pDraw, pGC, x, y, nglyphInit, | |
1528 | ppciInit, pglyphBase); | |
1529 | ||
1530 | if (boxNotEmpty && pPriv->postRefresh) | |
1531 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1532 | ||
1533 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1534 | } | |
1535 | ||
1536 | static void | |
1537 | ShadowPolyGlyphBlt(DrawablePtr pDraw, | |
1538 | GCPtr pGC, | |
1539 | int x, int y, | |
1540 | unsigned int nglyphInit, | |
1541 | CharInfoPtr * ppciInit, pointer pglyphBase) | |
1542 | { | |
1543 | BoxRec box; | |
1544 | Bool boxNotEmpty = FALSE; | |
1545 | ||
1546 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1547 | ||
1548 | if (IS_VISIBLE(pDraw) && nglyphInit) { | |
1549 | CharInfoPtr *ppci = ppciInit; | |
1550 | unsigned int nglyph = nglyphInit; | |
1551 | ||
1552 | /* ugh */ | |
1553 | box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing; | |
1554 | box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing; | |
1555 | ||
1556 | if (nglyph > 1) { | |
1557 | int width = 0; | |
1558 | ||
1559 | while (--nglyph) { | |
1560 | width += (*ppci)->metrics.characterWidth; | |
1561 | ppci++; | |
1562 | } | |
1563 | ||
1564 | if (width > 0) | |
1565 | box.x2 += width; | |
1566 | else | |
1567 | box.x1 += width; | |
1568 | } | |
1569 | ||
1570 | box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent); | |
1571 | box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent); | |
1572 | ||
1573 | TRIM_BOX(box, pGC); | |
1574 | if (BOX_NOT_EMPTY(box)) { | |
1575 | if (pPriv->preRefresh) | |
1576 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1577 | boxNotEmpty = TRUE; | |
1578 | } | |
1579 | } | |
1580 | ||
1581 | (*pGC->ops->PolyGlyphBlt) (pDraw, pGC, x, y, nglyphInit, | |
1582 | ppciInit, pglyphBase); | |
1583 | ||
1584 | if (boxNotEmpty && pPriv->postRefresh) | |
1585 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1586 | ||
1587 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1588 | } | |
1589 | ||
1590 | static void | |
1591 | ShadowPushPixels(GCPtr pGC, | |
1592 | PixmapPtr pBitMap, | |
1593 | DrawablePtr pDraw, int dx, int dy, int xOrg, int yOrg) | |
1594 | { | |
1595 | BoxRec box; | |
1596 | Bool boxNotEmpty = FALSE; | |
1597 | ||
1598 | SHADOW_GC_OP_PROLOGUE(pGC); | |
1599 | ||
1600 | if (IS_VISIBLE(pDraw)) { | |
1601 | box.x1 = xOrg; | |
1602 | box.y1 = yOrg; | |
1603 | ||
1604 | if (!pGC->miTranslate) { | |
1605 | box.x1 += pDraw->x; | |
1606 | box.y1 += pDraw->y; | |
1607 | } | |
1608 | ||
1609 | box.x2 = box.x1 + dx; | |
1610 | box.y2 = box.y1 + dy; | |
1611 | ||
1612 | TRIM_BOX(box, pGC); | |
1613 | if (BOX_NOT_EMPTY(box)) { | |
1614 | if (pPriv->preRefresh) | |
1615 | (*pPriv->preRefresh) (pPriv->pScrn, 1, &box); | |
1616 | boxNotEmpty = TRUE; | |
1617 | } | |
1618 | } | |
1619 | ||
1620 | (*pGC->ops->PushPixels) (pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); | |
1621 | ||
1622 | if (boxNotEmpty && pPriv->postRefresh) | |
1623 | (*pPriv->postRefresh) (pPriv->pScrn, 1, &box); | |
1624 | ||
1625 | SHADOW_GC_OP_EPILOGUE(pGC); | |
1626 | } | |
1627 | ||
1628 | GCOps ShadowGCOps = { | |
1629 | ShadowFillSpans, ShadowSetSpans, | |
1630 | ShadowPutImage, ShadowCopyArea, | |
1631 | ShadowCopyPlane, ShadowPolyPoint, | |
1632 | ShadowPolylines, ShadowPolySegment, | |
1633 | ShadowPolyRectangle, ShadowPolyArc, | |
1634 | ShadowFillPolygon, ShadowPolyFillRect, | |
1635 | ShadowPolyFillArc, ShadowPolyText8, | |
1636 | ShadowPolyText16, ShadowImageText8, | |
1637 | ShadowImageText16, ShadowImageGlyphBlt, | |
1638 | ShadowPolyGlyphBlt, ShadowPushPixels, | |
1639 | }; |