1706f2543Smrg/* 2706f2543Smrg * Graphics Context support for generic rootless X server 3706f2543Smrg */ 4706f2543Smrg/* 5706f2543Smrg * Copyright (c) 2001 Greg Parker. All Rights Reserved. 6706f2543Smrg * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. 7706f2543Smrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 8706f2543Smrg * 9706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 10706f2543Smrg * copy of this software and associated documentation files (the "Software"), 11706f2543Smrg * to deal in the Software without restriction, including without limitation 12706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 14706f2543Smrg * Software is furnished to do so, subject to the following conditions: 15706f2543Smrg * 16706f2543Smrg * The above copyright notice and this permission notice shall be included in 17706f2543Smrg * all copies or substantial portions of the Software. 18706f2543Smrg * 19706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 23706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25706f2543Smrg * DEALINGS IN THE SOFTWARE. 26706f2543Smrg * 27706f2543Smrg * Except as contained in this notice, the name(s) of the above copyright 28706f2543Smrg * holders shall not be used in advertising or otherwise to promote the sale, 29706f2543Smrg * use or other dealings in this Software without prior written authorization. 30706f2543Smrg */ 31706f2543Smrg 32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 33706f2543Smrg#include <dix-config.h> 34706f2543Smrg#endif 35706f2543Smrg 36706f2543Smrg#include <stddef.h> /* For NULL */ 37706f2543Smrg#include "mi.h" 38706f2543Smrg#include "scrnintstr.h" 39706f2543Smrg#include "gcstruct.h" 40706f2543Smrg#include "pixmapstr.h" 41706f2543Smrg#include "windowstr.h" 42706f2543Smrg#include "dixfontstr.h" 43706f2543Smrg#include "mivalidate.h" 44706f2543Smrg#include "fb.h" 45706f2543Smrg 46706f2543Smrg#include <sys/types.h> 47706f2543Smrg#include <sys/stat.h> 48706f2543Smrg#include <fcntl.h> 49706f2543Smrg 50706f2543Smrg#include "rootlessCommon.h" 51706f2543Smrg 52706f2543Smrg 53706f2543Smrg// GC functions 54706f2543Smrgstatic void RootlessValidateGC(GCPtr pGC, unsigned long changes, 55706f2543Smrg DrawablePtr pDrawable); 56706f2543Smrgstatic void RootlessChangeGC(GCPtr pGC, unsigned long mask); 57706f2543Smrgstatic void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); 58706f2543Smrgstatic void RootlessDestroyGC(GCPtr pGC); 59706f2543Smrgstatic void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, 60706f2543Smrg int nrects); 61706f2543Smrgstatic void RootlessDestroyClip(GCPtr pGC); 62706f2543Smrgstatic void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc); 63706f2543Smrg 64706f2543SmrgBool RootlessCreateGC(GCPtr pGC); 65706f2543Smrg 66706f2543SmrgGCFuncs rootlessGCFuncs = { 67706f2543Smrg RootlessValidateGC, 68706f2543Smrg RootlessChangeGC, 69706f2543Smrg RootlessCopyGC, 70706f2543Smrg RootlessDestroyGC, 71706f2543Smrg RootlessChangeClip, 72706f2543Smrg RootlessDestroyClip, 73706f2543Smrg RootlessCopyClip, 74706f2543Smrg}; 75706f2543Smrg 76706f2543Smrg// GC operations 77706f2543Smrgstatic void RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, 78706f2543Smrg DDXPointPtr pptInit, int *pwidthInit, 79706f2543Smrg int sorted); 80706f2543Smrgstatic void RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, 81706f2543Smrg DDXPointPtr pptInit, int *pwidthInit, 82706f2543Smrg int nspans, int sorted); 83706f2543Smrgstatic void RootlessPutImage(DrawablePtr dst, GCPtr pGC, 84706f2543Smrg int depth, int x, int y, int w, int h, 85706f2543Smrg int leftPad, int format, char *pBits); 86706f2543Smrgstatic RegionPtr RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, 87706f2543Smrg int srcx, int srcy, int w, int h, 88706f2543Smrg int dstx, int dsty); 89706f2543Smrgstatic RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst, 90706f2543Smrg GCPtr pGC, int srcx, int srcy, 91706f2543Smrg int w, int h, int dstx, int dsty, 92706f2543Smrg unsigned long plane); 93706f2543Smrgstatic void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC, 94706f2543Smrg int mode, int npt, DDXPointPtr pptInit); 95706f2543Smrgstatic void RootlessPolylines(DrawablePtr dst, GCPtr pGC, 96706f2543Smrg int mode, int npt, DDXPointPtr pptInit); 97706f2543Smrgstatic void RootlessPolySegment(DrawablePtr dst, GCPtr pGC, 98706f2543Smrg int nseg, xSegment *pSeg); 99706f2543Smrgstatic void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC, 100706f2543Smrg int nRects, xRectangle *pRects); 101706f2543Smrgstatic void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs); 102706f2543Smrgstatic void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC, 103706f2543Smrg int shape, int mode, int count, 104706f2543Smrg DDXPointPtr pptInit); 105706f2543Smrgstatic void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC, 106706f2543Smrg int nRectsInit, xRectangle *pRectsInit); 107706f2543Smrgstatic void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, 108706f2543Smrg int narcsInit, xArc *parcsInit); 109706f2543Smrgstatic int RootlessPolyText8(DrawablePtr dst, GCPtr pGC, 110706f2543Smrg int x, int y, int count, char *chars); 111706f2543Smrgstatic int RootlessPolyText16(DrawablePtr dst, GCPtr pGC, 112706f2543Smrg int x, int y, int count, unsigned short *chars); 113706f2543Smrgstatic void RootlessImageText8(DrawablePtr dst, GCPtr pGC, 114706f2543Smrg int x, int y, int count, char *chars); 115706f2543Smrgstatic void RootlessImageText16(DrawablePtr dst, GCPtr pGC, 116706f2543Smrg int x, int y, int count, unsigned short *chars); 117706f2543Smrgstatic void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC, 118706f2543Smrg int x, int y, unsigned int nglyphInit, 119706f2543Smrg CharInfoPtr *ppciInit, pointer unused); 120706f2543Smrgstatic void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, 121706f2543Smrg int x, int y, unsigned int nglyph, 122706f2543Smrg CharInfoPtr *ppci, pointer pglyphBase); 123706f2543Smrgstatic void RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, 124706f2543Smrg int dx, int dy, int xOrg, int yOrg); 125706f2543Smrg 126706f2543Smrg 127706f2543Smrgstatic GCOps rootlessGCOps = { 128706f2543Smrg RootlessFillSpans, 129706f2543Smrg RootlessSetSpans, 130706f2543Smrg RootlessPutImage, 131706f2543Smrg RootlessCopyArea, 132706f2543Smrg RootlessCopyPlane, 133706f2543Smrg RootlessPolyPoint, 134706f2543Smrg RootlessPolylines, 135706f2543Smrg RootlessPolySegment, 136706f2543Smrg RootlessPolyRectangle, 137706f2543Smrg RootlessPolyArc, 138706f2543Smrg RootlessFillPolygon, 139706f2543Smrg RootlessPolyFillRect, 140706f2543Smrg RootlessPolyFillArc, 141706f2543Smrg RootlessPolyText8, 142706f2543Smrg RootlessPolyText16, 143706f2543Smrg RootlessImageText8, 144706f2543Smrg RootlessImageText16, 145706f2543Smrg RootlessImageGlyphBlt, 146706f2543Smrg RootlessPolyGlyphBlt, 147706f2543Smrg RootlessPushPixels 148706f2543Smrg}; 149706f2543Smrg 150706f2543Smrg/* 151706f2543Smrg If ROOTLESS_PROTECT_ALPHA is set, we have to make sure that the alpha 152706f2543Smrg channel of the on screen windows is always opaque. fb makes this harder 153706f2543Smrg than it would otherwise be by noticing that a planemask of 0x00ffffff 154706f2543Smrg includes all bits when depth==24, and so it "optimizes" the planemask to 155706f2543Smrg 0xffffffff. We work around this by temporarily setting depth=bpp while 156706f2543Smrg changing the GC. 157706f2543Smrg 158706f2543Smrg So the normal situation (in 32 bit mode) is that the planemask is 159706f2543Smrg 0x00ffffff and thus fb leaves the alpha channel alone. The rootless 160706f2543Smrg implementation is responsible for setting the alpha channel opaque 161706f2543Smrg initially. 162706f2543Smrg 163706f2543Smrg Unfortunately drawing with a planemask that doesn't have all bits set 164706f2543Smrg normally causes fb to fall off its fastest paths when blitting and 165706f2543Smrg filling. So we try to recognize when we can relax the planemask back to 166706f2543Smrg 0xffffffff, and do that for the duration of the drawing operation, 167706f2543Smrg setting the alpha channel in fg/bg pixels to opaque at the same time. We 168706f2543Smrg can do this when drawing op is GXcopy. We can also do this when copying 169706f2543Smrg from another window since its alpha channel must also be opaque. 170706f2543Smrg 171706f2543Smrg The three macros below are used to implement this. Drawing ops that can 172706f2543Smrg potentially have their planemask relaxed look like: 173706f2543Smrg 174706f2543Smrg OP { 175706f2543Smrg GC_SAVE(gc); 176706f2543Smrg GCOP_UNWRAP(gc); 177706f2543Smrg 178706f2543Smrg ... 179706f2543Smrg 180706f2543Smrg if (canAccelxxx(..) && otherwise-suitable) 181706f2543Smrg GC_UNSET_PM(gc, dst); 182706f2543Smrg 183706f2543Smrg gc->funcs->OP(gc, ...); 184706f2543Smrg 185706f2543Smrg GC_RESTORE(gc, dst); 186706f2543Smrg GCOP_WRAP(gc); 187706f2543Smrg } 188706f2543Smrg 189706f2543Smrg */ 190706f2543Smrg 191706f2543Smrg#define GC_SAVE(pGC) \ 192706f2543Smrg unsigned long _save_fg = (pGC)->fgPixel; \ 193706f2543Smrg unsigned long _save_bg = (pGC)->bgPixel; \ 194706f2543Smrg unsigned long _save_pm = (pGC)->planemask; \ 195706f2543Smrg Bool _changed = FALSE 196706f2543Smrg 197706f2543Smrg#define GC_RESTORE(pGC, pDraw) \ 198706f2543Smrg do { \ 199706f2543Smrg if (_changed) { \ 200706f2543Smrg unsigned int depth = (pDraw)->depth; \ 201706f2543Smrg (pGC)->fgPixel = _save_fg; \ 202706f2543Smrg (pGC)->bgPixel = _save_bg; \ 203706f2543Smrg (pGC)->planemask = _save_pm; \ 204706f2543Smrg (pDraw)->depth = (pDraw)->bitsPerPixel; \ 205706f2543Smrg VALIDATE_GC(pGC, GCForeground | GCBackground | \ 206706f2543Smrg GCPlaneMask, pDraw); \ 207706f2543Smrg (pDraw)->depth = depth; \ 208706f2543Smrg } \ 209706f2543Smrg } while (0) 210706f2543Smrg 211706f2543Smrg#define GC_UNSET_PM(pGC, pDraw) \ 212706f2543Smrg do { \ 213706f2543Smrg unsigned int mask = RootlessAlphaMask ((pDraw)->bitsPerPixel); \ 214706f2543Smrg if (((pGC)->planemask & mask) != mask) { \ 215706f2543Smrg unsigned int depth = (pDraw)->depth; \ 216706f2543Smrg (pGC)->fgPixel |= mask; \ 217706f2543Smrg (pGC)->bgPixel |= mask; \ 218706f2543Smrg (pGC)->planemask |= mask; \ 219706f2543Smrg (pDraw)->depth = (pDraw)->bitsPerPixel; \ 220706f2543Smrg VALIDATE_GC(pGC, GCForeground | \ 221706f2543Smrg GCBackground | GCPlaneMask, pDraw); \ 222706f2543Smrg (pDraw)->depth = depth; \ 223706f2543Smrg _changed = TRUE; \ 224706f2543Smrg } \ 225706f2543Smrg } while (0) 226706f2543Smrg 227706f2543Smrg#define VALIDATE_GC(pGC, changes, pDrawable) \ 228706f2543Smrg do { \ 229706f2543Smrg pGC->funcs->ValidateGC(pGC, changes, pDrawable); \ 230706f2543Smrg if (((WindowPtr) pDrawable)->viewable) { \ 231706f2543Smrg gcrec->originalOps = pGC->ops; \ 232706f2543Smrg } \ 233706f2543Smrg } while(0) 234706f2543Smrg 235706f2543Smrgstatic RootlessWindowRec * 236706f2543SmrgcanAccelBlit (DrawablePtr pDraw, GCPtr pGC) 237706f2543Smrg{ 238706f2543Smrg WindowPtr pTop; 239706f2543Smrg RootlessWindowRec *winRec; 240706f2543Smrg unsigned int pm; 241706f2543Smrg 242706f2543Smrg if (pGC->alu != GXcopy) 243706f2543Smrg return NULL; 244706f2543Smrg 245706f2543Smrg if (pDraw->type != DRAWABLE_WINDOW) 246706f2543Smrg return NULL; 247706f2543Smrg 248706f2543Smrg pm = ~RootlessAlphaMask(pDraw->bitsPerPixel); 249706f2543Smrg if ((pGC->planemask & pm) != pm) 250706f2543Smrg return NULL; 251706f2543Smrg 252706f2543Smrg pTop = TopLevelParent((WindowPtr) pDraw); 253706f2543Smrg if (pTop == NULL) 254706f2543Smrg return NULL; 255706f2543Smrg 256706f2543Smrg winRec = WINREC(pTop); 257706f2543Smrg if (winRec == NULL) 258706f2543Smrg return NULL; 259706f2543Smrg 260706f2543Smrg return winRec; 261706f2543Smrg} 262706f2543Smrg 263706f2543Smrgstatic inline RootlessWindowRec * 264706f2543SmrgcanAccelFill(DrawablePtr pDraw, GCPtr pGC) 265706f2543Smrg{ 266706f2543Smrg if (pGC->fillStyle != FillSolid) 267706f2543Smrg return NULL; 268706f2543Smrg 269706f2543Smrg return canAccelBlit(pDraw, pGC); 270706f2543Smrg} 271706f2543Smrg 272706f2543Smrg 273706f2543Smrg/* 274706f2543Smrg * Screen function to create a graphics context 275706f2543Smrg */ 276706f2543SmrgBool 277706f2543SmrgRootlessCreateGC(GCPtr pGC) 278706f2543Smrg{ 279706f2543Smrg RootlessGCRec *gcrec; 280706f2543Smrg RootlessScreenRec *s; 281706f2543Smrg Bool result; 282706f2543Smrg 283706f2543Smrg SCREEN_UNWRAP(pGC->pScreen, CreateGC); 284706f2543Smrg s = SCREENREC(pGC->pScreen); 285706f2543Smrg result = s->CreateGC(pGC); 286706f2543Smrg 287706f2543Smrg gcrec = (RootlessGCRec *) 288706f2543Smrg dixLookupPrivate(&pGC->devPrivates, rootlessGCPrivateKey); 289706f2543Smrg gcrec->originalOps = NULL; // don't wrap ops yet 290706f2543Smrg gcrec->originalFuncs = pGC->funcs; 291706f2543Smrg pGC->funcs = &rootlessGCFuncs; 292706f2543Smrg 293706f2543Smrg SCREEN_WRAP(pGC->pScreen, CreateGC); 294706f2543Smrg return result; 295706f2543Smrg} 296706f2543Smrg 297706f2543Smrg 298706f2543Smrg/* 299706f2543Smrg * GC funcs 300706f2543Smrg * 301706f2543Smrg * These wrap lower level GC funcs. 302706f2543Smrg * ValidateGC wraps the GC ops iff dest is viewable. 303706f2543Smrg * All the others just unwrap and call. 304706f2543Smrg */ 305706f2543Smrg 306706f2543Smrg// GCFUNC_UNRAP assumes funcs have been wrapped and 307706f2543Smrg// does not assume ops have been wrapped 308706f2543Smrg#define GCFUNC_UNWRAP(pGC) \ 309706f2543Smrg RootlessGCRec *gcrec = (RootlessGCRec *) \ 310706f2543Smrg dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \ 311706f2543Smrg (pGC)->funcs = gcrec->originalFuncs; \ 312706f2543Smrg if (gcrec->originalOps) { \ 313706f2543Smrg (pGC)->ops = gcrec->originalOps; \ 314706f2543Smrg} 315706f2543Smrg 316706f2543Smrg#define GCFUNC_WRAP(pGC) \ 317706f2543Smrg gcrec->originalFuncs = (pGC)->funcs; \ 318706f2543Smrg (pGC)->funcs = &rootlessGCFuncs; \ 319706f2543Smrg if (gcrec->originalOps) { \ 320706f2543Smrg gcrec->originalOps = (pGC)->ops; \ 321706f2543Smrg (pGC)->ops = &rootlessGCOps; \ 322706f2543Smrg} 323706f2543Smrg 324706f2543Smrg 325706f2543Smrgstatic void 326706f2543SmrgRootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 327706f2543Smrg{ 328706f2543Smrg GCFUNC_UNWRAP(pGC); 329706f2543Smrg 330706f2543Smrg gcrec->originalOps = NULL; 331706f2543Smrg 332706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) 333706f2543Smrg { 334706f2543Smrg#ifdef ROOTLESS_PROTECT_ALPHA 335706f2543Smrg unsigned int depth = pDrawable->depth; 336706f2543Smrg 337706f2543Smrg // We force a planemask so fb doesn't overwrite the alpha channel. 338706f2543Smrg // Left to its own devices, fb will optimize away the planemask. 339706f2543Smrg pDrawable->depth = pDrawable->bitsPerPixel; 340706f2543Smrg pGC->planemask &= ~RootlessAlphaMask(pDrawable->bitsPerPixel); 341706f2543Smrg VALIDATE_GC(pGC, changes | GCPlaneMask, pDrawable); 342706f2543Smrg pDrawable->depth = depth; 343706f2543Smrg#else 344706f2543Smrg VALIDATE_GC(pGC, changes, pDrawable); 345706f2543Smrg#endif 346706f2543Smrg } else { 347706f2543Smrg pGC->funcs->ValidateGC(pGC, changes, pDrawable); 348706f2543Smrg } 349706f2543Smrg 350706f2543Smrg GCFUNC_WRAP(pGC); 351706f2543Smrg} 352706f2543Smrg 353706f2543Smrgstatic void RootlessChangeGC(GCPtr pGC, unsigned long mask) 354706f2543Smrg{ 355706f2543Smrg GCFUNC_UNWRAP(pGC); 356706f2543Smrg pGC->funcs->ChangeGC(pGC, mask); 357706f2543Smrg GCFUNC_WRAP(pGC); 358706f2543Smrg} 359706f2543Smrg 360706f2543Smrgstatic void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) 361706f2543Smrg{ 362706f2543Smrg GCFUNC_UNWRAP(pGCDst); 363706f2543Smrg pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst); 364706f2543Smrg GCFUNC_WRAP(pGCDst); 365706f2543Smrg} 366706f2543Smrg 367706f2543Smrgstatic void RootlessDestroyGC(GCPtr pGC) 368706f2543Smrg{ 369706f2543Smrg GCFUNC_UNWRAP(pGC); 370706f2543Smrg pGC->funcs->DestroyGC(pGC); 371706f2543Smrg GCFUNC_WRAP(pGC); 372706f2543Smrg} 373706f2543Smrg 374706f2543Smrgstatic void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects) 375706f2543Smrg{ 376706f2543Smrg GCFUNC_UNWRAP(pGC); 377706f2543Smrg pGC->funcs->ChangeClip(pGC, type, pvalue, nrects); 378706f2543Smrg GCFUNC_WRAP(pGC); 379706f2543Smrg} 380706f2543Smrg 381706f2543Smrgstatic void RootlessDestroyClip(GCPtr pGC) 382706f2543Smrg{ 383706f2543Smrg GCFUNC_UNWRAP(pGC); 384706f2543Smrg pGC->funcs->DestroyClip(pGC); 385706f2543Smrg GCFUNC_WRAP(pGC); 386706f2543Smrg} 387706f2543Smrg 388706f2543Smrgstatic void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc) 389706f2543Smrg{ 390706f2543Smrg GCFUNC_UNWRAP(pgcDst); 391706f2543Smrg pgcDst->funcs->CopyClip(pgcDst, pgcSrc); 392706f2543Smrg GCFUNC_WRAP(pgcDst); 393706f2543Smrg} 394706f2543Smrg 395706f2543Smrg 396706f2543Smrg/* 397706f2543Smrg * GC ops 398706f2543Smrg * 399706f2543Smrg * We can't use shadowfb because shadowfb assumes one pixmap 400706f2543Smrg * and our root window is a special case. 401706f2543Smrg * However, much of this code is copied from shadowfb. 402706f2543Smrg */ 403706f2543Smrg 404706f2543Smrg// assumes both funcs and ops are wrapped 405706f2543Smrg#define GCOP_UNWRAP(pGC) \ 406706f2543Smrg RootlessGCRec *gcrec = (RootlessGCRec *) \ 407706f2543Smrg dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \ 408706f2543Smrg GCFuncs *saveFuncs = pGC->funcs; \ 409706f2543Smrg (pGC)->funcs = gcrec->originalFuncs; \ 410706f2543Smrg (pGC)->ops = gcrec->originalOps; 411706f2543Smrg 412706f2543Smrg#define GCOP_WRAP(pGC) \ 413706f2543Smrg gcrec->originalOps = (pGC)->ops; \ 414706f2543Smrg (pGC)->funcs = saveFuncs; \ 415706f2543Smrg (pGC)->ops = &rootlessGCOps; 416706f2543Smrg 417706f2543Smrgstatic void 418706f2543SmrgRootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, 419706f2543Smrg DDXPointPtr pptInit, int *pwidthInit, int sorted) 420706f2543Smrg{ 421706f2543Smrg GC_SAVE(pGC); 422706f2543Smrg GCOP_UNWRAP(pGC); 423706f2543Smrg RL_DEBUG_MSG("fill spans start "); 424706f2543Smrg 425706f2543Smrg if (nInit <= 0) { 426706f2543Smrg pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); 427706f2543Smrg } else { 428706f2543Smrg DDXPointPtr ppt = pptInit; 429706f2543Smrg int *pwidth = pwidthInit; 430706f2543Smrg int i = nInit; 431706f2543Smrg BoxRec box; 432706f2543Smrg 433706f2543Smrg box.x1 = ppt->x; 434706f2543Smrg box.x2 = box.x1 + *pwidth; 435706f2543Smrg box.y2 = box.y1 = ppt->y; 436706f2543Smrg 437706f2543Smrg while (--i) { 438706f2543Smrg ppt++; 439706f2543Smrg pwidth++; 440706f2543Smrg if (box.x1 > ppt->x) 441706f2543Smrg box.x1 = ppt->x; 442706f2543Smrg if (box.x2 < (ppt->x + *pwidth)) 443706f2543Smrg box.x2 = ppt->x + *pwidth; 444706f2543Smrg if (box.y1 > ppt->y) 445706f2543Smrg box.y1 = ppt->y; 446706f2543Smrg else if (box.y2 < ppt->y) 447706f2543Smrg box.y2 = ppt->y; 448706f2543Smrg } 449706f2543Smrg 450706f2543Smrg box.y2++; 451706f2543Smrg 452706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 453706f2543Smrg 454706f2543Smrg if (canAccelFill(dst, pGC)) 455706f2543Smrg { 456706f2543Smrg GC_UNSET_PM(pGC, dst); 457706f2543Smrg } 458706f2543Smrg 459706f2543Smrg pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); 460706f2543Smrg 461706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 462706f2543Smrg if (BOX_NOT_EMPTY(box)) 463706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 464706f2543Smrg } 465706f2543Smrg 466706f2543Smrg GC_RESTORE(pGC, dst); 467706f2543Smrg GCOP_WRAP(pGC); 468706f2543Smrg RL_DEBUG_MSG("fill spans end\n"); 469706f2543Smrg} 470706f2543Smrg 471706f2543Smrgstatic void 472706f2543SmrgRootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, 473706f2543Smrg DDXPointPtr pptInit, int *pwidthInit, 474706f2543Smrg int nspans, int sorted) 475706f2543Smrg{ 476706f2543Smrg GCOP_UNWRAP(pGC); 477706f2543Smrg RL_DEBUG_MSG("set spans start "); 478706f2543Smrg 479706f2543Smrg if (nspans <= 0) { 480706f2543Smrg pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, 481706f2543Smrg nspans, sorted); 482706f2543Smrg } else { 483706f2543Smrg DDXPointPtr ppt = pptInit; 484706f2543Smrg int *pwidth = pwidthInit; 485706f2543Smrg int i = nspans; 486706f2543Smrg BoxRec box; 487706f2543Smrg 488706f2543Smrg box.x1 = ppt->x; 489706f2543Smrg box.x2 = box.x1 + *pwidth; 490706f2543Smrg box.y2 = box.y1 = ppt->y; 491706f2543Smrg 492706f2543Smrg while (--i) { 493706f2543Smrg ppt++; 494706f2543Smrg pwidth++; 495706f2543Smrg if (box.x1 > ppt->x) 496706f2543Smrg box.x1 = ppt->x; 497706f2543Smrg if (box.x2 < (ppt->x + *pwidth)) 498706f2543Smrg box.x2 = ppt->x + *pwidth; 499706f2543Smrg if (box.y1 > ppt->y) 500706f2543Smrg box.y1 = ppt->y; 501706f2543Smrg else if (box.y2 < ppt->y) 502706f2543Smrg box.y2 = ppt->y; 503706f2543Smrg } 504706f2543Smrg 505706f2543Smrg box.y2++; 506706f2543Smrg 507706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 508706f2543Smrg pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, 509706f2543Smrg nspans, sorted); 510706f2543Smrg 511706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 512706f2543Smrg if (BOX_NOT_EMPTY(box)) 513706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 514706f2543Smrg } 515706f2543Smrg GCOP_WRAP(pGC); 516706f2543Smrg RL_DEBUG_MSG("set spans end\n"); 517706f2543Smrg} 518706f2543Smrg 519706f2543Smrgstatic void 520706f2543SmrgRootlessPutImage(DrawablePtr dst, GCPtr pGC, 521706f2543Smrg int depth, int x, int y, int w, int h, 522706f2543Smrg int leftPad, int format, char *pBits) 523706f2543Smrg{ 524706f2543Smrg BoxRec box; 525706f2543Smrg 526706f2543Smrg GCOP_UNWRAP(pGC); 527706f2543Smrg RL_DEBUG_MSG("put image start "); 528706f2543Smrg 529706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 530706f2543Smrg pGC->ops->PutImage(dst, pGC, depth, x,y,w,h, leftPad, format, pBits); 531706f2543Smrg 532706f2543Smrg box.x1 = x + dst->x; 533706f2543Smrg box.x2 = box.x1 + w; 534706f2543Smrg box.y1 = y + dst->y; 535706f2543Smrg box.y2 = box.y1 + h; 536706f2543Smrg 537706f2543Smrg TRIM_BOX(box, pGC); 538706f2543Smrg if (BOX_NOT_EMPTY(box)) 539706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 540706f2543Smrg 541706f2543Smrg GCOP_WRAP(pGC); 542706f2543Smrg RL_DEBUG_MSG("put image end\n"); 543706f2543Smrg} 544706f2543Smrg 545706f2543Smrg/* changed area is *dest* rect */ 546706f2543Smrgstatic RegionPtr 547706f2543SmrgRootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, 548706f2543Smrg int srcx, int srcy, int w, int h, 549706f2543Smrg int dstx, int dsty) 550706f2543Smrg{ 551706f2543Smrg RegionPtr result; 552706f2543Smrg BoxRec box; 553706f2543Smrg 554706f2543Smrg GC_SAVE(pGC); 555706f2543Smrg GCOP_UNWRAP(pGC); 556706f2543Smrg 557706f2543Smrg RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst); 558706f2543Smrg 559706f2543Smrg if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) { 560706f2543Smrg /* If both source and dest are windows, and we're doing 561706f2543Smrg a simple copy operation, we can remove the alpha-protecting 562706f2543Smrg planemask (since source has opaque alpha as well) */ 563706f2543Smrg 564706f2543Smrg if (canAccelBlit(pSrc, pGC)) 565706f2543Smrg { 566706f2543Smrg GC_UNSET_PM(pGC, dst); 567706f2543Smrg } 568706f2543Smrg 569706f2543Smrg RootlessStartDrawing((WindowPtr) pSrc); 570706f2543Smrg } 571706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 572706f2543Smrg result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); 573706f2543Smrg 574706f2543Smrg box.x1 = dstx + dst->x; 575706f2543Smrg box.x2 = box.x1 + w; 576706f2543Smrg box.y1 = dsty + dst->y; 577706f2543Smrg box.y2 = box.y1 + h; 578706f2543Smrg 579706f2543Smrg TRIM_BOX(box, pGC); 580706f2543Smrg if (BOX_NOT_EMPTY(box)) 581706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 582706f2543Smrg 583706f2543Smrg GC_RESTORE(pGC, dst); 584706f2543Smrg GCOP_WRAP(pGC); 585706f2543Smrg RL_DEBUG_MSG("copy area end\n"); 586706f2543Smrg return result; 587706f2543Smrg} 588706f2543Smrg 589706f2543Smrg/* changed area is *dest* rect */ 590706f2543Smrgstatic RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst, 591706f2543Smrg GCPtr pGC, int srcx, int srcy, 592706f2543Smrg int w, int h, int dstx, int dsty, 593706f2543Smrg unsigned long plane) 594706f2543Smrg{ 595706f2543Smrg RegionPtr result; 596706f2543Smrg BoxRec box; 597706f2543Smrg 598706f2543Smrg GCOP_UNWRAP(pGC); 599706f2543Smrg 600706f2543Smrg RL_DEBUG_MSG("copy plane start "); 601706f2543Smrg 602706f2543Smrg if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) { 603706f2543Smrg RootlessStartDrawing((WindowPtr) pSrc); 604706f2543Smrg } 605706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 606706f2543Smrg result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, 607706f2543Smrg dstx, dsty, plane); 608706f2543Smrg 609706f2543Smrg box.x1 = dstx + dst->x; 610706f2543Smrg box.x2 = box.x1 + w; 611706f2543Smrg box.y1 = dsty + dst->y; 612706f2543Smrg box.y2 = box.y1 + h; 613706f2543Smrg 614706f2543Smrg TRIM_BOX(box, pGC); 615706f2543Smrg if (BOX_NOT_EMPTY(box)) 616706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 617706f2543Smrg 618706f2543Smrg GCOP_WRAP(pGC); 619706f2543Smrg RL_DEBUG_MSG("copy plane end\n"); 620706f2543Smrg return result; 621706f2543Smrg} 622706f2543Smrg 623706f2543Smrg// Options for size of changed area: 624706f2543Smrg// 0 = box per point 625706f2543Smrg// 1 = big box around all points 626706f2543Smrg// 2 = accumulate point in 20 pixel radius 627706f2543Smrg#define ROOTLESS_CHANGED_AREA 1 628706f2543Smrg#define abs(a) ((a) > 0 ? (a) : -(a)) 629706f2543Smrg 630706f2543Smrg/* changed area is box around all points */ 631706f2543Smrgstatic void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC, 632706f2543Smrg int mode, int npt, DDXPointPtr pptInit) 633706f2543Smrg{ 634706f2543Smrg GCOP_UNWRAP(pGC); 635706f2543Smrg RL_DEBUG_MSG("polypoint start "); 636706f2543Smrg 637706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 638706f2543Smrg pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); 639706f2543Smrg 640706f2543Smrg if (npt > 0) { 641706f2543Smrg#if ROOTLESS_CHANGED_AREA==0 642706f2543Smrg // box per point 643706f2543Smrg BoxRec box; 644706f2543Smrg 645706f2543Smrg while (npt) { 646706f2543Smrg box.x1 = pptInit->x; 647706f2543Smrg box.y1 = pptInit->y; 648706f2543Smrg box.x2 = box.x1 + 1; 649706f2543Smrg box.y2 = box.y1 + 1; 650706f2543Smrg 651706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 652706f2543Smrg if (BOX_NOT_EMPTY(box)) 653706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 654706f2543Smrg 655706f2543Smrg npt--; 656706f2543Smrg pptInit++; 657706f2543Smrg } 658706f2543Smrg 659706f2543Smrg#elif ROOTLESS_CHANGED_AREA==1 660706f2543Smrg // one big box 661706f2543Smrg BoxRec box; 662706f2543Smrg 663706f2543Smrg box.x2 = box.x1 = pptInit->x; 664706f2543Smrg box.y2 = box.y1 = pptInit->y; 665706f2543Smrg while (--npt) { 666706f2543Smrg pptInit++; 667706f2543Smrg if (box.x1 > pptInit->x) 668706f2543Smrg box.x1 = pptInit->x; 669706f2543Smrg else if (box.x2 < pptInit->x) 670706f2543Smrg box.x2 = pptInit->x; 671706f2543Smrg if (box.y1 > pptInit->y) 672706f2543Smrg box.y1 = pptInit->y; 673706f2543Smrg else if (box.y2 < pptInit->y) 674706f2543Smrg box.y2 = pptInit->y; 675706f2543Smrg } 676706f2543Smrg 677706f2543Smrg box.x2++; 678706f2543Smrg box.y2++; 679706f2543Smrg 680706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 681706f2543Smrg if (BOX_NOT_EMPTY(box)) 682706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 683706f2543Smrg 684706f2543Smrg#elif ROOTLESS_CHANGED_AREA==2 685706f2543Smrg // clever(?) method: accumulate point in 20-pixel radius 686706f2543Smrg BoxRec box; 687706f2543Smrg int firstx, firsty; 688706f2543Smrg 689706f2543Smrg box.x2 = box.x1 = firstx = pptInit->x; 690706f2543Smrg box.y2 = box.y1 = firsty = pptInit->y; 691706f2543Smrg while (--npt) { 692706f2543Smrg pptInit++; 693706f2543Smrg if (abs(pptInit->x - firstx) > 20 || 694706f2543Smrg abs(pptInit->y - firsty) > 20) { 695706f2543Smrg box.x2++; 696706f2543Smrg box.y2++; 697706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 698706f2543Smrg if (BOX_NOT_EMPTY(box)) 699706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 700706f2543Smrg box.x2 = box.x1 = firstx = pptInit->x; 701706f2543Smrg box.y2 = box.y1 = firsty = pptInit->y; 702706f2543Smrg } else { 703706f2543Smrg if (box.x1 > pptInit->x) box.x1 = pptInit->x; 704706f2543Smrg else if (box.x2 < pptInit->x) box.x2 = pptInit->x; 705706f2543Smrg if (box.y1 > pptInit->y) box.y1 = pptInit->y; 706706f2543Smrg else if (box.y2 < pptInit->y) box.y2 = pptInit->y; 707706f2543Smrg } 708706f2543Smrg } 709706f2543Smrg box.x2++; 710706f2543Smrg box.y2++; 711706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 712706f2543Smrg if (BOX_NOT_EMPTY(box)) 713706f2543Smrg RootlessDamageBox((WindowPtr) dst, &box); 714706f2543Smrg#endif /* ROOTLESS_CHANGED_AREA */ 715706f2543Smrg } 716706f2543Smrg 717706f2543Smrg GCOP_WRAP(pGC); 718706f2543Smrg RL_DEBUG_MSG("polypoint end\n"); 719706f2543Smrg} 720706f2543Smrg 721706f2543Smrg#undef ROOTLESS_CHANGED_AREA 722706f2543Smrg 723706f2543Smrg/* changed area is box around each line */ 724706f2543Smrgstatic void RootlessPolylines(DrawablePtr dst, GCPtr pGC, 725706f2543Smrg int mode, int npt, DDXPointPtr pptInit) 726706f2543Smrg{ 727706f2543Smrg GCOP_UNWRAP(pGC); 728706f2543Smrg RL_DEBUG_MSG("poly lines start "); 729706f2543Smrg 730706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 731706f2543Smrg pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); 732706f2543Smrg 733706f2543Smrg if (npt > 0) { 734706f2543Smrg BoxRec box; 735706f2543Smrg int extra = pGC->lineWidth >> 1; 736706f2543Smrg 737706f2543Smrg box.x2 = box.x1 = pptInit->x; 738706f2543Smrg box.y2 = box.y1 = pptInit->y; 739706f2543Smrg 740706f2543Smrg if (npt > 1) { 741706f2543Smrg if (pGC->joinStyle == JoinMiter) 742706f2543Smrg extra = 6 * pGC->lineWidth; 743706f2543Smrg else if (pGC->capStyle == CapProjecting) 744706f2543Smrg extra = pGC->lineWidth; 745706f2543Smrg } 746706f2543Smrg 747706f2543Smrg if (mode == CoordModePrevious) { 748706f2543Smrg int x = box.x1; 749706f2543Smrg int y = box.y1; 750706f2543Smrg 751706f2543Smrg while (--npt) { 752706f2543Smrg pptInit++; 753706f2543Smrg x += pptInit->x; 754706f2543Smrg y += pptInit->y; 755706f2543Smrg if (box.x1 > x) 756706f2543Smrg box.x1 = x; 757706f2543Smrg else if (box.x2 < x) 758706f2543Smrg box.x2 = x; 759706f2543Smrg if (box.y1 > y) 760706f2543Smrg box.y1 = y; 761706f2543Smrg else if (box.y2 < y) 762706f2543Smrg box.y2 = y; 763706f2543Smrg } 764706f2543Smrg } else { 765706f2543Smrg while (--npt) { 766706f2543Smrg pptInit++; 767706f2543Smrg if (box.x1 > pptInit->x) 768706f2543Smrg box.x1 = pptInit->x; 769706f2543Smrg else if (box.x2 < pptInit->x) 770706f2543Smrg box.x2 = pptInit->x; 771706f2543Smrg if (box.y1 > pptInit->y) 772706f2543Smrg box.y1 = pptInit->y; 773706f2543Smrg else if (box.y2 < pptInit->y) 774706f2543Smrg box.y2 = pptInit->y; 775706f2543Smrg } 776706f2543Smrg } 777706f2543Smrg 778706f2543Smrg box.x2++; 779706f2543Smrg box.y2++; 780706f2543Smrg 781706f2543Smrg if (extra) { 782706f2543Smrg box.x1 -= extra; 783706f2543Smrg box.x2 += extra; 784706f2543Smrg box.y1 -= extra; 785706f2543Smrg box.y2 += extra; 786706f2543Smrg } 787706f2543Smrg 788706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 789706f2543Smrg if (BOX_NOT_EMPTY(box)) 790706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 791706f2543Smrg } 792706f2543Smrg 793706f2543Smrg GCOP_WRAP(pGC); 794706f2543Smrg RL_DEBUG_MSG("poly lines end\n"); 795706f2543Smrg} 796706f2543Smrg 797706f2543Smrg/* changed area is box around each line segment */ 798706f2543Smrgstatic void RootlessPolySegment(DrawablePtr dst, GCPtr pGC, 799706f2543Smrg int nseg, xSegment *pSeg) 800706f2543Smrg{ 801706f2543Smrg GCOP_UNWRAP(pGC); 802706f2543Smrg RL_DEBUG_MSG("poly segment start (win 0x%x)", dst); 803706f2543Smrg 804706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 805706f2543Smrg pGC->ops->PolySegment(dst, pGC, nseg, pSeg); 806706f2543Smrg 807706f2543Smrg if (nseg > 0) { 808706f2543Smrg BoxRec box; 809706f2543Smrg int extra = pGC->lineWidth; 810706f2543Smrg 811706f2543Smrg if (pGC->capStyle != CapProjecting) 812706f2543Smrg extra >>= 1; 813706f2543Smrg 814706f2543Smrg if (pSeg->x2 > pSeg->x1) { 815706f2543Smrg box.x1 = pSeg->x1; 816706f2543Smrg box.x2 = pSeg->x2; 817706f2543Smrg } else { 818706f2543Smrg box.x2 = pSeg->x1; 819706f2543Smrg box.x1 = pSeg->x2; 820706f2543Smrg } 821706f2543Smrg 822706f2543Smrg if (pSeg->y2 > pSeg->y1) { 823706f2543Smrg box.y1 = pSeg->y1; 824706f2543Smrg box.y2 = pSeg->y2; 825706f2543Smrg } else { 826706f2543Smrg box.y2 = pSeg->y1; 827706f2543Smrg box.y1 = pSeg->y2; 828706f2543Smrg } 829706f2543Smrg 830706f2543Smrg while (--nseg) { 831706f2543Smrg pSeg++; 832706f2543Smrg if (pSeg->x2 > pSeg->x1) { 833706f2543Smrg if (pSeg->x1 < box.x1) box.x1 = pSeg->x1; 834706f2543Smrg if (pSeg->x2 > box.x2) box.x2 = pSeg->x2; 835706f2543Smrg } else { 836706f2543Smrg if (pSeg->x2 < box.x1) box.x1 = pSeg->x2; 837706f2543Smrg if (pSeg->x1 > box.x2) box.x2 = pSeg->x1; 838706f2543Smrg } 839706f2543Smrg if (pSeg->y2 > pSeg->y1) { 840706f2543Smrg if (pSeg->y1 < box.y1) box.y1 = pSeg->y1; 841706f2543Smrg if (pSeg->y2 > box.y2) box.y2 = pSeg->y2; 842706f2543Smrg } else { 843706f2543Smrg if (pSeg->y2 < box.y1) box.y1 = pSeg->y2; 844706f2543Smrg if (pSeg->y1 > box.y2) box.y2 = pSeg->y1; 845706f2543Smrg } 846706f2543Smrg } 847706f2543Smrg 848706f2543Smrg box.x2++; 849706f2543Smrg box.y2++; 850706f2543Smrg 851706f2543Smrg if (extra) { 852706f2543Smrg box.x1 -= extra; 853706f2543Smrg box.x2 += extra; 854706f2543Smrg box.y1 -= extra; 855706f2543Smrg box.y2 += extra; 856706f2543Smrg } 857706f2543Smrg 858706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 859706f2543Smrg if (BOX_NOT_EMPTY(box)) 860706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 861706f2543Smrg } 862706f2543Smrg 863706f2543Smrg GCOP_WRAP(pGC); 864706f2543Smrg RL_DEBUG_MSG("poly segment end\n"); 865706f2543Smrg} 866706f2543Smrg 867706f2543Smrg/* changed area is box around each line (not entire rects) */ 868706f2543Smrgstatic void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC, 869706f2543Smrg int nRects, xRectangle *pRects) 870706f2543Smrg{ 871706f2543Smrg GCOP_UNWRAP(pGC); 872706f2543Smrg RL_DEBUG_MSG("poly rectangle start "); 873706f2543Smrg 874706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 875706f2543Smrg pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); 876706f2543Smrg 877706f2543Smrg if (nRects > 0) { 878706f2543Smrg BoxRec box; 879706f2543Smrg int offset1, offset2, offset3; 880706f2543Smrg 881706f2543Smrg offset2 = pGC->lineWidth; 882706f2543Smrg if (!offset2) offset2 = 1; 883706f2543Smrg offset1 = offset2 >> 1; 884706f2543Smrg offset3 = offset2 - offset1; 885706f2543Smrg 886706f2543Smrg while (nRects--) { 887706f2543Smrg box.x1 = pRects->x - offset1; 888706f2543Smrg box.y1 = pRects->y - offset1; 889706f2543Smrg box.x2 = box.x1 + pRects->width + offset2; 890706f2543Smrg box.y2 = box.y1 + offset2; 891706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 892706f2543Smrg if (BOX_NOT_EMPTY(box)) 893706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 894706f2543Smrg 895706f2543Smrg box.x1 = pRects->x - offset1; 896706f2543Smrg box.y1 = pRects->y + offset3; 897706f2543Smrg box.x2 = box.x1 + offset2; 898706f2543Smrg box.y2 = box.y1 + pRects->height - offset2; 899706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 900706f2543Smrg if (BOX_NOT_EMPTY(box)) 901706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 902706f2543Smrg 903706f2543Smrg box.x1 = pRects->x + pRects->width - offset1; 904706f2543Smrg box.y1 = pRects->y + offset3; 905706f2543Smrg box.x2 = box.x1 + offset2; 906706f2543Smrg box.y2 = box.y1 + pRects->height - offset2; 907706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 908706f2543Smrg if (BOX_NOT_EMPTY(box)) 909706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 910706f2543Smrg 911706f2543Smrg box.x1 = pRects->x - offset1; 912706f2543Smrg box.y1 = pRects->y + pRects->height - offset1; 913706f2543Smrg box.x2 = box.x1 + pRects->width + offset2; 914706f2543Smrg box.y2 = box.y1 + offset2; 915706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 916706f2543Smrg if (BOX_NOT_EMPTY(box)) 917706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 918706f2543Smrg 919706f2543Smrg pRects++; 920706f2543Smrg } 921706f2543Smrg } 922706f2543Smrg 923706f2543Smrg GCOP_WRAP(pGC); 924706f2543Smrg RL_DEBUG_MSG("poly rectangle end\n"); 925706f2543Smrg} 926706f2543Smrg 927706f2543Smrg 928706f2543Smrg/* changed area is box around each arc (assumes all arcs are 360 degrees) */ 929706f2543Smrgstatic void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs) 930706f2543Smrg{ 931706f2543Smrg GCOP_UNWRAP(pGC); 932706f2543Smrg RL_DEBUG_MSG("poly arc start "); 933706f2543Smrg 934706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 935706f2543Smrg pGC->ops->PolyArc(dst, pGC, narcs, parcs); 936706f2543Smrg 937706f2543Smrg if (narcs > 0) { 938706f2543Smrg int extra = pGC->lineWidth >> 1; 939706f2543Smrg BoxRec box; 940706f2543Smrg 941706f2543Smrg box.x1 = parcs->x; 942706f2543Smrg box.x2 = box.x1 + parcs->width; 943706f2543Smrg box.y1 = parcs->y; 944706f2543Smrg box.y2 = box.y1 + parcs->height; 945706f2543Smrg 946706f2543Smrg /* should I break these up instead ? */ 947706f2543Smrg 948706f2543Smrg while (--narcs) { 949706f2543Smrg parcs++; 950706f2543Smrg if (box.x1 > parcs->x) 951706f2543Smrg box.x1 = parcs->x; 952706f2543Smrg if (box.x2 < (parcs->x + parcs->width)) 953706f2543Smrg box.x2 = parcs->x + parcs->width; 954706f2543Smrg if (box.y1 > parcs->y) 955706f2543Smrg box.y1 = parcs->y; 956706f2543Smrg if (box.y2 < (parcs->y + parcs->height)) 957706f2543Smrg box.y2 = parcs->y + parcs->height; 958706f2543Smrg } 959706f2543Smrg 960706f2543Smrg if (extra) { 961706f2543Smrg box.x1 -= extra; 962706f2543Smrg box.x2 += extra; 963706f2543Smrg box.y1 -= extra; 964706f2543Smrg box.y2 += extra; 965706f2543Smrg } 966706f2543Smrg 967706f2543Smrg box.x2++; 968706f2543Smrg box.y2++; 969706f2543Smrg 970706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 971706f2543Smrg if (BOX_NOT_EMPTY(box)) 972706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 973706f2543Smrg } 974706f2543Smrg 975706f2543Smrg GCOP_WRAP(pGC); 976706f2543Smrg RL_DEBUG_MSG("poly arc end\n"); 977706f2543Smrg} 978706f2543Smrg 979706f2543Smrg 980706f2543Smrg/* changed area is box around each poly */ 981706f2543Smrgstatic void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC, 982706f2543Smrg int shape, int mode, int count, 983706f2543Smrg DDXPointPtr pptInit) 984706f2543Smrg{ 985706f2543Smrg GC_SAVE(pGC); 986706f2543Smrg GCOP_UNWRAP(pGC); 987706f2543Smrg RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)", dst, 988706f2543Smrg pGC->fillStyle); 989706f2543Smrg 990706f2543Smrg if (count <= 2) { 991706f2543Smrg pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); 992706f2543Smrg } else { 993706f2543Smrg DDXPointPtr ppt = pptInit; 994706f2543Smrg int i = count; 995706f2543Smrg BoxRec box; 996706f2543Smrg 997706f2543Smrg box.x2 = box.x1 = ppt->x; 998706f2543Smrg box.y2 = box.y1 = ppt->y; 999706f2543Smrg 1000706f2543Smrg if (mode != CoordModeOrigin) { 1001706f2543Smrg int x = box.x1; 1002706f2543Smrg int y = box.y1; 1003706f2543Smrg 1004706f2543Smrg while (--i) { 1005706f2543Smrg ppt++; 1006706f2543Smrg x += ppt->x; 1007706f2543Smrg y += ppt->y; 1008706f2543Smrg if (box.x1 > x) 1009706f2543Smrg box.x1 = x; 1010706f2543Smrg else if (box.x2 < x) 1011706f2543Smrg box.x2 = x; 1012706f2543Smrg if (box.y1 > y) 1013706f2543Smrg box.y1 = y; 1014706f2543Smrg else if (box.y2 < y) 1015706f2543Smrg box.y2 = y; 1016706f2543Smrg } 1017706f2543Smrg } else { 1018706f2543Smrg while (--i) { 1019706f2543Smrg ppt++; 1020706f2543Smrg if (box.x1 > ppt->x) 1021706f2543Smrg box.x1 = ppt->x; 1022706f2543Smrg else if (box.x2 < ppt->x) 1023706f2543Smrg box.x2 = ppt->x; 1024706f2543Smrg if (box.y1 > ppt->y) 1025706f2543Smrg box.y1 = ppt->y; 1026706f2543Smrg else if (box.y2 < ppt->y) 1027706f2543Smrg box.y2 = ppt->y; 1028706f2543Smrg } 1029706f2543Smrg } 1030706f2543Smrg 1031706f2543Smrg box.x2++; 1032706f2543Smrg box.y2++; 1033706f2543Smrg 1034706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1035706f2543Smrg 1036706f2543Smrg if (canAccelFill(dst, pGC)) 1037706f2543Smrg { 1038706f2543Smrg GC_UNSET_PM(pGC, dst); 1039706f2543Smrg } 1040706f2543Smrg 1041706f2543Smrg pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); 1042706f2543Smrg 1043706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 1044706f2543Smrg if (BOX_NOT_EMPTY(box)) 1045706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1046706f2543Smrg } 1047706f2543Smrg 1048706f2543Smrg GC_RESTORE(pGC, dst); 1049706f2543Smrg GCOP_WRAP(pGC); 1050706f2543Smrg RL_DEBUG_MSG("fill poly end\n"); 1051706f2543Smrg} 1052706f2543Smrg 1053706f2543Smrg/* changed area is the rects */ 1054706f2543Smrgstatic void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC, 1055706f2543Smrg int nRectsInit, xRectangle *pRectsInit) 1056706f2543Smrg{ 1057706f2543Smrg GC_SAVE(pGC); 1058706f2543Smrg GCOP_UNWRAP(pGC); 1059706f2543Smrg RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)", dst, 1060706f2543Smrg pGC->fillStyle); 1061706f2543Smrg 1062706f2543Smrg if (nRectsInit <= 0) { 1063706f2543Smrg pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); 1064706f2543Smrg } else { 1065706f2543Smrg BoxRec box; 1066706f2543Smrg xRectangle *pRects = pRectsInit; 1067706f2543Smrg int nRects = nRectsInit; 1068706f2543Smrg 1069706f2543Smrg box.x1 = pRects->x; 1070706f2543Smrg box.x2 = box.x1 + pRects->width; 1071706f2543Smrg box.y1 = pRects->y; 1072706f2543Smrg box.y2 = box.y1 + pRects->height; 1073706f2543Smrg 1074706f2543Smrg while (--nRects) { 1075706f2543Smrg pRects++; 1076706f2543Smrg if (box.x1 > pRects->x) 1077706f2543Smrg box.x1 = pRects->x; 1078706f2543Smrg if (box.x2 < (pRects->x + pRects->width)) 1079706f2543Smrg box.x2 = pRects->x + pRects->width; 1080706f2543Smrg if (box.y1 > pRects->y) 1081706f2543Smrg box.y1 = pRects->y; 1082706f2543Smrg if (box.y2 < (pRects->y + pRects->height)) 1083706f2543Smrg box.y2 = pRects->y + pRects->height; 1084706f2543Smrg } 1085706f2543Smrg 1086706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1087706f2543Smrg 1088706f2543Smrg if (canAccelFill(dst, pGC)) 1089706f2543Smrg { 1090706f2543Smrg GC_UNSET_PM(pGC, dst); 1091706f2543Smrg } 1092706f2543Smrg 1093706f2543Smrg pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); 1094706f2543Smrg 1095706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 1096706f2543Smrg if (BOX_NOT_EMPTY(box)) 1097706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1098706f2543Smrg } 1099706f2543Smrg 1100706f2543Smrg GC_RESTORE(pGC, dst); 1101706f2543Smrg GCOP_WRAP(pGC); 1102706f2543Smrg RL_DEBUG_MSG("fill rect end\n"); 1103706f2543Smrg} 1104706f2543Smrg 1105706f2543Smrg 1106706f2543Smrg/* changed area is box around each arc (assuming arcs are all 360 degrees) */ 1107706f2543Smrgstatic void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, 1108706f2543Smrg int narcsInit, xArc *parcsInit) 1109706f2543Smrg{ 1110706f2543Smrg GC_SAVE(pGC); 1111706f2543Smrg GCOP_UNWRAP(pGC); 1112706f2543Smrg RL_DEBUG_MSG("fill arc start "); 1113706f2543Smrg 1114706f2543Smrg if (narcsInit > 0) { 1115706f2543Smrg BoxRec box; 1116706f2543Smrg int narcs = narcsInit; 1117706f2543Smrg xArc *parcs = parcsInit; 1118706f2543Smrg 1119706f2543Smrg box.x1 = parcs->x; 1120706f2543Smrg box.x2 = box.x1 + parcs->width; 1121706f2543Smrg box.y1 = parcs->y; 1122706f2543Smrg box.y2 = box.y1 + parcs->height; 1123706f2543Smrg 1124706f2543Smrg /* should I break these up instead ? */ 1125706f2543Smrg 1126706f2543Smrg while (--narcs) { 1127706f2543Smrg parcs++; 1128706f2543Smrg if (box.x1 > parcs->x) 1129706f2543Smrg box.x1 = parcs->x; 1130706f2543Smrg if (box.x2 < (parcs->x + parcs->width)) 1131706f2543Smrg box.x2 = parcs->x + parcs->width; 1132706f2543Smrg if (box.y1 > parcs->y) 1133706f2543Smrg box.y1 = parcs->y; 1134706f2543Smrg if (box.y2 < (parcs->y + parcs->height)) 1135706f2543Smrg box.y2 = parcs->y + parcs->height; 1136706f2543Smrg } 1137706f2543Smrg 1138706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1139706f2543Smrg 1140706f2543Smrg if (canAccelFill(dst, pGC)) 1141706f2543Smrg { 1142706f2543Smrg GC_UNSET_PM(pGC, dst); 1143706f2543Smrg } 1144706f2543Smrg 1145706f2543Smrg pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); 1146706f2543Smrg 1147706f2543Smrg TRIM_AND_TRANSLATE_BOX(box, dst, pGC); 1148706f2543Smrg if (BOX_NOT_EMPTY(box)) 1149706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1150706f2543Smrg } else { 1151706f2543Smrg pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); 1152706f2543Smrg } 1153706f2543Smrg 1154706f2543Smrg GC_RESTORE(pGC, dst); 1155706f2543Smrg GCOP_WRAP(pGC); 1156706f2543Smrg RL_DEBUG_MSG("fill arc end\n"); 1157706f2543Smrg} 1158706f2543Smrg 1159706f2543Smrg 1160706f2543Smrgstatic void RootlessImageText8(DrawablePtr dst, GCPtr pGC, 1161706f2543Smrg int x, int y, int count, char *chars) 1162706f2543Smrg{ 1163706f2543Smrg GC_SAVE(pGC); 1164706f2543Smrg GCOP_UNWRAP(pGC); 1165706f2543Smrg RL_DEBUG_MSG("imagetext8 start "); 1166706f2543Smrg 1167706f2543Smrg if (count > 0) { 1168706f2543Smrg int top, bot, Min, Max; 1169706f2543Smrg BoxRec box; 1170706f2543Smrg 1171706f2543Smrg top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); 1172706f2543Smrg bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); 1173706f2543Smrg 1174706f2543Smrg Min = count * FONTMINBOUNDS(pGC->font, characterWidth); 1175706f2543Smrg if (Min > 0) Min = 0; 1176706f2543Smrg Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); 1177706f2543Smrg if (Max < 0) Max = 0; 1178706f2543Smrg 1179706f2543Smrg /* ugh */ 1180706f2543Smrg box.x1 = dst->x + x + Min + 1181706f2543Smrg FONTMINBOUNDS(pGC->font, leftSideBearing); 1182706f2543Smrg box.x2 = dst->x + x + Max + 1183706f2543Smrg FONTMAXBOUNDS(pGC->font, rightSideBearing); 1184706f2543Smrg 1185706f2543Smrg box.y1 = dst->y + y - top; 1186706f2543Smrg box.y2 = dst->y + y + bot; 1187706f2543Smrg 1188706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1189706f2543Smrg 1190706f2543Smrg if (canAccelFill(dst, pGC)) 1191706f2543Smrg { 1192706f2543Smrg GC_UNSET_PM(pGC, dst); 1193706f2543Smrg } 1194706f2543Smrg 1195706f2543Smrg pGC->ops->ImageText8(dst, pGC, x, y, count, chars); 1196706f2543Smrg 1197706f2543Smrg TRIM_BOX(box, pGC); 1198706f2543Smrg if (BOX_NOT_EMPTY(box)) 1199706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1200706f2543Smrg } else { 1201706f2543Smrg pGC->ops->ImageText8(dst, pGC, x, y, count, chars); 1202706f2543Smrg } 1203706f2543Smrg 1204706f2543Smrg GC_RESTORE(pGC, dst); 1205706f2543Smrg GCOP_WRAP(pGC); 1206706f2543Smrg RL_DEBUG_MSG("imagetext8 end\n"); 1207706f2543Smrg} 1208706f2543Smrg 1209706f2543Smrgstatic int RootlessPolyText8(DrawablePtr dst, GCPtr pGC, 1210706f2543Smrg int x, int y, int count, char *chars) 1211706f2543Smrg{ 1212706f2543Smrg int width; // the result, sorta 1213706f2543Smrg 1214706f2543Smrg GCOP_UNWRAP(pGC); 1215706f2543Smrg 1216706f2543Smrg RL_DEBUG_MSG("polytext8 start "); 1217706f2543Smrg 1218706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1219706f2543Smrg width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); 1220706f2543Smrg width -= x; 1221706f2543Smrg 1222706f2543Smrg if (width > 0) { 1223706f2543Smrg BoxRec box; 1224706f2543Smrg 1225706f2543Smrg /* ugh */ 1226706f2543Smrg box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); 1227706f2543Smrg box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); 1228706f2543Smrg 1229706f2543Smrg if (count > 1) { 1230706f2543Smrg if (width > 0) box.x2 += width; 1231706f2543Smrg else box.x1 += width; 1232706f2543Smrg } 1233706f2543Smrg 1234706f2543Smrg box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); 1235706f2543Smrg box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); 1236706f2543Smrg 1237706f2543Smrg TRIM_BOX(box, pGC); 1238706f2543Smrg if (BOX_NOT_EMPTY(box)) 1239706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1240706f2543Smrg } 1241706f2543Smrg 1242706f2543Smrg GCOP_WRAP(pGC); 1243706f2543Smrg RL_DEBUG_MSG("polytext8 end\n"); 1244706f2543Smrg return width + x; 1245706f2543Smrg} 1246706f2543Smrg 1247706f2543Smrgstatic void RootlessImageText16(DrawablePtr dst, GCPtr pGC, 1248706f2543Smrg int x, int y, int count, unsigned short *chars) 1249706f2543Smrg{ 1250706f2543Smrg GC_SAVE(pGC); 1251706f2543Smrg GCOP_UNWRAP(pGC); 1252706f2543Smrg RL_DEBUG_MSG("imagetext16 start "); 1253706f2543Smrg 1254706f2543Smrg if (count > 0) { 1255706f2543Smrg int top, bot, Min, Max; 1256706f2543Smrg BoxRec box; 1257706f2543Smrg 1258706f2543Smrg top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); 1259706f2543Smrg bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); 1260706f2543Smrg 1261706f2543Smrg Min = count * FONTMINBOUNDS(pGC->font, characterWidth); 1262706f2543Smrg if (Min > 0) Min = 0; 1263706f2543Smrg Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); 1264706f2543Smrg if (Max < 0) Max = 0; 1265706f2543Smrg 1266706f2543Smrg /* ugh */ 1267706f2543Smrg box.x1 = dst->x + x + Min + 1268706f2543Smrg FONTMINBOUNDS(pGC->font, leftSideBearing); 1269706f2543Smrg box.x2 = dst->x + x + Max + 1270706f2543Smrg FONTMAXBOUNDS(pGC->font, rightSideBearing); 1271706f2543Smrg 1272706f2543Smrg box.y1 = dst->y + y - top; 1273706f2543Smrg box.y2 = dst->y + y + bot; 1274706f2543Smrg 1275706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1276706f2543Smrg 1277706f2543Smrg if (canAccelFill(dst, pGC)) 1278706f2543Smrg { 1279706f2543Smrg GC_UNSET_PM(pGC, dst); 1280706f2543Smrg } 1281706f2543Smrg 1282706f2543Smrg pGC->ops->ImageText16(dst, pGC, x, y, count, chars); 1283706f2543Smrg 1284706f2543Smrg TRIM_BOX(box, pGC); 1285706f2543Smrg if (BOX_NOT_EMPTY(box)) 1286706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1287706f2543Smrg } else { 1288706f2543Smrg pGC->ops->ImageText16(dst, pGC, x, y, count, chars); 1289706f2543Smrg } 1290706f2543Smrg 1291706f2543Smrg GC_RESTORE(pGC, dst); 1292706f2543Smrg GCOP_WRAP(pGC); 1293706f2543Smrg RL_DEBUG_MSG("imagetext16 end\n"); 1294706f2543Smrg} 1295706f2543Smrg 1296706f2543Smrgstatic int RootlessPolyText16(DrawablePtr dst, GCPtr pGC, 1297706f2543Smrg int x, int y, int count, unsigned short *chars) 1298706f2543Smrg{ 1299706f2543Smrg int width; // the result, sorta 1300706f2543Smrg 1301706f2543Smrg GCOP_UNWRAP(pGC); 1302706f2543Smrg 1303706f2543Smrg RL_DEBUG_MSG("polytext16 start "); 1304706f2543Smrg 1305706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1306706f2543Smrg width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); 1307706f2543Smrg width -= x; 1308706f2543Smrg 1309706f2543Smrg if (width > 0) { 1310706f2543Smrg BoxRec box; 1311706f2543Smrg 1312706f2543Smrg /* ugh */ 1313706f2543Smrg box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); 1314706f2543Smrg box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); 1315706f2543Smrg 1316706f2543Smrg if (count > 1) { 1317706f2543Smrg if (width > 0) box.x2 += width; 1318706f2543Smrg else box.x1 += width; 1319706f2543Smrg } 1320706f2543Smrg 1321706f2543Smrg box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); 1322706f2543Smrg box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); 1323706f2543Smrg 1324706f2543Smrg TRIM_BOX(box, pGC); 1325706f2543Smrg if (BOX_NOT_EMPTY(box)) 1326706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1327706f2543Smrg } 1328706f2543Smrg 1329706f2543Smrg GCOP_WRAP(pGC); 1330706f2543Smrg RL_DEBUG_MSG("polytext16 end\n"); 1331706f2543Smrg return width + x; 1332706f2543Smrg} 1333706f2543Smrg 1334706f2543Smrgstatic void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC, 1335706f2543Smrg int x, int y, unsigned int nglyphInit, 1336706f2543Smrg CharInfoPtr *ppciInit, pointer unused) 1337706f2543Smrg{ 1338706f2543Smrg GC_SAVE(pGC); 1339706f2543Smrg GCOP_UNWRAP(pGC); 1340706f2543Smrg RL_DEBUG_MSG("imageglyph start "); 1341706f2543Smrg 1342706f2543Smrg if (nglyphInit > 0) { 1343706f2543Smrg int top, bot, width = 0; 1344706f2543Smrg BoxRec box; 1345706f2543Smrg unsigned int nglyph = nglyphInit; 1346706f2543Smrg CharInfoPtr *ppci = ppciInit; 1347706f2543Smrg 1348706f2543Smrg top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); 1349706f2543Smrg bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); 1350706f2543Smrg 1351706f2543Smrg box.x1 = ppci[0]->metrics.leftSideBearing; 1352706f2543Smrg if (box.x1 > 0) box.x1 = 0; 1353706f2543Smrg box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - 1354706f2543Smrg ppci[nglyph - 1]->metrics.characterWidth; 1355706f2543Smrg if (box.x2 < 0) box.x2 = 0; 1356706f2543Smrg 1357706f2543Smrg box.x2 += dst->x + x; 1358706f2543Smrg box.x1 += dst->x + x; 1359706f2543Smrg 1360706f2543Smrg while (nglyph--) { 1361706f2543Smrg width += (*ppci)->metrics.characterWidth; 1362706f2543Smrg ppci++; 1363706f2543Smrg } 1364706f2543Smrg 1365706f2543Smrg if (width > 0) 1366706f2543Smrg box.x2 += width; 1367706f2543Smrg else 1368706f2543Smrg box.x1 += width; 1369706f2543Smrg 1370706f2543Smrg box.y1 = dst->y + y - top; 1371706f2543Smrg box.y2 = dst->y + y + bot; 1372706f2543Smrg 1373706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1374706f2543Smrg 1375706f2543Smrg if (canAccelFill(dst, pGC)) 1376706f2543Smrg { 1377706f2543Smrg GC_UNSET_PM(pGC, dst); 1378706f2543Smrg } 1379706f2543Smrg 1380706f2543Smrg pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); 1381706f2543Smrg 1382706f2543Smrg TRIM_BOX(box, pGC); 1383706f2543Smrg if (BOX_NOT_EMPTY(box)) 1384706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1385706f2543Smrg } else { 1386706f2543Smrg pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); 1387706f2543Smrg } 1388706f2543Smrg 1389706f2543Smrg GC_RESTORE(pGC, dst); 1390706f2543Smrg GCOP_WRAP(pGC); 1391706f2543Smrg RL_DEBUG_MSG("imageglyph end\n"); 1392706f2543Smrg} 1393706f2543Smrg 1394706f2543Smrgstatic void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, 1395706f2543Smrg int x, int y, unsigned int nglyph, 1396706f2543Smrg CharInfoPtr *ppci, pointer pglyphBase) 1397706f2543Smrg{ 1398706f2543Smrg GCOP_UNWRAP(pGC); 1399706f2543Smrg RL_DEBUG_MSG("polyglyph start "); 1400706f2543Smrg 1401706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1402706f2543Smrg pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); 1403706f2543Smrg 1404706f2543Smrg if (nglyph > 0) { 1405706f2543Smrg BoxRec box; 1406706f2543Smrg 1407706f2543Smrg /* ugh */ 1408706f2543Smrg box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing; 1409706f2543Smrg box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing; 1410706f2543Smrg 1411706f2543Smrg if (nglyph > 1) { 1412706f2543Smrg int width = 0; 1413706f2543Smrg 1414706f2543Smrg while (--nglyph) { 1415706f2543Smrg width += (*ppci)->metrics.characterWidth; 1416706f2543Smrg ppci++; 1417706f2543Smrg } 1418706f2543Smrg 1419706f2543Smrg if (width > 0) box.x2 += width; 1420706f2543Smrg else box.x1 += width; 1421706f2543Smrg } 1422706f2543Smrg 1423706f2543Smrg box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); 1424706f2543Smrg box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); 1425706f2543Smrg 1426706f2543Smrg TRIM_BOX(box, pGC); 1427706f2543Smrg if (BOX_NOT_EMPTY(box)) 1428706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1429706f2543Smrg } 1430706f2543Smrg 1431706f2543Smrg GCOP_WRAP(pGC); 1432706f2543Smrg RL_DEBUG_MSG("polyglyph end\n"); 1433706f2543Smrg} 1434706f2543Smrg 1435706f2543Smrg 1436706f2543Smrg/* changed area is in dest */ 1437706f2543Smrgstatic void 1438706f2543SmrgRootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, 1439706f2543Smrg int dx, int dy, int xOrg, int yOrg) 1440706f2543Smrg{ 1441706f2543Smrg BoxRec box; 1442706f2543Smrg 1443706f2543Smrg GCOP_UNWRAP(pGC); 1444706f2543Smrg RL_DEBUG_MSG("push pixels start "); 1445706f2543Smrg 1446706f2543Smrg RootlessStartDrawing((WindowPtr) dst); 1447706f2543Smrg pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); 1448706f2543Smrg 1449706f2543Smrg box.x1 = xOrg + dst->x; 1450706f2543Smrg box.x2 = box.x1 + dx; 1451706f2543Smrg box.y1 = yOrg + dst->y; 1452706f2543Smrg box.y2 = box.y1 + dy; 1453706f2543Smrg 1454706f2543Smrg TRIM_BOX(box, pGC); 1455706f2543Smrg if (BOX_NOT_EMPTY(box)) 1456706f2543Smrg RootlessDamageBox ((WindowPtr) dst, &box); 1457706f2543Smrg 1458706f2543Smrg GCOP_WRAP(pGC); 1459706f2543Smrg RL_DEBUG_MSG("push pixels end\n"); 1460706f2543Smrg} 1461