105b261ecSmrg/* 205b261ecSmrg * Graphics Context support for generic rootless X server 305b261ecSmrg */ 405b261ecSmrg/* 505b261ecSmrg * Copyright (c) 2001 Greg Parker. All Rights Reserved. 605b261ecSmrg * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. 705b261ecSmrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 805b261ecSmrg * 905b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 1005b261ecSmrg * copy of this software and associated documentation files (the "Software"), 1105b261ecSmrg * to deal in the Software without restriction, including without limitation 1205b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1305b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 1405b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1505b261ecSmrg * 1605b261ecSmrg * The above copyright notice and this permission notice shall be included in 1705b261ecSmrg * all copies or substantial portions of the Software. 1805b261ecSmrg * 1905b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2005b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2105b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2205b261ecSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2305b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2405b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2505b261ecSmrg * DEALINGS IN THE SOFTWARE. 2605b261ecSmrg * 2705b261ecSmrg * Except as contained in this notice, the name(s) of the above copyright 2805b261ecSmrg * holders shall not be used in advertising or otherwise to promote the sale, 2905b261ecSmrg * use or other dealings in this Software without prior written authorization. 3005b261ecSmrg */ 3105b261ecSmrg 3205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3305b261ecSmrg#include <dix-config.h> 3405b261ecSmrg#endif 3505b261ecSmrg 3635c4bbdfSmrg#include <stddef.h> /* For NULL */ 3705b261ecSmrg#include "mi.h" 3805b261ecSmrg#include "scrnintstr.h" 3905b261ecSmrg#include "gcstruct.h" 4005b261ecSmrg#include "pixmapstr.h" 4105b261ecSmrg#include "windowstr.h" 4205b261ecSmrg#include "dixfontstr.h" 4305b261ecSmrg#include "mivalidate.h" 4405b261ecSmrg#include "fb.h" 4505b261ecSmrg 4605b261ecSmrg#include <sys/types.h> 4705b261ecSmrg#include <sys/stat.h> 4805b261ecSmrg#include <fcntl.h> 4905b261ecSmrg 5005b261ecSmrg#include "rootlessCommon.h" 5105b261ecSmrg 5205b261ecSmrg// GC functions 5305b261ecSmrgstatic void RootlessValidateGC(GCPtr pGC, unsigned long changes, 5405b261ecSmrg DrawablePtr pDrawable); 5505b261ecSmrgstatic void RootlessChangeGC(GCPtr pGC, unsigned long mask); 5605b261ecSmrgstatic void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); 5705b261ecSmrgstatic void RootlessDestroyGC(GCPtr pGC); 5835c4bbdfSmrgstatic void RootlessChangeClip(GCPtr pGC, int type, void *pvalue, int nrects); 5905b261ecSmrgstatic void RootlessDestroyClip(GCPtr pGC); 6005b261ecSmrgstatic void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc); 6105b261ecSmrg 624642e01fSmrgBool RootlessCreateGC(GCPtr pGC); 634642e01fSmrg 6405b261ecSmrgGCFuncs rootlessGCFuncs = { 6505b261ecSmrg RootlessValidateGC, 6605b261ecSmrg RootlessChangeGC, 6705b261ecSmrg RootlessCopyGC, 6805b261ecSmrg RootlessDestroyGC, 6905b261ecSmrg RootlessChangeClip, 7005b261ecSmrg RootlessDestroyClip, 7105b261ecSmrg RootlessCopyClip, 7205b261ecSmrg}; 7305b261ecSmrg 7405b261ecSmrg// GC operations 754642e01fSmrgstatic void RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, 7635c4bbdfSmrg DDXPointPtr pptInit, int *pwidthInit, int sorted); 774642e01fSmrgstatic void RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, 7835c4bbdfSmrg DDXPointPtr pptInit, int *pwidthInit, 7935c4bbdfSmrg int nspans, int sorted); 804642e01fSmrgstatic void RootlessPutImage(DrawablePtr dst, GCPtr pGC, 8135c4bbdfSmrg int depth, int x, int y, int w, int h, 8235c4bbdfSmrg int leftPad, int format, char *pBits); 834642e01fSmrgstatic RegionPtr RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, 8435c4bbdfSmrg int srcx, int srcy, int w, int h, 8535c4bbdfSmrg int dstx, int dsty); 864642e01fSmrgstatic RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst, 874642e01fSmrg GCPtr pGC, int srcx, int srcy, 884642e01fSmrg int w, int h, int dstx, int dsty, 894642e01fSmrg unsigned long plane); 904642e01fSmrgstatic void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC, 914642e01fSmrg int mode, int npt, DDXPointPtr pptInit); 924642e01fSmrgstatic void RootlessPolylines(DrawablePtr dst, GCPtr pGC, 934642e01fSmrg int mode, int npt, DDXPointPtr pptInit); 944642e01fSmrgstatic void RootlessPolySegment(DrawablePtr dst, GCPtr pGC, 9535c4bbdfSmrg int nseg, xSegment * pSeg); 964642e01fSmrgstatic void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC, 974642e01fSmrg int nRects, xRectangle *pRects); 9835c4bbdfSmrgstatic void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, 9935c4bbdfSmrg xArc * parcs); 10035c4bbdfSmrgstatic void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC, int shape, int mode, 10135c4bbdfSmrg int count, DDXPointPtr pptInit); 10235c4bbdfSmrgstatic void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC, int nRectsInit, 10335c4bbdfSmrg xRectangle *pRectsInit); 10435c4bbdfSmrgstatic void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, int narcsInit, 10535c4bbdfSmrg xArc * parcsInit); 10635c4bbdfSmrgstatic int RootlessPolyText8(DrawablePtr dst, GCPtr pGC, int x, int y, 10735c4bbdfSmrg int count, char *chars); 10835c4bbdfSmrgstatic int RootlessPolyText16(DrawablePtr dst, GCPtr pGC, int x, int y, 10935c4bbdfSmrg int count, unsigned short *chars); 11035c4bbdfSmrgstatic void RootlessImageText8(DrawablePtr dst, GCPtr pGC, int x, int y, 11135c4bbdfSmrg int count, char *chars); 11235c4bbdfSmrgstatic void RootlessImageText16(DrawablePtr dst, GCPtr pGC, int x, int y, 11335c4bbdfSmrg int count, unsigned short *chars); 11435c4bbdfSmrgstatic void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC, int x, int y, 11535c4bbdfSmrg unsigned int nglyphInit, 11635c4bbdfSmrg CharInfoPtr * ppciInit, void *unused); 11735c4bbdfSmrgstatic void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, int x, int y, 11835c4bbdfSmrg unsigned int nglyph, CharInfoPtr * ppci, 11935c4bbdfSmrg void *pglyphBase); 1204642e01fSmrgstatic void RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, 12135c4bbdfSmrg int dx, int dy, int xOrg, int yOrg); 12205b261ecSmrg 12305b261ecSmrgstatic GCOps rootlessGCOps = { 12405b261ecSmrg RootlessFillSpans, 12505b261ecSmrg RootlessSetSpans, 12605b261ecSmrg RootlessPutImage, 12705b261ecSmrg RootlessCopyArea, 12805b261ecSmrg RootlessCopyPlane, 12905b261ecSmrg RootlessPolyPoint, 13005b261ecSmrg RootlessPolylines, 13105b261ecSmrg RootlessPolySegment, 13205b261ecSmrg RootlessPolyRectangle, 13305b261ecSmrg RootlessPolyArc, 13405b261ecSmrg RootlessFillPolygon, 13505b261ecSmrg RootlessPolyFillRect, 13605b261ecSmrg RootlessPolyFillArc, 13705b261ecSmrg RootlessPolyText8, 13805b261ecSmrg RootlessPolyText16, 13905b261ecSmrg RootlessImageText8, 14005b261ecSmrg RootlessImageText16, 14105b261ecSmrg RootlessImageGlyphBlt, 14205b261ecSmrg RootlessPolyGlyphBlt, 14305b261ecSmrg RootlessPushPixels 14405b261ecSmrg}; 14505b261ecSmrg 14605b261ecSmrg/* 14705b261ecSmrg If ROOTLESS_PROTECT_ALPHA is set, we have to make sure that the alpha 14805b261ecSmrg channel of the on screen windows is always opaque. fb makes this harder 14905b261ecSmrg than it would otherwise be by noticing that a planemask of 0x00ffffff 15005b261ecSmrg includes all bits when depth==24, and so it "optimizes" the planemask to 15105b261ecSmrg 0xffffffff. We work around this by temporarily setting depth=bpp while 15205b261ecSmrg changing the GC. 15305b261ecSmrg 15405b261ecSmrg So the normal situation (in 32 bit mode) is that the planemask is 15505b261ecSmrg 0x00ffffff and thus fb leaves the alpha channel alone. The rootless 15605b261ecSmrg implementation is responsible for setting the alpha channel opaque 15705b261ecSmrg initially. 15805b261ecSmrg 15905b261ecSmrg Unfortunately drawing with a planemask that doesn't have all bits set 16005b261ecSmrg normally causes fb to fall off its fastest paths when blitting and 16105b261ecSmrg filling. So we try to recognize when we can relax the planemask back to 16205b261ecSmrg 0xffffffff, and do that for the duration of the drawing operation, 16305b261ecSmrg setting the alpha channel in fg/bg pixels to opaque at the same time. We 16405b261ecSmrg can do this when drawing op is GXcopy. We can also do this when copying 16505b261ecSmrg from another window since its alpha channel must also be opaque. 16605b261ecSmrg 1679ace9065Smrg The three macros below are used to implement this. Drawing ops that can 1689ace9065Smrg potentially have their planemask relaxed look like: 16905b261ecSmrg 17005b261ecSmrg OP { 17105b261ecSmrg GC_SAVE(gc); 17205b261ecSmrg GCOP_UNWRAP(gc); 17305b261ecSmrg 17405b261ecSmrg ... 17505b261ecSmrg 17605b261ecSmrg if (canAccelxxx(..) && otherwise-suitable) 17705b261ecSmrg GC_UNSET_PM(gc, dst); 17805b261ecSmrg 17905b261ecSmrg gc->funcs->OP(gc, ...); 18005b261ecSmrg 18105b261ecSmrg GC_RESTORE(gc, dst); 18205b261ecSmrg GCOP_WRAP(gc); 18305b261ecSmrg } 18405b261ecSmrg 18505b261ecSmrg */ 18605b261ecSmrg 18705b261ecSmrg#define GC_SAVE(pGC) \ 18805b261ecSmrg unsigned long _save_fg = (pGC)->fgPixel; \ 18905b261ecSmrg unsigned long _save_bg = (pGC)->bgPixel; \ 19005b261ecSmrg unsigned long _save_pm = (pGC)->planemask; \ 19105b261ecSmrg Bool _changed = FALSE 19205b261ecSmrg 19305b261ecSmrg#define GC_RESTORE(pGC, pDraw) \ 19405b261ecSmrg do { \ 19505b261ecSmrg if (_changed) { \ 19605b261ecSmrg unsigned int depth = (pDraw)->depth; \ 19705b261ecSmrg (pGC)->fgPixel = _save_fg; \ 19805b261ecSmrg (pGC)->bgPixel = _save_bg; \ 19905b261ecSmrg (pGC)->planemask = _save_pm; \ 20005b261ecSmrg (pDraw)->depth = (pDraw)->bitsPerPixel; \ 20105b261ecSmrg VALIDATE_GC(pGC, GCForeground | GCBackground | \ 20205b261ecSmrg GCPlaneMask, pDraw); \ 20305b261ecSmrg (pDraw)->depth = depth; \ 20405b261ecSmrg } \ 20505b261ecSmrg } while (0) 20605b261ecSmrg 20705b261ecSmrg#define GC_UNSET_PM(pGC, pDraw) \ 20805b261ecSmrg do { \ 20905b261ecSmrg unsigned int mask = RootlessAlphaMask ((pDraw)->bitsPerPixel); \ 21005b261ecSmrg if (((pGC)->planemask & mask) != mask) { \ 21105b261ecSmrg unsigned int depth = (pDraw)->depth; \ 21205b261ecSmrg (pGC)->fgPixel |= mask; \ 21305b261ecSmrg (pGC)->bgPixel |= mask; \ 21405b261ecSmrg (pGC)->planemask |= mask; \ 21505b261ecSmrg (pDraw)->depth = (pDraw)->bitsPerPixel; \ 21605b261ecSmrg VALIDATE_GC(pGC, GCForeground | \ 21705b261ecSmrg GCBackground | GCPlaneMask, pDraw); \ 21805b261ecSmrg (pDraw)->depth = depth; \ 21905b261ecSmrg _changed = TRUE; \ 22005b261ecSmrg } \ 22105b261ecSmrg } while (0) 22205b261ecSmrg 22305b261ecSmrg#define VALIDATE_GC(pGC, changes, pDrawable) \ 22405b261ecSmrg do { \ 22505b261ecSmrg pGC->funcs->ValidateGC(pGC, changes, pDrawable); \ 22605b261ecSmrg if (((WindowPtr) pDrawable)->viewable) { \ 22705b261ecSmrg gcrec->originalOps = pGC->ops; \ 22805b261ecSmrg } \ 22905b261ecSmrg } while(0) 23005b261ecSmrg 23105b261ecSmrgstatic RootlessWindowRec * 23235c4bbdfSmrgcanAccelBlit(DrawablePtr pDraw, GCPtr pGC) 23305b261ecSmrg{ 23405b261ecSmrg WindowPtr pTop; 23505b261ecSmrg RootlessWindowRec *winRec; 23605b261ecSmrg unsigned int pm; 23705b261ecSmrg 23805b261ecSmrg if (pGC->alu != GXcopy) 23905b261ecSmrg return NULL; 24005b261ecSmrg 24105b261ecSmrg if (pDraw->type != DRAWABLE_WINDOW) 24205b261ecSmrg return NULL; 24305b261ecSmrg 24405b261ecSmrg pm = ~RootlessAlphaMask(pDraw->bitsPerPixel); 24505b261ecSmrg if ((pGC->planemask & pm) != pm) 24605b261ecSmrg return NULL; 24705b261ecSmrg 24805b261ecSmrg pTop = TopLevelParent((WindowPtr) pDraw); 24905b261ecSmrg if (pTop == NULL) 25005b261ecSmrg return NULL; 25105b261ecSmrg 25205b261ecSmrg winRec = WINREC(pTop); 25305b261ecSmrg if (winRec == NULL) 25405b261ecSmrg return NULL; 25505b261ecSmrg 25605b261ecSmrg return winRec; 25705b261ecSmrg} 25805b261ecSmrg 25905b261ecSmrgstatic inline RootlessWindowRec * 26005b261ecSmrgcanAccelFill(DrawablePtr pDraw, GCPtr pGC) 26105b261ecSmrg{ 26205b261ecSmrg if (pGC->fillStyle != FillSolid) 26305b261ecSmrg return NULL; 26405b261ecSmrg 26505b261ecSmrg return canAccelBlit(pDraw, pGC); 26605b261ecSmrg} 26705b261ecSmrg 26805b261ecSmrg/* 26905b261ecSmrg * Screen function to create a graphics context 27005b261ecSmrg */ 27105b261ecSmrgBool 27205b261ecSmrgRootlessCreateGC(GCPtr pGC) 27305b261ecSmrg{ 27405b261ecSmrg RootlessGCRec *gcrec; 27505b261ecSmrg RootlessScreenRec *s; 27605b261ecSmrg Bool result; 27705b261ecSmrg 27805b261ecSmrg SCREEN_UNWRAP(pGC->pScreen, CreateGC); 2794642e01fSmrg s = SCREENREC(pGC->pScreen); 28005b261ecSmrg result = s->CreateGC(pGC); 28105b261ecSmrg 2824642e01fSmrg gcrec = (RootlessGCRec *) 28335c4bbdfSmrg dixLookupPrivate(&pGC->devPrivates, rootlessGCPrivateKey); 28435c4bbdfSmrg gcrec->originalOps = NULL; // don't wrap ops yet 28505b261ecSmrg gcrec->originalFuncs = pGC->funcs; 28605b261ecSmrg pGC->funcs = &rootlessGCFuncs; 28705b261ecSmrg 28805b261ecSmrg SCREEN_WRAP(pGC->pScreen, CreateGC); 28905b261ecSmrg return result; 29005b261ecSmrg} 29105b261ecSmrg 29205b261ecSmrg/* 29305b261ecSmrg * GC funcs 29405b261ecSmrg * 29505b261ecSmrg * These wrap lower level GC funcs. 29605b261ecSmrg * ValidateGC wraps the GC ops iff dest is viewable. 29705b261ecSmrg * All the others just unwrap and call. 29805b261ecSmrg */ 29905b261ecSmrg 30035c4bbdfSmrg// GCFUNC_UNRAP assumes funcs have been wrapped and 30105b261ecSmrg// does not assume ops have been wrapped 30205b261ecSmrg#define GCFUNC_UNWRAP(pGC) \ 30305b261ecSmrg RootlessGCRec *gcrec = (RootlessGCRec *) \ 3044642e01fSmrg dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \ 30505b261ecSmrg (pGC)->funcs = gcrec->originalFuncs; \ 30605b261ecSmrg if (gcrec->originalOps) { \ 30705b261ecSmrg (pGC)->ops = gcrec->originalOps; \ 30805b261ecSmrg} 30905b261ecSmrg 31005b261ecSmrg#define GCFUNC_WRAP(pGC) \ 31105b261ecSmrg gcrec->originalFuncs = (pGC)->funcs; \ 31205b261ecSmrg (pGC)->funcs = &rootlessGCFuncs; \ 31305b261ecSmrg if (gcrec->originalOps) { \ 31405b261ecSmrg gcrec->originalOps = (pGC)->ops; \ 31505b261ecSmrg (pGC)->ops = &rootlessGCOps; \ 31605b261ecSmrg} 31705b261ecSmrg 31805b261ecSmrgstatic void 31905b261ecSmrgRootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 32005b261ecSmrg{ 32105b261ecSmrg GCFUNC_UNWRAP(pGC); 32205b261ecSmrg 32305b261ecSmrg gcrec->originalOps = NULL; 32405b261ecSmrg 32535c4bbdfSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 32605b261ecSmrg#ifdef ROOTLESS_PROTECT_ALPHA 32705b261ecSmrg unsigned int depth = pDrawable->depth; 32805b261ecSmrg 32905b261ecSmrg // We force a planemask so fb doesn't overwrite the alpha channel. 33005b261ecSmrg // Left to its own devices, fb will optimize away the planemask. 33105b261ecSmrg pDrawable->depth = pDrawable->bitsPerPixel; 33205b261ecSmrg pGC->planemask &= ~RootlessAlphaMask(pDrawable->bitsPerPixel); 33305b261ecSmrg VALIDATE_GC(pGC, changes | GCPlaneMask, pDrawable); 33405b261ecSmrg pDrawable->depth = depth; 33505b261ecSmrg#else 33605b261ecSmrg VALIDATE_GC(pGC, changes, pDrawable); 33705b261ecSmrg#endif 33835c4bbdfSmrg } 33935c4bbdfSmrg else { 34005b261ecSmrg pGC->funcs->ValidateGC(pGC, changes, pDrawable); 34105b261ecSmrg } 34205b261ecSmrg 34305b261ecSmrg GCFUNC_WRAP(pGC); 34405b261ecSmrg} 34505b261ecSmrg 34635c4bbdfSmrgstatic void 34735c4bbdfSmrgRootlessChangeGC(GCPtr pGC, unsigned long mask) 34805b261ecSmrg{ 34905b261ecSmrg GCFUNC_UNWRAP(pGC); 35005b261ecSmrg pGC->funcs->ChangeGC(pGC, mask); 35105b261ecSmrg GCFUNC_WRAP(pGC); 35205b261ecSmrg} 35305b261ecSmrg 35435c4bbdfSmrgstatic void 35535c4bbdfSmrgRootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) 35605b261ecSmrg{ 35705b261ecSmrg GCFUNC_UNWRAP(pGCDst); 35805b261ecSmrg pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst); 35905b261ecSmrg GCFUNC_WRAP(pGCDst); 36005b261ecSmrg} 36105b261ecSmrg 36235c4bbdfSmrgstatic void 36335c4bbdfSmrgRootlessDestroyGC(GCPtr pGC) 36405b261ecSmrg{ 36505b261ecSmrg GCFUNC_UNWRAP(pGC); 36605b261ecSmrg pGC->funcs->DestroyGC(pGC); 36705b261ecSmrg GCFUNC_WRAP(pGC); 36805b261ecSmrg} 36905b261ecSmrg 37035c4bbdfSmrgstatic void 37135c4bbdfSmrgRootlessChangeClip(GCPtr pGC, int type, void *pvalue, int nrects) 37205b261ecSmrg{ 37305b261ecSmrg GCFUNC_UNWRAP(pGC); 37405b261ecSmrg pGC->funcs->ChangeClip(pGC, type, pvalue, nrects); 37505b261ecSmrg GCFUNC_WRAP(pGC); 37605b261ecSmrg} 37705b261ecSmrg 37835c4bbdfSmrgstatic void 37935c4bbdfSmrgRootlessDestroyClip(GCPtr pGC) 38005b261ecSmrg{ 38105b261ecSmrg GCFUNC_UNWRAP(pGC); 38205b261ecSmrg pGC->funcs->DestroyClip(pGC); 38305b261ecSmrg GCFUNC_WRAP(pGC); 38405b261ecSmrg} 38505b261ecSmrg 38635c4bbdfSmrgstatic void 38735c4bbdfSmrgRootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc) 38805b261ecSmrg{ 38905b261ecSmrg GCFUNC_UNWRAP(pgcDst); 39005b261ecSmrg pgcDst->funcs->CopyClip(pgcDst, pgcSrc); 39105b261ecSmrg GCFUNC_WRAP(pgcDst); 39205b261ecSmrg} 39305b261ecSmrg 39405b261ecSmrg/* 39505b261ecSmrg * GC ops 39605b261ecSmrg * 39705b261ecSmrg * We can't use shadowfb because shadowfb assumes one pixmap 39805b261ecSmrg * and our root window is a special case. 39905b261ecSmrg * However, much of this code is copied from shadowfb. 40005b261ecSmrg */ 40105b261ecSmrg 40205b261ecSmrg// assumes both funcs and ops are wrapped 40305b261ecSmrg#define GCOP_UNWRAP(pGC) \ 40405b261ecSmrg RootlessGCRec *gcrec = (RootlessGCRec *) \ 4054642e01fSmrg dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \ 40635c4bbdfSmrg const GCFuncs *saveFuncs = pGC->funcs; \ 40705b261ecSmrg (pGC)->funcs = gcrec->originalFuncs; \ 40805b261ecSmrg (pGC)->ops = gcrec->originalOps; 40905b261ecSmrg 41005b261ecSmrg#define GCOP_WRAP(pGC) \ 41105b261ecSmrg gcrec->originalOps = (pGC)->ops; \ 41205b261ecSmrg (pGC)->funcs = saveFuncs; \ 41305b261ecSmrg (pGC)->ops = &rootlessGCOps; 41405b261ecSmrg 41505b261ecSmrgstatic void 41605b261ecSmrgRootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, 41705b261ecSmrg DDXPointPtr pptInit, int *pwidthInit, int sorted) 41805b261ecSmrg{ 41905b261ecSmrg GC_SAVE(pGC); 42005b261ecSmrg GCOP_UNWRAP(pGC); 42105b261ecSmrg RL_DEBUG_MSG("fill spans start "); 42205b261ecSmrg 42305b261ecSmrg if (nInit <= 0) { 42405b261ecSmrg pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); 42535c4bbdfSmrg } 42635c4bbdfSmrg else { 42705b261ecSmrg DDXPointPtr ppt = pptInit; 42805b261ecSmrg int *pwidth = pwidthInit; 42905b261ecSmrg int i = nInit; 43005b261ecSmrg BoxRec box; 43105b261ecSmrg 43205b261ecSmrg box.x1 = ppt->x; 43305b261ecSmrg box.x2 = box.x1 + *pwidth; 43405b261ecSmrg box.y2 = box.y1 = ppt->y; 43505b261ecSmrg 43605b261ecSmrg while (--i) { 43705b261ecSmrg ppt++; 43805b261ecSmrg pwidth++; 43905b261ecSmrg if (box.x1 > ppt->x) 44005b261ecSmrg box.x1 = ppt->x; 44105b261ecSmrg if (box.x2 < (ppt->x + *pwidth)) 44205b261ecSmrg box.x2 = ppt->x + *pwidth; 44305b261ecSmrg if (box.y1 > ppt->y) 44405b261ecSmrg box.y1 = ppt->y; 44505b261ecSmrg else if (box.y2 < ppt->y) 44605b261ecSmrg box.y2 = ppt->y; 44705b261ecSmrg } 44805b261ecSmrg 44905b261ecSmrg box.y2++; 45005b261ecSmrg 45105b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 45205b261ecSmrg 45335c4bbdfSmrg if (canAccelFill(dst, pGC)) { 45405b261ecSmrg GC_UNSET_PM(pGC, dst); 45505b261ecSmrg } 45605b261ecSmrg 45705b261ecSmrg pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); 45805b261ecSmrg 45905b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 46005b261ecSmrg if (BOX_NOT_EMPTY(box)) 46135c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 46205b261ecSmrg } 46305b261ecSmrg 46405b261ecSmrg GC_RESTORE(pGC, dst); 46505b261ecSmrg GCOP_WRAP(pGC); 46605b261ecSmrg RL_DEBUG_MSG("fill spans end\n"); 46705b261ecSmrg} 46805b261ecSmrg 46905b261ecSmrgstatic void 47005b261ecSmrgRootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, 47135c4bbdfSmrg DDXPointPtr pptInit, int *pwidthInit, int nspans, int sorted) 47205b261ecSmrg{ 47305b261ecSmrg GCOP_UNWRAP(pGC); 47405b261ecSmrg RL_DEBUG_MSG("set spans start "); 47505b261ecSmrg 47605b261ecSmrg if (nspans <= 0) { 47735c4bbdfSmrg pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); 47835c4bbdfSmrg } 47935c4bbdfSmrg else { 48005b261ecSmrg DDXPointPtr ppt = pptInit; 48105b261ecSmrg int *pwidth = pwidthInit; 48205b261ecSmrg int i = nspans; 48305b261ecSmrg BoxRec box; 48405b261ecSmrg 48505b261ecSmrg box.x1 = ppt->x; 48605b261ecSmrg box.x2 = box.x1 + *pwidth; 48705b261ecSmrg box.y2 = box.y1 = ppt->y; 48805b261ecSmrg 48905b261ecSmrg while (--i) { 49005b261ecSmrg ppt++; 49105b261ecSmrg pwidth++; 49205b261ecSmrg if (box.x1 > ppt->x) 49305b261ecSmrg box.x1 = ppt->x; 49405b261ecSmrg if (box.x2 < (ppt->x + *pwidth)) 49505b261ecSmrg box.x2 = ppt->x + *pwidth; 49605b261ecSmrg if (box.y1 > ppt->y) 49705b261ecSmrg box.y1 = ppt->y; 49805b261ecSmrg else if (box.y2 < ppt->y) 49905b261ecSmrg box.y2 = ppt->y; 50005b261ecSmrg } 50105b261ecSmrg 50205b261ecSmrg box.y2++; 50305b261ecSmrg 50405b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 50535c4bbdfSmrg pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); 50605b261ecSmrg 50705b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 50805b261ecSmrg if (BOX_NOT_EMPTY(box)) 50935c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 51005b261ecSmrg } 51105b261ecSmrg GCOP_WRAP(pGC); 51205b261ecSmrg RL_DEBUG_MSG("set spans end\n"); 51305b261ecSmrg} 51405b261ecSmrg 51505b261ecSmrgstatic void 51605b261ecSmrgRootlessPutImage(DrawablePtr dst, GCPtr pGC, 51705b261ecSmrg int depth, int x, int y, int w, int h, 51805b261ecSmrg int leftPad, int format, char *pBits) 51905b261ecSmrg{ 52005b261ecSmrg BoxRec box; 52105b261ecSmrg 52205b261ecSmrg GCOP_UNWRAP(pGC); 52305b261ecSmrg RL_DEBUG_MSG("put image start "); 52405b261ecSmrg 52505b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 52635c4bbdfSmrg pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits); 52705b261ecSmrg 52805b261ecSmrg box.x1 = x + dst->x; 52905b261ecSmrg box.x2 = box.x1 + w; 53005b261ecSmrg box.y1 = y + dst->y; 53105b261ecSmrg box.y2 = box.y1 + h; 53205b261ecSmrg 53305b261ecSmrg TRIM_BOX(box, pGC); 53405b261ecSmrg if (BOX_NOT_EMPTY(box)) 53535c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 53605b261ecSmrg 53705b261ecSmrg GCOP_WRAP(pGC); 53805b261ecSmrg RL_DEBUG_MSG("put image end\n"); 53905b261ecSmrg} 54005b261ecSmrg 54105b261ecSmrg/* changed area is *dest* rect */ 54205b261ecSmrgstatic RegionPtr 54305b261ecSmrgRootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, 54435c4bbdfSmrg int srcx, int srcy, int w, int h, int dstx, int dsty) 54505b261ecSmrg{ 54605b261ecSmrg RegionPtr result; 54705b261ecSmrg BoxRec box; 54805b261ecSmrg 54905b261ecSmrg GC_SAVE(pGC); 55005b261ecSmrg GCOP_UNWRAP(pGC); 55105b261ecSmrg 55205b261ecSmrg RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst); 55305b261ecSmrg 55435c4bbdfSmrg if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) { 55505b261ecSmrg /* If both source and dest are windows, and we're doing 55605b261ecSmrg a simple copy operation, we can remove the alpha-protecting 55705b261ecSmrg planemask (since source has opaque alpha as well) */ 55805b261ecSmrg 55935c4bbdfSmrg if (canAccelBlit(pSrc, pGC)) { 56005b261ecSmrg GC_UNSET_PM(pGC, dst); 56105b261ecSmrg } 56205b261ecSmrg 56305b261ecSmrg RootlessStartDrawing((WindowPtr) pSrc); 56405b261ecSmrg } 56505b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 56605b261ecSmrg result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); 56705b261ecSmrg 56805b261ecSmrg box.x1 = dstx + dst->x; 56905b261ecSmrg box.x2 = box.x1 + w; 57005b261ecSmrg box.y1 = dsty + dst->y; 57105b261ecSmrg box.y2 = box.y1 + h; 57205b261ecSmrg 57305b261ecSmrg TRIM_BOX(box, pGC); 57405b261ecSmrg if (BOX_NOT_EMPTY(box)) 57535c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 57605b261ecSmrg 57705b261ecSmrg GC_RESTORE(pGC, dst); 57805b261ecSmrg GCOP_WRAP(pGC); 57905b261ecSmrg RL_DEBUG_MSG("copy area end\n"); 58005b261ecSmrg return result; 58105b261ecSmrg} 58205b261ecSmrg 58305b261ecSmrg/* changed area is *dest* rect */ 58435c4bbdfSmrgstatic RegionPtr 58535c4bbdfSmrgRootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst, 58635c4bbdfSmrg GCPtr pGC, int srcx, int srcy, 58735c4bbdfSmrg int w, int h, int dstx, int dsty, unsigned long plane) 58805b261ecSmrg{ 58905b261ecSmrg RegionPtr result; 59005b261ecSmrg BoxRec box; 59105b261ecSmrg 59205b261ecSmrg GCOP_UNWRAP(pGC); 59305b261ecSmrg 59405b261ecSmrg RL_DEBUG_MSG("copy plane start "); 59505b261ecSmrg 59635c4bbdfSmrg if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) { 59705b261ecSmrg RootlessStartDrawing((WindowPtr) pSrc); 59805b261ecSmrg } 59905b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 60005b261ecSmrg result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, 60105b261ecSmrg dstx, dsty, plane); 60205b261ecSmrg 60305b261ecSmrg box.x1 = dstx + dst->x; 60405b261ecSmrg box.x2 = box.x1 + w; 60505b261ecSmrg box.y1 = dsty + dst->y; 60605b261ecSmrg box.y2 = box.y1 + h; 60705b261ecSmrg 60805b261ecSmrg TRIM_BOX(box, pGC); 60905b261ecSmrg if (BOX_NOT_EMPTY(box)) 61035c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 61105b261ecSmrg 61205b261ecSmrg GCOP_WRAP(pGC); 61305b261ecSmrg RL_DEBUG_MSG("copy plane end\n"); 61405b261ecSmrg return result; 61505b261ecSmrg} 61605b261ecSmrg 61705b261ecSmrg// Options for size of changed area: 61805b261ecSmrg// 0 = box per point 61905b261ecSmrg// 1 = big box around all points 62005b261ecSmrg// 2 = accumulate point in 20 pixel radius 62105b261ecSmrg#define ROOTLESS_CHANGED_AREA 1 62205b261ecSmrg#define abs(a) ((a) > 0 ? (a) : -(a)) 62305b261ecSmrg 62405b261ecSmrg/* changed area is box around all points */ 62535c4bbdfSmrgstatic void 62635c4bbdfSmrgRootlessPolyPoint(DrawablePtr dst, GCPtr pGC, 62735c4bbdfSmrg int mode, int npt, DDXPointPtr pptInit) 62805b261ecSmrg{ 62905b261ecSmrg GCOP_UNWRAP(pGC); 63005b261ecSmrg RL_DEBUG_MSG("polypoint start "); 63105b261ecSmrg 63205b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 63305b261ecSmrg pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); 63405b261ecSmrg 63505b261ecSmrg if (npt > 0) { 63605b261ecSmrg#if ROOTLESS_CHANGED_AREA==0 63705b261ecSmrg // box per point 63805b261ecSmrg BoxRec box; 63905b261ecSmrg 64005b261ecSmrg while (npt) { 64105b261ecSmrg box.x1 = pptInit->x; 64205b261ecSmrg box.y1 = pptInit->y; 64305b261ecSmrg box.x2 = box.x1 + 1; 64405b261ecSmrg box.y2 = box.y1 + 1; 64505b261ecSmrg 64605b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 64705b261ecSmrg if (BOX_NOT_EMPTY(box)) 64835c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 64905b261ecSmrg 65005b261ecSmrg npt--; 65105b261ecSmrg pptInit++; 65205b261ecSmrg } 65305b261ecSmrg 65405b261ecSmrg#elif ROOTLESS_CHANGED_AREA==1 65505b261ecSmrg // one big box 65605b261ecSmrg BoxRec box; 65705b261ecSmrg 65805b261ecSmrg box.x2 = box.x1 = pptInit->x; 65905b261ecSmrg box.y2 = box.y1 = pptInit->y; 66005b261ecSmrg while (--npt) { 66105b261ecSmrg pptInit++; 66205b261ecSmrg if (box.x1 > pptInit->x) 66305b261ecSmrg box.x1 = pptInit->x; 66405b261ecSmrg else if (box.x2 < pptInit->x) 66505b261ecSmrg box.x2 = pptInit->x; 66605b261ecSmrg if (box.y1 > pptInit->y) 66705b261ecSmrg box.y1 = pptInit->y; 66805b261ecSmrg else if (box.y2 < pptInit->y) 66905b261ecSmrg box.y2 = pptInit->y; 67005b261ecSmrg } 67105b261ecSmrg 67205b261ecSmrg box.x2++; 67305b261ecSmrg box.y2++; 67405b261ecSmrg 67505b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 67605b261ecSmrg if (BOX_NOT_EMPTY(box)) 67735c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 67805b261ecSmrg 67905b261ecSmrg#elif ROOTLESS_CHANGED_AREA==2 68005b261ecSmrg // clever(?) method: accumulate point in 20-pixel radius 68105b261ecSmrg BoxRec box; 68205b261ecSmrg int firstx, firsty; 68305b261ecSmrg 68405b261ecSmrg box.x2 = box.x1 = firstx = pptInit->x; 68505b261ecSmrg box.y2 = box.y1 = firsty = pptInit->y; 68605b261ecSmrg while (--npt) { 68705b261ecSmrg pptInit++; 68835c4bbdfSmrg if (abs(pptInit->x - firstx) > 20 || abs(pptInit->y - firsty) > 20) { 68905b261ecSmrg box.x2++; 69005b261ecSmrg box.y2++; 69105b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 69205b261ecSmrg if (BOX_NOT_EMPTY(box)) 69335c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 69405b261ecSmrg box.x2 = box.x1 = firstx = pptInit->x; 69505b261ecSmrg box.y2 = box.y1 = firsty = pptInit->y; 69635c4bbdfSmrg } 69735c4bbdfSmrg else { 69835c4bbdfSmrg if (box.x1 > pptInit->x) 69935c4bbdfSmrg box.x1 = pptInit->x; 70035c4bbdfSmrg else if (box.x2 < pptInit->x) 70135c4bbdfSmrg box.x2 = pptInit->x; 70235c4bbdfSmrg if (box.y1 > pptInit->y) 70335c4bbdfSmrg box.y1 = pptInit->y; 70435c4bbdfSmrg else if (box.y2 < pptInit->y) 70535c4bbdfSmrg box.y2 = pptInit->y; 70605b261ecSmrg } 70705b261ecSmrg } 70805b261ecSmrg box.x2++; 70905b261ecSmrg box.y2++; 71005b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 71105b261ecSmrg if (BOX_NOT_EMPTY(box)) 71205b261ecSmrg RootlessDamageBox((WindowPtr) dst, &box); 71335c4bbdfSmrg#endif /* ROOTLESS_CHANGED_AREA */ 71405b261ecSmrg } 71505b261ecSmrg 71605b261ecSmrg GCOP_WRAP(pGC); 71705b261ecSmrg RL_DEBUG_MSG("polypoint end\n"); 71805b261ecSmrg} 71905b261ecSmrg 72005b261ecSmrg#undef ROOTLESS_CHANGED_AREA 72105b261ecSmrg 72205b261ecSmrg/* changed area is box around each line */ 72335c4bbdfSmrgstatic void 72435c4bbdfSmrgRootlessPolylines(DrawablePtr dst, GCPtr pGC, 72535c4bbdfSmrg int mode, int npt, DDXPointPtr pptInit) 72605b261ecSmrg{ 72705b261ecSmrg GCOP_UNWRAP(pGC); 72805b261ecSmrg RL_DEBUG_MSG("poly lines start "); 72905b261ecSmrg 73005b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 73105b261ecSmrg pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); 73205b261ecSmrg 73305b261ecSmrg if (npt > 0) { 73405b261ecSmrg BoxRec box; 73505b261ecSmrg int extra = pGC->lineWidth >> 1; 73605b261ecSmrg 73705b261ecSmrg box.x2 = box.x1 = pptInit->x; 73805b261ecSmrg box.y2 = box.y1 = pptInit->y; 73905b261ecSmrg 74005b261ecSmrg if (npt > 1) { 74105b261ecSmrg if (pGC->joinStyle == JoinMiter) 74205b261ecSmrg extra = 6 * pGC->lineWidth; 74305b261ecSmrg else if (pGC->capStyle == CapProjecting) 74405b261ecSmrg extra = pGC->lineWidth; 74505b261ecSmrg } 74605b261ecSmrg 74705b261ecSmrg if (mode == CoordModePrevious) { 74805b261ecSmrg int x = box.x1; 74905b261ecSmrg int y = box.y1; 75005b261ecSmrg 75105b261ecSmrg while (--npt) { 75205b261ecSmrg pptInit++; 75305b261ecSmrg x += pptInit->x; 75405b261ecSmrg y += pptInit->y; 75505b261ecSmrg if (box.x1 > x) 75605b261ecSmrg box.x1 = x; 75705b261ecSmrg else if (box.x2 < x) 75805b261ecSmrg box.x2 = x; 75905b261ecSmrg if (box.y1 > y) 76005b261ecSmrg box.y1 = y; 76105b261ecSmrg else if (box.y2 < y) 76205b261ecSmrg box.y2 = y; 76305b261ecSmrg } 76435c4bbdfSmrg } 76535c4bbdfSmrg else { 76605b261ecSmrg while (--npt) { 76705b261ecSmrg pptInit++; 76805b261ecSmrg if (box.x1 > pptInit->x) 76905b261ecSmrg box.x1 = pptInit->x; 77005b261ecSmrg else if (box.x2 < pptInit->x) 77105b261ecSmrg box.x2 = pptInit->x; 77205b261ecSmrg if (box.y1 > pptInit->y) 77305b261ecSmrg box.y1 = pptInit->y; 77405b261ecSmrg else if (box.y2 < pptInit->y) 77505b261ecSmrg box.y2 = pptInit->y; 77605b261ecSmrg } 77705b261ecSmrg } 77805b261ecSmrg 77905b261ecSmrg box.x2++; 78005b261ecSmrg box.y2++; 78105b261ecSmrg 78205b261ecSmrg if (extra) { 78305b261ecSmrg box.x1 -= extra; 78405b261ecSmrg box.x2 += extra; 78505b261ecSmrg box.y1 -= extra; 78605b261ecSmrg box.y2 += extra; 78705b261ecSmrg } 78805b261ecSmrg 78905b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 79005b261ecSmrg if (BOX_NOT_EMPTY(box)) 79135c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 79205b261ecSmrg } 79305b261ecSmrg 79405b261ecSmrg GCOP_WRAP(pGC); 79505b261ecSmrg RL_DEBUG_MSG("poly lines end\n"); 79605b261ecSmrg} 79705b261ecSmrg 79805b261ecSmrg/* changed area is box around each line segment */ 79935c4bbdfSmrgstatic void 80035c4bbdfSmrgRootlessPolySegment(DrawablePtr dst, GCPtr pGC, int nseg, xSegment * pSeg) 80105b261ecSmrg{ 80205b261ecSmrg GCOP_UNWRAP(pGC); 80305b261ecSmrg RL_DEBUG_MSG("poly segment start (win 0x%x)", dst); 80405b261ecSmrg 80505b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 80605b261ecSmrg pGC->ops->PolySegment(dst, pGC, nseg, pSeg); 80705b261ecSmrg 80805b261ecSmrg if (nseg > 0) { 80905b261ecSmrg BoxRec box; 81005b261ecSmrg int extra = pGC->lineWidth; 81105b261ecSmrg 81205b261ecSmrg if (pGC->capStyle != CapProjecting) 81335c4bbdfSmrg extra >>= 1; 81405b261ecSmrg 81505b261ecSmrg if (pSeg->x2 > pSeg->x1) { 81605b261ecSmrg box.x1 = pSeg->x1; 81705b261ecSmrg box.x2 = pSeg->x2; 81835c4bbdfSmrg } 81935c4bbdfSmrg else { 82005b261ecSmrg box.x2 = pSeg->x1; 82105b261ecSmrg box.x1 = pSeg->x2; 82205b261ecSmrg } 82305b261ecSmrg 82405b261ecSmrg if (pSeg->y2 > pSeg->y1) { 82505b261ecSmrg box.y1 = pSeg->y1; 82605b261ecSmrg box.y2 = pSeg->y2; 82735c4bbdfSmrg } 82835c4bbdfSmrg else { 82905b261ecSmrg box.y2 = pSeg->y1; 83005b261ecSmrg box.y1 = pSeg->y2; 83105b261ecSmrg } 83205b261ecSmrg 83305b261ecSmrg while (--nseg) { 83405b261ecSmrg pSeg++; 83505b261ecSmrg if (pSeg->x2 > pSeg->x1) { 83635c4bbdfSmrg if (pSeg->x1 < box.x1) 83735c4bbdfSmrg box.x1 = pSeg->x1; 83835c4bbdfSmrg if (pSeg->x2 > box.x2) 83935c4bbdfSmrg box.x2 = pSeg->x2; 84035c4bbdfSmrg } 84135c4bbdfSmrg else { 84235c4bbdfSmrg if (pSeg->x2 < box.x1) 84335c4bbdfSmrg box.x1 = pSeg->x2; 84435c4bbdfSmrg if (pSeg->x1 > box.x2) 84535c4bbdfSmrg box.x2 = pSeg->x1; 84605b261ecSmrg } 84705b261ecSmrg if (pSeg->y2 > pSeg->y1) { 84835c4bbdfSmrg if (pSeg->y1 < box.y1) 84935c4bbdfSmrg box.y1 = pSeg->y1; 85035c4bbdfSmrg if (pSeg->y2 > box.y2) 85135c4bbdfSmrg box.y2 = pSeg->y2; 85235c4bbdfSmrg } 85335c4bbdfSmrg else { 85435c4bbdfSmrg if (pSeg->y2 < box.y1) 85535c4bbdfSmrg box.y1 = pSeg->y2; 85635c4bbdfSmrg if (pSeg->y1 > box.y2) 85735c4bbdfSmrg box.y2 = pSeg->y1; 85805b261ecSmrg } 85905b261ecSmrg } 86005b261ecSmrg 86105b261ecSmrg box.x2++; 86205b261ecSmrg box.y2++; 86305b261ecSmrg 86405b261ecSmrg if (extra) { 86505b261ecSmrg box.x1 -= extra; 86605b261ecSmrg box.x2 += extra; 86705b261ecSmrg box.y1 -= extra; 86805b261ecSmrg box.y2 += extra; 86905b261ecSmrg } 87005b261ecSmrg 87105b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 87205b261ecSmrg if (BOX_NOT_EMPTY(box)) 87335c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 87405b261ecSmrg } 87505b261ecSmrg 87605b261ecSmrg GCOP_WRAP(pGC); 87705b261ecSmrg RL_DEBUG_MSG("poly segment end\n"); 87805b261ecSmrg} 87905b261ecSmrg 88005b261ecSmrg/* changed area is box around each line (not entire rects) */ 88135c4bbdfSmrgstatic void 88235c4bbdfSmrgRootlessPolyRectangle(DrawablePtr dst, GCPtr pGC, 88335c4bbdfSmrg int nRects, xRectangle *pRects) 88405b261ecSmrg{ 88505b261ecSmrg GCOP_UNWRAP(pGC); 88605b261ecSmrg RL_DEBUG_MSG("poly rectangle start "); 88705b261ecSmrg 88805b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 88905b261ecSmrg pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); 89005b261ecSmrg 89105b261ecSmrg if (nRects > 0) { 89205b261ecSmrg BoxRec box; 89305b261ecSmrg int offset1, offset2, offset3; 89405b261ecSmrg 89505b261ecSmrg offset2 = pGC->lineWidth; 89635c4bbdfSmrg if (!offset2) 89735c4bbdfSmrg offset2 = 1; 89805b261ecSmrg offset1 = offset2 >> 1; 89905b261ecSmrg offset3 = offset2 - offset1; 90005b261ecSmrg 90105b261ecSmrg while (nRects--) { 90205b261ecSmrg box.x1 = pRects->x - offset1; 90305b261ecSmrg box.y1 = pRects->y - offset1; 90405b261ecSmrg box.x2 = box.x1 + pRects->width + offset2; 90505b261ecSmrg box.y2 = box.y1 + offset2; 90605b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 90705b261ecSmrg if (BOX_NOT_EMPTY(box)) 90835c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 90905b261ecSmrg 91005b261ecSmrg box.x1 = pRects->x - offset1; 91105b261ecSmrg box.y1 = pRects->y + offset3; 91205b261ecSmrg box.x2 = box.x1 + offset2; 91305b261ecSmrg box.y2 = box.y1 + pRects->height - offset2; 91405b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 91505b261ecSmrg if (BOX_NOT_EMPTY(box)) 91635c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 91705b261ecSmrg 91805b261ecSmrg box.x1 = pRects->x + pRects->width - offset1; 91905b261ecSmrg box.y1 = pRects->y + offset3; 92005b261ecSmrg box.x2 = box.x1 + offset2; 92105b261ecSmrg box.y2 = box.y1 + pRects->height - offset2; 92205b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 92305b261ecSmrg if (BOX_NOT_EMPTY(box)) 92435c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 92505b261ecSmrg 92605b261ecSmrg box.x1 = pRects->x - offset1; 92705b261ecSmrg box.y1 = pRects->y + pRects->height - offset1; 92805b261ecSmrg box.x2 = box.x1 + pRects->width + offset2; 92905b261ecSmrg box.y2 = box.y1 + offset2; 93005b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 93105b261ecSmrg if (BOX_NOT_EMPTY(box)) 93235c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 93305b261ecSmrg 93405b261ecSmrg pRects++; 93505b261ecSmrg } 93605b261ecSmrg } 93705b261ecSmrg 93805b261ecSmrg GCOP_WRAP(pGC); 93905b261ecSmrg RL_DEBUG_MSG("poly rectangle end\n"); 94005b261ecSmrg} 94105b261ecSmrg 94205b261ecSmrg/* changed area is box around each arc (assumes all arcs are 360 degrees) */ 94335c4bbdfSmrgstatic void 94435c4bbdfSmrgRootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc * parcs) 94505b261ecSmrg{ 94605b261ecSmrg GCOP_UNWRAP(pGC); 94705b261ecSmrg RL_DEBUG_MSG("poly arc start "); 94805b261ecSmrg 94905b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 95005b261ecSmrg pGC->ops->PolyArc(dst, pGC, narcs, parcs); 95105b261ecSmrg 95205b261ecSmrg if (narcs > 0) { 95305b261ecSmrg int extra = pGC->lineWidth >> 1; 95405b261ecSmrg BoxRec box; 95505b261ecSmrg 95605b261ecSmrg box.x1 = parcs->x; 95705b261ecSmrg box.x2 = box.x1 + parcs->width; 95805b261ecSmrg box.y1 = parcs->y; 95905b261ecSmrg box.y2 = box.y1 + parcs->height; 96005b261ecSmrg 96105b261ecSmrg /* should I break these up instead ? */ 96205b261ecSmrg 96305b261ecSmrg while (--narcs) { 96405b261ecSmrg parcs++; 96505b261ecSmrg if (box.x1 > parcs->x) 96605b261ecSmrg box.x1 = parcs->x; 96705b261ecSmrg if (box.x2 < (parcs->x + parcs->width)) 96805b261ecSmrg box.x2 = parcs->x + parcs->width; 96905b261ecSmrg if (box.y1 > parcs->y) 97005b261ecSmrg box.y1 = parcs->y; 97105b261ecSmrg if (box.y2 < (parcs->y + parcs->height)) 97205b261ecSmrg box.y2 = parcs->y + parcs->height; 97305b261ecSmrg } 97405b261ecSmrg 97505b261ecSmrg if (extra) { 97605b261ecSmrg box.x1 -= extra; 97705b261ecSmrg box.x2 += extra; 97805b261ecSmrg box.y1 -= extra; 97905b261ecSmrg box.y2 += extra; 98005b261ecSmrg } 98105b261ecSmrg 98205b261ecSmrg box.x2++; 98305b261ecSmrg box.y2++; 98405b261ecSmrg 98505b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 98605b261ecSmrg if (BOX_NOT_EMPTY(box)) 98735c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 98805b261ecSmrg } 98905b261ecSmrg 99005b261ecSmrg GCOP_WRAP(pGC); 99105b261ecSmrg RL_DEBUG_MSG("poly arc end\n"); 99205b261ecSmrg} 99305b261ecSmrg 99405b261ecSmrg/* changed area is box around each poly */ 99535c4bbdfSmrgstatic void 99635c4bbdfSmrgRootlessFillPolygon(DrawablePtr dst, GCPtr pGC, 99735c4bbdfSmrg int shape, int mode, int count, DDXPointPtr pptInit) 99805b261ecSmrg{ 99905b261ecSmrg GC_SAVE(pGC); 100005b261ecSmrg GCOP_UNWRAP(pGC); 100105b261ecSmrg RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)", dst, 100205b261ecSmrg pGC->fillStyle); 100305b261ecSmrg 100405b261ecSmrg if (count <= 2) { 100505b261ecSmrg pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); 100635c4bbdfSmrg } 100735c4bbdfSmrg else { 100805b261ecSmrg DDXPointPtr ppt = pptInit; 100905b261ecSmrg int i = count; 101005b261ecSmrg BoxRec box; 101105b261ecSmrg 101205b261ecSmrg box.x2 = box.x1 = ppt->x; 101305b261ecSmrg box.y2 = box.y1 = ppt->y; 101405b261ecSmrg 101505b261ecSmrg if (mode != CoordModeOrigin) { 101605b261ecSmrg int x = box.x1; 101705b261ecSmrg int y = box.y1; 101805b261ecSmrg 101905b261ecSmrg while (--i) { 102005b261ecSmrg ppt++; 102105b261ecSmrg x += ppt->x; 102205b261ecSmrg y += ppt->y; 102305b261ecSmrg if (box.x1 > x) 102405b261ecSmrg box.x1 = x; 102505b261ecSmrg else if (box.x2 < x) 102605b261ecSmrg box.x2 = x; 102705b261ecSmrg if (box.y1 > y) 102805b261ecSmrg box.y1 = y; 102905b261ecSmrg else if (box.y2 < y) 103005b261ecSmrg box.y2 = y; 103105b261ecSmrg } 103235c4bbdfSmrg } 103335c4bbdfSmrg else { 103405b261ecSmrg while (--i) { 103505b261ecSmrg ppt++; 103605b261ecSmrg if (box.x1 > ppt->x) 103705b261ecSmrg box.x1 = ppt->x; 103805b261ecSmrg else if (box.x2 < ppt->x) 103905b261ecSmrg box.x2 = ppt->x; 104005b261ecSmrg if (box.y1 > ppt->y) 104105b261ecSmrg box.y1 = ppt->y; 104205b261ecSmrg else if (box.y2 < ppt->y) 104305b261ecSmrg box.y2 = ppt->y; 104405b261ecSmrg } 104505b261ecSmrg } 104605b261ecSmrg 104705b261ecSmrg box.x2++; 104805b261ecSmrg box.y2++; 104905b261ecSmrg 105005b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 105105b261ecSmrg 105235c4bbdfSmrg if (canAccelFill(dst, pGC)) { 105305b261ecSmrg GC_UNSET_PM(pGC, dst); 105405b261ecSmrg } 105505b261ecSmrg 105605b261ecSmrg pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); 105705b261ecSmrg 105805b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 105905b261ecSmrg if (BOX_NOT_EMPTY(box)) 106035c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 106105b261ecSmrg } 106205b261ecSmrg 106305b261ecSmrg GC_RESTORE(pGC, dst); 106405b261ecSmrg GCOP_WRAP(pGC); 106505b261ecSmrg RL_DEBUG_MSG("fill poly end\n"); 106605b261ecSmrg} 106705b261ecSmrg 106805b261ecSmrg/* changed area is the rects */ 106935c4bbdfSmrgstatic void 107035c4bbdfSmrgRootlessPolyFillRect(DrawablePtr dst, GCPtr pGC, 107135c4bbdfSmrg int nRectsInit, xRectangle *pRectsInit) 107205b261ecSmrg{ 107305b261ecSmrg GC_SAVE(pGC); 107405b261ecSmrg GCOP_UNWRAP(pGC); 107505b261ecSmrg RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)", dst, 107605b261ecSmrg pGC->fillStyle); 107705b261ecSmrg 107805b261ecSmrg if (nRectsInit <= 0) { 107905b261ecSmrg pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); 108035c4bbdfSmrg } 108135c4bbdfSmrg else { 108205b261ecSmrg BoxRec box; 108305b261ecSmrg xRectangle *pRects = pRectsInit; 108405b261ecSmrg int nRects = nRectsInit; 108505b261ecSmrg 108605b261ecSmrg box.x1 = pRects->x; 108705b261ecSmrg box.x2 = box.x1 + pRects->width; 108805b261ecSmrg box.y1 = pRects->y; 108905b261ecSmrg box.y2 = box.y1 + pRects->height; 109005b261ecSmrg 109105b261ecSmrg while (--nRects) { 109205b261ecSmrg pRects++; 109305b261ecSmrg if (box.x1 > pRects->x) 109405b261ecSmrg box.x1 = pRects->x; 109505b261ecSmrg if (box.x2 < (pRects->x + pRects->width)) 109605b261ecSmrg box.x2 = pRects->x + pRects->width; 109705b261ecSmrg if (box.y1 > pRects->y) 109805b261ecSmrg box.y1 = pRects->y; 109905b261ecSmrg if (box.y2 < (pRects->y + pRects->height)) 110005b261ecSmrg box.y2 = pRects->y + pRects->height; 110105b261ecSmrg } 110205b261ecSmrg 110305b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 110435c4bbdfSmrg 110535c4bbdfSmrg if (canAccelFill(dst, pGC)) { 110605b261ecSmrg GC_UNSET_PM(pGC, dst); 110705b261ecSmrg } 110805b261ecSmrg 110935c4bbdfSmrg pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); 111005b261ecSmrg 111105b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 111205b261ecSmrg if (BOX_NOT_EMPTY(box)) 111335c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 111405b261ecSmrg } 111505b261ecSmrg 111605b261ecSmrg GC_RESTORE(pGC, dst); 111705b261ecSmrg GCOP_WRAP(pGC); 111805b261ecSmrg RL_DEBUG_MSG("fill rect end\n"); 111905b261ecSmrg} 112005b261ecSmrg 112105b261ecSmrg/* changed area is box around each arc (assuming arcs are all 360 degrees) */ 112235c4bbdfSmrgstatic void 112335c4bbdfSmrgRootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, int narcsInit, xArc * parcsInit) 112405b261ecSmrg{ 112505b261ecSmrg GC_SAVE(pGC); 112605b261ecSmrg GCOP_UNWRAP(pGC); 112705b261ecSmrg RL_DEBUG_MSG("fill arc start "); 112805b261ecSmrg 112905b261ecSmrg if (narcsInit > 0) { 113005b261ecSmrg BoxRec box; 113105b261ecSmrg int narcs = narcsInit; 113205b261ecSmrg xArc *parcs = parcsInit; 113305b261ecSmrg 113405b261ecSmrg box.x1 = parcs->x; 113505b261ecSmrg box.x2 = box.x1 + parcs->width; 113605b261ecSmrg box.y1 = parcs->y; 113705b261ecSmrg box.y2 = box.y1 + parcs->height; 113805b261ecSmrg 113905b261ecSmrg /* should I break these up instead ? */ 114005b261ecSmrg 114105b261ecSmrg while (--narcs) { 114205b261ecSmrg parcs++; 114305b261ecSmrg if (box.x1 > parcs->x) 114405b261ecSmrg box.x1 = parcs->x; 114505b261ecSmrg if (box.x2 < (parcs->x + parcs->width)) 114605b261ecSmrg box.x2 = parcs->x + parcs->width; 114705b261ecSmrg if (box.y1 > parcs->y) 114805b261ecSmrg box.y1 = parcs->y; 114905b261ecSmrg if (box.y2 < (parcs->y + parcs->height)) 115005b261ecSmrg box.y2 = parcs->y + parcs->height; 115105b261ecSmrg } 115205b261ecSmrg 115305b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 115405b261ecSmrg 115535c4bbdfSmrg if (canAccelFill(dst, pGC)) { 115605b261ecSmrg GC_UNSET_PM(pGC, dst); 115705b261ecSmrg } 115805b261ecSmrg 115905b261ecSmrg pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); 116005b261ecSmrg 116105b261ecSmrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 116205b261ecSmrg if (BOX_NOT_EMPTY(box)) 116335c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 116435c4bbdfSmrg } 116535c4bbdfSmrg else { 116605b261ecSmrg pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); 116705b261ecSmrg } 116805b261ecSmrg 116905b261ecSmrg GC_RESTORE(pGC, dst); 117005b261ecSmrg GCOP_WRAP(pGC); 117105b261ecSmrg RL_DEBUG_MSG("fill arc end\n"); 117205b261ecSmrg} 117305b261ecSmrg 117435c4bbdfSmrgstatic void 117535c4bbdfSmrgRootlessImageText8(DrawablePtr dst, GCPtr pGC, 117635c4bbdfSmrg int x, int y, int count, char *chars) 117705b261ecSmrg{ 117805b261ecSmrg GC_SAVE(pGC); 117905b261ecSmrg GCOP_UNWRAP(pGC); 118005b261ecSmrg RL_DEBUG_MSG("imagetext8 start "); 118105b261ecSmrg 118205b261ecSmrg if (count > 0) { 118305b261ecSmrg int top, bot, Min, Max; 118405b261ecSmrg BoxRec box; 118505b261ecSmrg 118605b261ecSmrg top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); 118705b261ecSmrg bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); 118805b261ecSmrg 118905b261ecSmrg Min = count * FONTMINBOUNDS(pGC->font, characterWidth); 119035c4bbdfSmrg if (Min > 0) 119135c4bbdfSmrg Min = 0; 119205b261ecSmrg Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); 119335c4bbdfSmrg if (Max < 0) 119435c4bbdfSmrg Max = 0; 119505b261ecSmrg 119605b261ecSmrg /* ugh */ 119735c4bbdfSmrg box.x1 = dst->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing); 119835c4bbdfSmrg box.x2 = dst->x + x + Max + FONTMAXBOUNDS(pGC->font, rightSideBearing); 119905b261ecSmrg 120005b261ecSmrg box.y1 = dst->y + y - top; 120105b261ecSmrg box.y2 = dst->y + y + bot; 120205b261ecSmrg 120305b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 120405b261ecSmrg 120535c4bbdfSmrg if (canAccelFill(dst, pGC)) { 120605b261ecSmrg GC_UNSET_PM(pGC, dst); 120705b261ecSmrg } 120805b261ecSmrg 120905b261ecSmrg pGC->ops->ImageText8(dst, pGC, x, y, count, chars); 121005b261ecSmrg 121105b261ecSmrg TRIM_BOX(box, pGC); 121205b261ecSmrg if (BOX_NOT_EMPTY(box)) 121335c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 121435c4bbdfSmrg } 121535c4bbdfSmrg else { 121605b261ecSmrg pGC->ops->ImageText8(dst, pGC, x, y, count, chars); 121705b261ecSmrg } 121805b261ecSmrg 121905b261ecSmrg GC_RESTORE(pGC, dst); 122005b261ecSmrg GCOP_WRAP(pGC); 122105b261ecSmrg RL_DEBUG_MSG("imagetext8 end\n"); 122205b261ecSmrg} 122305b261ecSmrg 122435c4bbdfSmrgstatic int 122535c4bbdfSmrgRootlessPolyText8(DrawablePtr dst, GCPtr pGC, 122635c4bbdfSmrg int x, int y, int count, char *chars) 122705b261ecSmrg{ 122835c4bbdfSmrg int width; // the result, sorta 122905b261ecSmrg 123005b261ecSmrg GCOP_UNWRAP(pGC); 123105b261ecSmrg 123205b261ecSmrg RL_DEBUG_MSG("polytext8 start "); 123305b261ecSmrg 123405b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 123505b261ecSmrg width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); 123605b261ecSmrg width -= x; 123705b261ecSmrg 123805b261ecSmrg if (width > 0) { 123905b261ecSmrg BoxRec box; 124005b261ecSmrg 124105b261ecSmrg /* ugh */ 124205b261ecSmrg box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); 124305b261ecSmrg box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); 124405b261ecSmrg 124505b261ecSmrg if (count > 1) { 1246ed6184dfSmrg box.x2 += width; 124705b261ecSmrg } 124805b261ecSmrg 124905b261ecSmrg box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); 125005b261ecSmrg box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); 125105b261ecSmrg 125205b261ecSmrg TRIM_BOX(box, pGC); 125305b261ecSmrg if (BOX_NOT_EMPTY(box)) 125435c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 125505b261ecSmrg } 125605b261ecSmrg 125705b261ecSmrg GCOP_WRAP(pGC); 125805b261ecSmrg RL_DEBUG_MSG("polytext8 end\n"); 12596747b715Smrg return width + x; 126005b261ecSmrg} 126105b261ecSmrg 126235c4bbdfSmrgstatic void 126335c4bbdfSmrgRootlessImageText16(DrawablePtr dst, GCPtr pGC, 126435c4bbdfSmrg int x, int y, int count, unsigned short *chars) 126505b261ecSmrg{ 126605b261ecSmrg GC_SAVE(pGC); 126705b261ecSmrg GCOP_UNWRAP(pGC); 126805b261ecSmrg RL_DEBUG_MSG("imagetext16 start "); 126905b261ecSmrg 127005b261ecSmrg if (count > 0) { 127105b261ecSmrg int top, bot, Min, Max; 127205b261ecSmrg BoxRec box; 127305b261ecSmrg 127405b261ecSmrg top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); 127505b261ecSmrg bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); 127605b261ecSmrg 127705b261ecSmrg Min = count * FONTMINBOUNDS(pGC->font, characterWidth); 127835c4bbdfSmrg if (Min > 0) 127935c4bbdfSmrg Min = 0; 128005b261ecSmrg Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); 128135c4bbdfSmrg if (Max < 0) 128235c4bbdfSmrg Max = 0; 128305b261ecSmrg 128405b261ecSmrg /* ugh */ 128535c4bbdfSmrg box.x1 = dst->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing); 128635c4bbdfSmrg box.x2 = dst->x + x + Max + FONTMAXBOUNDS(pGC->font, rightSideBearing); 128705b261ecSmrg 128805b261ecSmrg box.y1 = dst->y + y - top; 128905b261ecSmrg box.y2 = dst->y + y + bot; 129005b261ecSmrg 129105b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 129205b261ecSmrg 129335c4bbdfSmrg if (canAccelFill(dst, pGC)) { 129405b261ecSmrg GC_UNSET_PM(pGC, dst); 129505b261ecSmrg } 129605b261ecSmrg 129705b261ecSmrg pGC->ops->ImageText16(dst, pGC, x, y, count, chars); 129805b261ecSmrg 129905b261ecSmrg TRIM_BOX(box, pGC); 130005b261ecSmrg if (BOX_NOT_EMPTY(box)) 130135c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 130235c4bbdfSmrg } 130335c4bbdfSmrg else { 130405b261ecSmrg pGC->ops->ImageText16(dst, pGC, x, y, count, chars); 130505b261ecSmrg } 130605b261ecSmrg 130705b261ecSmrg GC_RESTORE(pGC, dst); 130805b261ecSmrg GCOP_WRAP(pGC); 130905b261ecSmrg RL_DEBUG_MSG("imagetext16 end\n"); 131005b261ecSmrg} 131105b261ecSmrg 131235c4bbdfSmrgstatic int 131335c4bbdfSmrgRootlessPolyText16(DrawablePtr dst, GCPtr pGC, 131435c4bbdfSmrg int x, int y, int count, unsigned short *chars) 131505b261ecSmrg{ 131635c4bbdfSmrg int width; // the result, sorta 131705b261ecSmrg 131805b261ecSmrg GCOP_UNWRAP(pGC); 131905b261ecSmrg 132005b261ecSmrg RL_DEBUG_MSG("polytext16 start "); 132105b261ecSmrg 132205b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 132305b261ecSmrg width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); 132405b261ecSmrg width -= x; 132505b261ecSmrg 132605b261ecSmrg if (width > 0) { 132705b261ecSmrg BoxRec box; 132805b261ecSmrg 132905b261ecSmrg /* ugh */ 133005b261ecSmrg box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); 133105b261ecSmrg box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); 133205b261ecSmrg 133305b261ecSmrg if (count > 1) { 1334ed6184dfSmrg box.x2 += width; 133505b261ecSmrg } 133605b261ecSmrg 133705b261ecSmrg box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); 133805b261ecSmrg box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); 133905b261ecSmrg 134005b261ecSmrg TRIM_BOX(box, pGC); 134105b261ecSmrg if (BOX_NOT_EMPTY(box)) 134235c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 134305b261ecSmrg } 134405b261ecSmrg 134505b261ecSmrg GCOP_WRAP(pGC); 134605b261ecSmrg RL_DEBUG_MSG("polytext16 end\n"); 134705b261ecSmrg return width + x; 134805b261ecSmrg} 134905b261ecSmrg 135035c4bbdfSmrgstatic void 135135c4bbdfSmrgRootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC, 135235c4bbdfSmrg int x, int y, unsigned int nglyphInit, 135335c4bbdfSmrg CharInfoPtr * ppciInit, void *unused) 135405b261ecSmrg{ 135505b261ecSmrg GC_SAVE(pGC); 135605b261ecSmrg GCOP_UNWRAP(pGC); 135705b261ecSmrg RL_DEBUG_MSG("imageglyph start "); 135805b261ecSmrg 135905b261ecSmrg if (nglyphInit > 0) { 136005b261ecSmrg int top, bot, width = 0; 136105b261ecSmrg BoxRec box; 136205b261ecSmrg unsigned int nglyph = nglyphInit; 136305b261ecSmrg CharInfoPtr *ppci = ppciInit; 136405b261ecSmrg 136505b261ecSmrg top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); 136605b261ecSmrg bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); 136705b261ecSmrg 136805b261ecSmrg box.x1 = ppci[0]->metrics.leftSideBearing; 136935c4bbdfSmrg if (box.x1 > 0) 137035c4bbdfSmrg box.x1 = 0; 137105b261ecSmrg box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - 137205b261ecSmrg ppci[nglyph - 1]->metrics.characterWidth; 137335c4bbdfSmrg if (box.x2 < 0) 137435c4bbdfSmrg box.x2 = 0; 137505b261ecSmrg 137605b261ecSmrg box.x2 += dst->x + x; 137705b261ecSmrg box.x1 += dst->x + x; 137805b261ecSmrg 137905b261ecSmrg while (nglyph--) { 138005b261ecSmrg width += (*ppci)->metrics.characterWidth; 138105b261ecSmrg ppci++; 138205b261ecSmrg } 138305b261ecSmrg 138405b261ecSmrg if (width > 0) 138505b261ecSmrg box.x2 += width; 138605b261ecSmrg else 138705b261ecSmrg box.x1 += width; 138805b261ecSmrg 138905b261ecSmrg box.y1 = dst->y + y - top; 139005b261ecSmrg box.y2 = dst->y + y + bot; 139105b261ecSmrg 139205b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 139305b261ecSmrg 139435c4bbdfSmrg if (canAccelFill(dst, pGC)) { 139505b261ecSmrg GC_UNSET_PM(pGC, dst); 139605b261ecSmrg } 139705b261ecSmrg 139805b261ecSmrg pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); 139905b261ecSmrg 140005b261ecSmrg TRIM_BOX(box, pGC); 140105b261ecSmrg if (BOX_NOT_EMPTY(box)) 140235c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 140335c4bbdfSmrg } 140435c4bbdfSmrg else { 140505b261ecSmrg pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); 140605b261ecSmrg } 140705b261ecSmrg 140805b261ecSmrg GC_RESTORE(pGC, dst); 140905b261ecSmrg GCOP_WRAP(pGC); 141005b261ecSmrg RL_DEBUG_MSG("imageglyph end\n"); 141105b261ecSmrg} 141205b261ecSmrg 141335c4bbdfSmrgstatic void 141435c4bbdfSmrgRootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, 141535c4bbdfSmrg int x, int y, unsigned int nglyph, 141635c4bbdfSmrg CharInfoPtr * ppci, void *pglyphBase) 141705b261ecSmrg{ 141805b261ecSmrg GCOP_UNWRAP(pGC); 141905b261ecSmrg RL_DEBUG_MSG("polyglyph start "); 142005b261ecSmrg 142105b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 142205b261ecSmrg pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); 142305b261ecSmrg 142405b261ecSmrg if (nglyph > 0) { 142505b261ecSmrg BoxRec box; 142605b261ecSmrg 142705b261ecSmrg /* ugh */ 142805b261ecSmrg box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing; 142905b261ecSmrg box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing; 143005b261ecSmrg 143105b261ecSmrg if (nglyph > 1) { 143205b261ecSmrg int width = 0; 143305b261ecSmrg 143405b261ecSmrg while (--nglyph) { 143505b261ecSmrg width += (*ppci)->metrics.characterWidth; 143605b261ecSmrg ppci++; 143705b261ecSmrg } 143805b261ecSmrg 143935c4bbdfSmrg if (width > 0) 144035c4bbdfSmrg box.x2 += width; 144135c4bbdfSmrg else 144235c4bbdfSmrg box.x1 += width; 144305b261ecSmrg } 144405b261ecSmrg 144505b261ecSmrg box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); 144605b261ecSmrg box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); 144705b261ecSmrg 144805b261ecSmrg TRIM_BOX(box, pGC); 144905b261ecSmrg if (BOX_NOT_EMPTY(box)) 145035c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 145105b261ecSmrg } 145205b261ecSmrg 145305b261ecSmrg GCOP_WRAP(pGC); 145405b261ecSmrg RL_DEBUG_MSG("polyglyph end\n"); 145505b261ecSmrg} 145605b261ecSmrg 145705b261ecSmrg/* changed area is in dest */ 145805b261ecSmrgstatic void 145905b261ecSmrgRootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, 146005b261ecSmrg int dx, int dy, int xOrg, int yOrg) 146105b261ecSmrg{ 146205b261ecSmrg BoxRec box; 146305b261ecSmrg 146405b261ecSmrg GCOP_UNWRAP(pGC); 146505b261ecSmrg RL_DEBUG_MSG("push pixels start "); 146605b261ecSmrg 146705b261ecSmrg RootlessStartDrawing((WindowPtr) dst); 146805b261ecSmrg pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); 146905b261ecSmrg 147005b261ecSmrg box.x1 = xOrg + dst->x; 147105b261ecSmrg box.x2 = box.x1 + dx; 147205b261ecSmrg box.y1 = yOrg + dst->y; 147305b261ecSmrg box.y2 = box.y1 + dy; 147405b261ecSmrg 147505b261ecSmrg TRIM_BOX(box, pGC); 147605b261ecSmrg if (BOX_NOT_EMPTY(box)) 147735c4bbdfSmrg RootlessDamageBox((WindowPtr) dst, &box); 147805b261ecSmrg 147905b261ecSmrg GCOP_WRAP(pGC); 148005b261ecSmrg RL_DEBUG_MSG("push pixels end\n"); 148105b261ecSmrg} 1482