|
|
1.1 ! root 1: /*********************************************************** ! 2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, ! 3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts. ! 4: ! 5: All Rights Reserved ! 6: ! 7: Permission to use, copy, modify, and distribute this software and its ! 8: documentation for any purpose and without fee is hereby granted, ! 9: provided that the above copyright notice appear in all copies and that ! 10: both that copyright notice and this permission notice appear in ! 11: supporting documentation, and that the names of Digital or MIT not be ! 12: used in advertising or publicity pertaining to distribution of the ! 13: software without specific, written prior permission. ! 14: ! 15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 21: SOFTWARE. ! 22: ! 23: ******************************************************************/ ! 24: /* $Header: mfbgc.c,v 1.115 87/09/03 09:04:25 toddb Exp $ */ ! 25: #include "X.h" ! 26: #include "Xmd.h" ! 27: #include "Xproto.h" ! 28: #include "dixfontstr.h" ! 29: #include "fontstruct.h" ! 30: #include "gcstruct.h" ! 31: #include "windowstr.h" ! 32: #include "pixmapstr.h" ! 33: #include "scrnintstr.h" ! 34: #include "region.h" ! 35: ! 36: #include "mfb.h" ! 37: #include "mistruct.h" ! 38: ! 39: #include "maskbits.h" ! 40: ! 41: static PixmapPtr BogusPixmap = (PixmapPtr)1; ! 42: ! 43: Bool ! 44: mfbCreateGC(pGC) ! 45: register GCPtr pGC; ! 46: { ! 47: mfbPrivGC *pPriv; ! 48: GCInterestPtr pQ; ! 49: ! 50: pGC->clientClip = NULL; ! 51: pGC->clientClipType = CT_NONE; ! 52: ! 53: /* some of the output primitives aren't really necessary, since ! 54: they will be filled in ValidateGC because of dix/CreateGC() ! 55: setting all the change bits. Others are necessary because although ! 56: they depend on being a monochrome frame buffer, they don't change ! 57: */ ! 58: ! 59: pGC->FillSpans = mfbWhiteSolidFS; ! 60: pGC->SetSpans = mfbSetSpans; ! 61: pGC->PutImage = mfbPutImage; ! 62: pGC->CopyArea = mfbCopyArea; ! 63: pGC->CopyPlane = mfbCopyPlane; ! 64: pGC->PolyPoint = mfbPolyPoint; ! 65: ! 66: pGC->Polylines = mfbLineSS; ! 67: pGC->PolySegment = miPolySegment; ! 68: pGC->PolyRectangle = miPolyRectangle; ! 69: pGC->PolyArc = miPolyArc; ! 70: pGC->FillPolygon = miFillPolygon; ! 71: pGC->PolyFillRect = mfbPolyFillRect; ! 72: pGC->PolyFillArc = miPolyFillArc; ! 73: pGC->PolyText8 = miPolyText8; ! 74: pGC->ImageText8 = miImageText8; ! 75: pGC->PolyText16 = miPolyText16; ! 76: pGC->ImageText16 = miImageText16; ! 77: pGC->ImageGlyphBlt = mfbImageGlyphBltWhite; ! 78: pGC->PolyGlyphBlt = mfbPolyGlyphBltInvert; ! 79: pGC->PushPixels = mfbPushPixels; ! 80: pGC->LineHelper = miMiter; ! 81: pGC->ChangeClip = mfbChangeClip; ! 82: pGC->DestroyClip = mfbDestroyClip; ! 83: pGC->CopyClip = mfbCopyClip; ! 84: ! 85: /* mfb wants to translate before scan convesion */ ! 86: pGC->miTranslate = 1; ! 87: ! 88: pPriv = (mfbPrivGC *)Xalloc(sizeof(mfbPrivGC)); ! 89: if (!pPriv) ! 90: return FALSE; ! 91: else ! 92: { ! 93: pPriv->rop = ReduceRop(pGC->alu, pGC->fgPixel); ! 94: pPriv->fExpose = TRUE; ! 95: pGC->devPriv = (pointer)pPriv; ! 96: pPriv->pRotatedTile = NullPixmap; ! 97: pPriv->pRotatedStipple = NullPixmap; ! 98: pPriv->pAbsClientRegion =(* pGC->pScreen->RegionCreate)(NULL, 1); ! 99: ! 100: /* since freeCompClip isn't FREE_CC, we don't need to create ! 101: a null region -- no one will try to free the field. ! 102: */ ! 103: pPriv->freeCompClip = REPLACE_CC; ! 104: pPriv->ppPixmap = &BogusPixmap; ! 105: pPriv->FillArea = mfbSolidInvertArea; ! 106: } ! 107: pQ = (GCInterestPtr) Xalloc(sizeof(GCInterestRec)); ! 108: if(!pQ) ! 109: { ! 110: Xfree(pPriv); ! 111: return FALSE; ! 112: } ! 113: ! 114: /* Now link this device into the GCque */ ! 115: pGC->pNextGCInterest = pQ; ! 116: pGC->pLastGCInterest = pQ; ! 117: pQ->pNextGCInterest = (GCInterestPtr) &pGC->pNextGCInterest; ! 118: pQ->pLastGCInterest = (GCInterestPtr) &pGC->pNextGCInterest; ! 119: pQ->length = sizeof(GCInterestRec); ! 120: pQ->owner = 0; /* server owns this */ ! 121: pQ->ValInterestMask = ~0; /* interested in everything at validate time */ ! 122: pQ->ValidateGC = mfbValidateGC; ! 123: pQ->ChangeInterestMask = 0; /* interested in nothing at change time */ ! 124: pQ->ChangeGC = (int (*) () ) NULL; ! 125: pQ->CopyGCSource = (void (*) () ) NULL; ! 126: pQ->CopyGCDest = (void (*) () ) NULL; ! 127: pQ->DestroyGC = mfbDestroyGC; ! 128: return TRUE; ! 129: } ! 130: ! 131: void ! 132: mfbDestroyGC(pGC, pQ) ! 133: GC *pGC; ! 134: GCInterestPtr pQ; ! 135: ! 136: { ! 137: mfbPrivGC *pPriv; ! 138: ! 139: /* Most GCInterest pointers would free pQ->devPriv. This one is privileged ! 140: * and allowed to allocate its private data directly in the GC (this ! 141: * saves an indirection). We must also unlink and free the pQ. ! 142: */ ! 143: pQ->pLastGCInterest->pNextGCInterest = pQ->pNextGCInterest; ! 144: pQ->pNextGCInterest->pLastGCInterest = pQ->pLastGCInterest; ! 145: ! 146: pPriv = (mfbPrivGC *)(pGC->devPriv); ! 147: if (pPriv->pRotatedTile) ! 148: mfbDestroyPixmap(pPriv->pRotatedTile); ! 149: if (pPriv->pRotatedStipple) ! 150: mfbDestroyPixmap(pPriv->pRotatedStipple); ! 151: if (pPriv->freeCompClip == FREE_CC) ! 152: (*pGC->pScreen->RegionDestroy)(pPriv->pCompositeClip); ! 153: if(pPriv->pAbsClientRegion) ! 154: (*pGC->pScreen->RegionDestroy)(pPriv->pAbsClientRegion); ! 155: Xfree(pGC->devPriv); ! 156: Xfree(pQ); ! 157: } ! 158: ! 159: #define WINMOVED(pWin, pGC) \ ! 160: ((pWin->absCorner.x != pGC->lastWinOrg.x) || \ ! 161: (pWin->absCorner.y != pGC->lastWinOrg.y)) ! 162: ! 163: /* Clipping conventions ! 164: if the drawable is a window ! 165: CT_REGION ==> pCompositeClip really is the composite ! 166: CT_other ==> pCompositeClip is the window clip region ! 167: if the drawable is a pixmap ! 168: CT_REGION ==> pCompositeClip is the translated client region ! 169: clipped to the pixmap boundary ! 170: CT_other ==> pCompositeClip is the pixmap bounding box ! 171: */ ! 172: ! 173: void ! 174: mfbValidateGC(pGC, pQ, changes, pDrawable) ! 175: register GCPtr pGC; ! 176: GCInterestPtr pQ; ! 177: Mask changes; ! 178: DrawablePtr pDrawable; ! 179: { ! 180: register mfbPrivGCPtr devPriv; ! 181: WindowPtr pWin; ! 182: int mask; /* stateChanges */ ! 183: int index; /* used for stepping through bitfields */ ! 184: int xrot, yrot; /* rotations for tile and stipple pattern */ ! 185: int rrop; /* reduced rasterop */ ! 186: /* flags for changing the proc vector ! 187: and updating things in devPriv ! 188: */ ! 189: int new_rotate, new_rrop, new_line, new_text, new_fill; ! 190: DDXPointRec oldOrg; /* origin of thing GC was last used with */ ! 191: ! 192: if (pDrawable->type == DRAWABLE_WINDOW) ! 193: pWin = (WindowPtr)pDrawable; ! 194: else ! 195: pWin = (WindowPtr)NULL; ! 196: ! 197: devPriv = ((mfbPrivGCPtr) (pGC->devPriv)); ! 198: oldOrg = pGC->lastWinOrg; ! 199: /* ! 200: if the client clip is different or moved OR ! 201: the subwindowMode has changed OR ! 202: the window's clip has changed since the last validation ! 203: we need to recompute the composite clip ! 204: */ ! 205: ! 206: if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask)) || ! 207: (changes & GCSubwindowMode) || ! 208: (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) ! 209: ) ! 210: { ! 211: ! 212: /* if there is a client clip (always a region, for us) AND ! 213: it has moved or is different OR ! 214: the window has moved ! 215: we need to (re)translate it. ! 216: */ ! 217: if ((pGC->clientClipType == CT_REGION) && ! 218: ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask)) || ! 219: (pWin && WINMOVED(pWin, pGC)) ! 220: ) ! 221: ) ! 222: { ! 223: /* retranslate client clip */ ! 224: (* pGC->pScreen->RegionCopy)( devPriv->pAbsClientRegion, ! 225: pGC->clientClip); ! 226: ! 227: if (pWin) ! 228: { ! 229: pGC->lastWinOrg.x = pWin->absCorner.x; ! 230: pGC->lastWinOrg.y = pWin->absCorner.y; ! 231: (* pGC->pScreen->TranslateRegion)( ! 232: devPriv->pAbsClientRegion, ! 233: pGC->lastWinOrg.x + pGC->clipOrg.x, ! 234: pGC->lastWinOrg.y + pGC->clipOrg.y); ! 235: } ! 236: else ! 237: { ! 238: pGC->lastWinOrg.x = 0; ! 239: pGC->lastWinOrg.y = 0; ! 240: (* pGC->pScreen->TranslateRegion)( ! 241: devPriv->pAbsClientRegion, pGC->clipOrg.x, pGC->clipOrg.y); ! 242: } ! 243: } ! 244: ! 245: if (pWin) ! 246: { ! 247: int freeTmpClip, freeCompClip; ! 248: RegionPtr pregWin; /* clip for this window, without ! 249: client clip */ ! 250: ! 251: if (pGC->subWindowMode == IncludeInferiors) ! 252: { ! 253: pregWin = NotClippedByChildren(pWin); ! 254: freeTmpClip = FREE_CC; ! 255: } ! 256: else ! 257: { ! 258: pregWin = pWin->clipList; ! 259: freeTmpClip = REPLACE_CC; ! 260: } ! 261: freeCompClip = devPriv->freeCompClip; ! 262: ! 263: /* if there is no client clip, we can get by with ! 264: just keeping the pointer we got, and remembering ! 265: whether or not should destroy (or maybe re-use) ! 266: it later. this way, we avoid unnecessary copying ! 267: of regions. (this wins especially if many clients clip ! 268: by children and have no client clip.) ! 269: */ ! 270: if (pGC->clientClipType == CT_NONE) ! 271: { ! 272: if(freeCompClip == FREE_CC) ! 273: { ! 274: (* pGC->pScreen->RegionDestroy) (devPriv->pCompositeClip); ! 275: } ! 276: devPriv->pCompositeClip = pregWin; ! 277: devPriv->freeCompClip = freeTmpClip; ! 278: } ! 279: else ! 280: { ! 281: /* we need one 'real' region to put into the composite ! 282: clip. ! 283: if pregWin and the current composite clip ! 284: are real, we can get rid of one. ! 285: if the current composite clip is real and ! 286: pregWin isn't, intersect the client clip and ! 287: pregWin into the existing composite clip. ! 288: if pregWin is real and the current composite ! 289: clip isn't, intersect pregWin with the client clip ! 290: and replace the composite clip with it. ! 291: if neither is real, create a new region and ! 292: do the intersection into it. ! 293: */ ! 294: ! 295: if ((freeTmpClip == FREE_CC) && (freeCompClip == FREE_CC)) ! 296: { ! 297: (* pGC->pScreen->Intersect)( ! 298: devPriv->pCompositeClip, ! 299: pregWin, ! 300: devPriv->pAbsClientRegion); ! 301: (* pGC->pScreen->RegionDestroy)(pregWin); ! 302: } ! 303: else if ((freeTmpClip == REPLACE_CC) && ! 304: (freeCompClip == FREE_CC)) ! 305: { ! 306: (* pGC->pScreen->Intersect)( ! 307: devPriv->pCompositeClip, ! 308: pregWin, ! 309: devPriv->pAbsClientRegion); ! 310: } ! 311: else if ((freeTmpClip == FREE_CC) && ! 312: (freeCompClip == REPLACE_CC)) ! 313: { ! 314: (* pGC->pScreen->Intersect)( ! 315: pregWin, ! 316: pregWin, ! 317: devPriv->pAbsClientRegion); ! 318: devPriv->pCompositeClip = pregWin; ! 319: } ! 320: else if ((freeTmpClip == REPLACE_CC) && ! 321: (freeCompClip == REPLACE_CC)) ! 322: { ! 323: devPriv->pCompositeClip = ! 324: (* pGC->pScreen->RegionCreate)(NULL, 1); ! 325: (* pGC->pScreen->Intersect)( ! 326: devPriv->pCompositeClip, ! 327: pregWin, ! 328: devPriv->pAbsClientRegion); ! 329: } ! 330: devPriv->freeCompClip = FREE_CC; ! 331: } ! 332: } /* end of composite clip for a window */ ! 333: else ! 334: { ! 335: BoxRec pixbounds; ! 336: ! 337: pixbounds.x1 = 0; ! 338: pixbounds.y1 = 0; ! 339: pixbounds.x2 = ((PixmapPtr)pDrawable)->width; ! 340: pixbounds.y2 = ((PixmapPtr)pDrawable)->height; ! 341: ! 342: if (devPriv->freeCompClip == FREE_CC) ! 343: (* pGC->pScreen->RegionReset)( ! 344: devPriv->pCompositeClip, &pixbounds); ! 345: else ! 346: { ! 347: devPriv->freeCompClip = FREE_CC; ! 348: devPriv->pCompositeClip = ! 349: (* pGC->pScreen->RegionCreate)(&pixbounds, 1); ! 350: } ! 351: ! 352: if (pGC->clientClipType == CT_REGION) ! 353: (* pGC->pScreen->Intersect)( ! 354: devPriv->pCompositeClip, ! 355: devPriv->pCompositeClip, ! 356: devPriv->pAbsClientRegion); ! 357: } /* end of composite clip for pixmap */ ! 358: } ! 359: ! 360: /* we need to re-rotate the tile if the previous window/pixmap ! 361: origin (oldOrg) differs from the new window/pixmap origin ! 362: (pGC->lastWinOrg) ! 363: */ ! 364: if ((oldOrg.x != pGC->lastWinOrg.x) || ! 365: (oldOrg.y != pGC->lastWinOrg.y)) ! 366: { ! 367: new_rotate = TRUE; ! 368: } ! 369: else ! 370: { ! 371: new_rotate = FALSE; ! 372: } ! 373: ! 374: new_rrop = FALSE; ! 375: new_line = FALSE; ! 376: new_text = FALSE; ! 377: new_fill = FALSE; ! 378: ! 379: mask = changes; ! 380: while (mask) ! 381: { ! 382: index = ffs(mask) - 1; ! 383: mask &= ~(index = (1 << index)); ! 384: ! 385: /* this switch acculmulates a list of which procedures ! 386: might have to change due to changes in the GC. in ! 387: some cases (e.g. changing one 16 bit tile for another) ! 388: we might not really need a change, but the code is ! 389: being paranoid. ! 390: this sort of batching wins if, for example, the alu ! 391: and the font have been changed, or any other pair ! 392: of items that both change the same thing. ! 393: */ ! 394: switch (index) ! 395: { ! 396: case GCFunction: ! 397: case GCForeground: ! 398: new_rrop = TRUE; ! 399: break; ! 400: case GCPlaneMask: ! 401: break; ! 402: case GCBackground: ! 403: new_rrop = TRUE; /* for opaque stipples */ ! 404: break; ! 405: case GCLineStyle: ! 406: new_line = TRUE; ! 407: break; ! 408: case GCLineWidth: ! 409: case GCCapStyle: ! 410: case GCJoinStyle: ! 411: new_line = TRUE; ! 412: break; ! 413: case GCFillStyle: ! 414: new_fill = TRUE; ! 415: break; ! 416: case GCFillRule: ! 417: break; ! 418: case GCTile: ! 419: if(pGC->tile == (PixmapPtr)NULL) ! 420: break; ! 421: mfbPadPixmap(pGC->tile); ! 422: new_rotate = TRUE; ! 423: new_fill = TRUE; ! 424: break; ! 425: ! 426: case GCStipple: ! 427: if(pGC->stipple == (PixmapPtr)NULL) ! 428: break; ! 429: mfbPadPixmap(pGC->stipple); ! 430: new_rotate = TRUE; ! 431: new_fill = TRUE; ! 432: break; ! 433: ! 434: case GCTileStipXOrigin: ! 435: new_rotate = TRUE; ! 436: break; ! 437: ! 438: case GCTileStipYOrigin: ! 439: new_rotate = TRUE; ! 440: break; ! 441: ! 442: case GCFont: ! 443: new_text = TRUE; ! 444: break; ! 445: case GCSubwindowMode: ! 446: break; ! 447: case GCGraphicsExposures: ! 448: break; ! 449: case GCClipXOrigin: ! 450: break; ! 451: case GCClipYOrigin: ! 452: break; ! 453: case GCClipMask: ! 454: break; ! 455: case GCDashOffset: ! 456: break; ! 457: case GCDashList: ! 458: break; ! 459: case GCArcMode: ! 460: break; ! 461: default: ! 462: break; ! 463: } ! 464: } ! 465: ! 466: /* deal with the changes we've collected . ! 467: new_rrop must be done first because subsequent things ! 468: depend on it. ! 469: */ ! 470: if (new_rrop || new_fill) ! 471: { ! 472: rrop = ReduceRop(pGC->alu, pGC->fgPixel); ! 473: devPriv->rop = rrop; ! 474: new_fill = TRUE; ! 475: /* FillArea raster op is GC's for tile filling, ! 476: and the reduced rop for solid and stipple ! 477: */ ! 478: if (pGC->fillStyle == FillTiled) ! 479: devPriv->ropFillArea = pGC->alu; ! 480: else ! 481: devPriv->ropFillArea = rrop; ! 482: ! 483: /* opaque stipples: ! 484: fg bg ropOpStip fill style ! 485: 1 0 alu tile ! 486: 0 1 inverseAlu tile ! 487: 1 1 rrop(fg, alu) solid ! 488: 0 0 rrop(fg, alu) solid ! 489: Note that rrop(fg, alu) == mfbPrivGC.rop, so we don't really need to ! 490: compute it. ! 491: */ ! 492: if (pGC->fillStyle == FillOpaqueStippled) ! 493: { ! 494: if (pGC->fgPixel != pGC->bgPixel) ! 495: { ! 496: if (pGC->fgPixel) ! 497: devPriv->ropOpStip = pGC->alu; ! 498: else ! 499: devPriv->ropOpStip = InverseAlu[pGC->alu]; ! 500: } ! 501: else ! 502: devPriv->ropOpStip = rrop; ! 503: devPriv->ropFillArea = devPriv->ropOpStip; ! 504: } ! 505: } ! 506: else ! 507: rrop = devPriv->rop; ! 508: ! 509: if (new_line || new_fill) ! 510: { ! 511: if (pGC->lineStyle == LineSolid) ! 512: { ! 513: if(pGC->lineWidth == 0) ! 514: { ! 515: if (pGC->fillStyle == FillSolid) ! 516: pGC->Polylines = mfbLineSS; ! 517: else ! 518: pGC->Polylines = miZeroLine; ! 519: } ! 520: else ! 521: { ! 522: pGC->Polylines = miWideLine; ! 523: } ! 524: } ! 525: else ! 526: if(pGC->lineWidth == 0) ! 527: pGC->Polylines = mfbDashLine; ! 528: else ! 529: pGC->Polylines = miWideDash; ! 530: ! 531: switch(pGC->joinStyle) ! 532: { ! 533: case JoinMiter: ! 534: pGC->LineHelper = miMiter; ! 535: break; ! 536: case JoinRound: ! 537: case JoinBevel: ! 538: pGC->LineHelper = miNotMiter; ! 539: break; ! 540: } ! 541: } ! 542: ! 543: if (new_text || new_fill) ! 544: { ! 545: if ((pGC->font) && ! 546: (pGC->font->pFI->maxbounds.metrics.rightSideBearing - ! 547: pGC->font->pFI->maxbounds.metrics.leftSideBearing) > 32) ! 548: { ! 549: pGC->PolyGlyphBlt = miPolyGlyphBlt; ! 550: pGC->ImageGlyphBlt = miImageGlyphBlt; ! 551: } ! 552: else ! 553: { ! 554: /* special case ImageGlyphBlt for terminal emulator fonts */ ! 555: if ((pGC->font) && ! 556: (pGC->font->pFI->terminalFont) && ! 557: (pGC->fgPixel != pGC->bgPixel)) ! 558: { ! 559: /* pcc bug makes this not compile... ! 560: pGC->ImageGlyphBlt = (pGC->fgPixel) ? mfbTEGlyphBltWhite : ! 561: mfbTEGlyphBltBlack; ! 562: */ ! 563: if (pGC->fgPixel) ! 564: pGC->ImageGlyphBlt = mfbTEGlyphBltWhite; ! 565: else ! 566: pGC->ImageGlyphBlt = mfbTEGlyphBltBlack; ! 567: } ! 568: else ! 569: { ! 570: if (pGC->fgPixel == 0) ! 571: pGC->ImageGlyphBlt = mfbImageGlyphBltBlack; ! 572: else ! 573: pGC->ImageGlyphBlt = mfbImageGlyphBltWhite; ! 574: } ! 575: ! 576: /* now do PolyGlyphBlt */ ! 577: if (pGC->fillStyle == FillSolid || ! 578: (pGC->fillStyle == FillOpaqueStippled && ! 579: pGC->fgPixel == pGC->bgPixel ! 580: ) ! 581: ) ! 582: { ! 583: if (rrop == RROP_WHITE) ! 584: pGC->PolyGlyphBlt = mfbPolyGlyphBltWhite; ! 585: else if (rrop == RROP_BLACK) ! 586: pGC->PolyGlyphBlt = mfbPolyGlyphBltBlack; ! 587: else if (rrop == RROP_INVERT) ! 588: pGC->PolyGlyphBlt = mfbPolyGlyphBltInvert; ! 589: else ! 590: pGC->PolyGlyphBlt = NoopDDA; ! 591: } ! 592: else ! 593: { ! 594: pGC->PolyGlyphBlt = miPolyGlyphBlt; ! 595: } ! 596: } ! 597: } ! 598: ! 599: if (new_fill) ! 600: { ! 601: /* install a suitable fillspans */ ! 602: if ((pGC->fillStyle == FillSolid) || ! 603: (pGC->fillStyle == FillOpaqueStippled && pGC->fgPixel==pGC->bgPixel) ! 604: ) ! 605: { ! 606: switch(devPriv->rop) ! 607: { ! 608: case RROP_WHITE: ! 609: pGC->FillSpans = mfbWhiteSolidFS; ! 610: break; ! 611: case RROP_BLACK: ! 612: pGC->FillSpans = mfbBlackSolidFS; ! 613: break; ! 614: case RROP_INVERT: ! 615: pGC->FillSpans = mfbInvertSolidFS; ! 616: break; ! 617: case RROP_NOP: ! 618: pGC->FillSpans = NoopDDA; ! 619: break; ! 620: } ! 621: } ! 622: /* beyond this point, opaqueStippled ==> fg != bg */ ! 623: else if ((pGC->fillStyle==FillTiled && pGC->tile->width!=32) || ! 624: (pGC->fillStyle==FillOpaqueStippled && pGC->stipple->width!=32) ! 625: ) ! 626: { ! 627: pGC->FillSpans = mfbUnnaturalTileFS; ! 628: } ! 629: else if (pGC->fillStyle == FillStippled && pGC->stipple->width != 32) ! 630: { ! 631: pGC->FillSpans = mfbUnnaturalStippleFS; ! 632: } ! 633: else if (pGC->fillStyle == FillStippled) ! 634: { ! 635: switch(devPriv->rop) ! 636: { ! 637: case RROP_WHITE: ! 638: pGC->FillSpans = mfbWhiteStippleFS; ! 639: break; ! 640: case RROP_BLACK: ! 641: pGC->FillSpans = mfbBlackStippleFS; ! 642: break; ! 643: case RROP_INVERT: ! 644: pGC->FillSpans = mfbInvertStippleFS; ! 645: break; ! 646: case RROP_NOP: ! 647: pGC->FillSpans = NoopDDA; ! 648: break; ! 649: } ! 650: } ! 651: else /* overload tiles to do parti-colored opaque stipples */ ! 652: { ! 653: pGC->FillSpans = mfbTileFS; ! 654: } ! 655: ! 656: /* the rectangle code doesn't deal with opaque stipples that ! 657: are two colors -- we can fool it for fg==bg, though ! 658: */ ! 659: if (((pGC->fillStyle == FillTiled) && (pGC->tile->width!=32)) || ! 660: ((pGC->fillStyle == FillStippled) && (pGC->stipple->width!=32)) || ! 661: ((pGC->fillStyle == FillOpaqueStippled) && ! 662: (pGC->fgPixel != pGC->bgPixel)) ! 663: ) ! 664: { ! 665: pGC->PolyFillRect = miPolyFillRect; ! 666: devPriv->ppPixmap = &BogusPixmap; ! 667: } ! 668: else /* deal with solids and natural stipples and tiles */ ! 669: { ! 670: pGC->PolyFillRect = mfbPolyFillRect; ! 671: ! 672: if ((pGC->fillStyle == FillSolid) || ! 673: (pGC->fillStyle == FillOpaqueStippled && ! 674: pGC->fgPixel == pGC->bgPixel) ! 675: ) ! 676: { ! 677: devPriv->ppPixmap = &BogusPixmap; ! 678: switch(devPriv->rop) ! 679: { ! 680: case RROP_WHITE: ! 681: devPriv->FillArea = mfbSolidWhiteArea; ! 682: break; ! 683: case RROP_BLACK: ! 684: devPriv->FillArea = mfbSolidBlackArea; ! 685: break; ! 686: case RROP_INVERT: ! 687: devPriv->FillArea = mfbSolidInvertArea; ! 688: break; ! 689: case RROP_NOP: ! 690: devPriv->FillArea = NoopDDA; ! 691: break; ! 692: } ! 693: } ! 694: else if (pGC->fillStyle == FillStippled) ! 695: { ! 696: devPriv->ppPixmap = &devPriv->pRotatedStipple; ! 697: switch(devPriv->rop) ! 698: { ! 699: case RROP_WHITE: ! 700: devPriv->FillArea = mfbStippleWhiteArea; ! 701: break; ! 702: case RROP_BLACK: ! 703: devPriv->FillArea = mfbStippleBlackArea; ! 704: break; ! 705: case RROP_INVERT: ! 706: devPriv->FillArea = mfbStippleInvertArea; ! 707: break; ! 708: case RROP_NOP: ! 709: devPriv->FillArea = NoopDDA; ! 710: break; ! 711: } ! 712: } ! 713: else /* deal with tiles */ ! 714: { ! 715: if (pGC->fillStyle == FillTiled) ! 716: devPriv->ppPixmap = &devPriv->pRotatedTile; ! 717: else ! 718: devPriv->ppPixmap = &devPriv->pRotatedStipple; ! 719: devPriv->FillArea = mfbTileArea32; ! 720: } ! 721: } /* end of natural rectangles */ ! 722: } /* end of new_fill */ ! 723: ! 724: ! 725: if(new_rotate) ! 726: { ! 727: /* figure out how much to rotate */ ! 728: xrot = pGC->patOrg.x; ! 729: yrot = pGC->patOrg.y; ! 730: if (pWin) ! 731: { ! 732: xrot += pWin->absCorner.x; ! 733: yrot += pWin->absCorner.y; ! 734: } ! 735: ! 736: /* destroy any previously rotated tile or stipple */ ! 737: if(devPriv->pRotatedTile) ! 738: { ! 739: mfbDestroyPixmap(devPriv->pRotatedTile); ! 740: devPriv->pRotatedTile = (PixmapPtr)NULL; ! 741: } ! 742: if(devPriv->pRotatedStipple) ! 743: { ! 744: mfbDestroyPixmap(devPriv->pRotatedStipple); ! 745: devPriv->pRotatedStipple = (PixmapPtr)NULL; ! 746: } ! 747: ! 748: /* copy current tile and stipple */ ! 749: if(pGC->tile && ! 750: (pGC->tile->width == 32) && ! 751: (devPriv->pRotatedTile = mfbCopyPixmap(pGC->tile)) == ! 752: (PixmapPtr)NULL) ! 753: return ; /* shouldn't happen, internal error */ ! 754: if(pGC->stipple && ! 755: (pGC->stipple->width == 32) && ! 756: (devPriv->pRotatedStipple = mfbCopyPixmap(pGC->stipple)) == ! 757: (PixmapPtr)NULL) ! 758: return ; /* shouldn't happen, internal error */ ! 759: ! 760: if(xrot) ! 761: { ! 762: if (pGC->tile && pGC->tile->width == 32 && ! 763: devPriv->pRotatedTile) ! 764: mfbXRotatePixmap(devPriv->pRotatedTile, xrot); ! 765: if (pGC->stipple && pGC->stipple->width == 32 && ! 766: devPriv->pRotatedStipple) ! 767: mfbXRotatePixmap(devPriv->pRotatedStipple, xrot); ! 768: } ! 769: if(yrot) ! 770: { ! 771: if (pGC->tile && pGC->tile->width == 32 && ! 772: devPriv->pRotatedTile) ! 773: mfbYRotatePixmap(devPriv->pRotatedTile, yrot); ! 774: if (pGC->tile && pGC->tile->width == 32 && ! 775: devPriv->pRotatedStipple) ! 776: mfbYRotatePixmap(devPriv->pRotatedStipple, yrot); ! 777: } ! 778: } ! 779: ! 780: return ; ! 781: } ! 782: ! 783: /* table to map alu(src, dst) to alu(~src, dst) */ ! 784: int InverseAlu[16] = { ! 785: GXclear, ! 786: GXandInverted, ! 787: GXnor, ! 788: GXcopyInverted, ! 789: GXand, ! 790: GXnoop, ! 791: GXequiv, ! 792: GXorInverted, ! 793: GXandReverse, ! 794: GXxor, ! 795: GXinvert, ! 796: GXnand, ! 797: GXcopy, ! 798: GXor, ! 799: GXorReverse, ! 800: GXset ! 801: }; ! 802: ! 803: ReduceRop(alu, src) ! 804: register int alu; ! 805: register int src; ! 806: { ! 807: int rop; ! 808: if (src == 0) /* src is black */ ! 809: { ! 810: switch(alu) ! 811: { ! 812: case GXclear: ! 813: rop = RROP_BLACK; ! 814: break; ! 815: case GXand: ! 816: rop = RROP_BLACK; ! 817: break; ! 818: case GXandReverse: ! 819: rop = RROP_BLACK; ! 820: break; ! 821: case GXcopy: ! 822: rop = RROP_BLACK; ! 823: break; ! 824: case GXandInverted: ! 825: rop = RROP_NOP; ! 826: break; ! 827: case GXnoop: ! 828: rop = RROP_NOP; ! 829: break; ! 830: case GXxor: ! 831: rop = RROP_NOP; ! 832: break; ! 833: case GXor: ! 834: rop = RROP_NOP; ! 835: break; ! 836: case GXnor: ! 837: rop = RROP_INVERT; ! 838: break; ! 839: case GXequiv: ! 840: rop = RROP_INVERT; ! 841: break; ! 842: case GXinvert: ! 843: rop = RROP_INVERT; ! 844: break; ! 845: case GXorReverse: ! 846: rop = RROP_INVERT; ! 847: break; ! 848: case GXcopyInverted: ! 849: rop = RROP_WHITE; ! 850: break; ! 851: case GXorInverted: ! 852: rop = RROP_WHITE; ! 853: break; ! 854: case GXnand: ! 855: rop = RROP_WHITE; ! 856: break; ! 857: case GXset: ! 858: rop = RROP_WHITE; ! 859: break; ! 860: } ! 861: } ! 862: else /* src is white */ ! 863: { ! 864: switch(alu) ! 865: { ! 866: case GXclear: ! 867: rop = RROP_BLACK; ! 868: break; ! 869: case GXand: ! 870: rop = RROP_NOP; ! 871: break; ! 872: case GXandReverse: ! 873: rop = RROP_INVERT; ! 874: break; ! 875: case GXcopy: ! 876: rop = RROP_WHITE; ! 877: break; ! 878: case GXandInverted: ! 879: rop = RROP_BLACK; ! 880: break; ! 881: case GXnoop: ! 882: rop = RROP_NOP; ! 883: break; ! 884: case GXxor: ! 885: rop = RROP_INVERT; ! 886: break; ! 887: case GXor: ! 888: rop = RROP_WHITE; ! 889: break; ! 890: case GXnor: ! 891: rop = RROP_BLACK; ! 892: break; ! 893: case GXequiv: ! 894: rop = RROP_NOP; ! 895: break; ! 896: case GXinvert: ! 897: rop = RROP_INVERT; ! 898: break; ! 899: case GXorReverse: ! 900: rop = RROP_WHITE; ! 901: break; ! 902: case GXcopyInverted: ! 903: rop = RROP_BLACK; ! 904: break; ! 905: case GXorInverted: ! 906: rop = RROP_NOP; ! 907: break; ! 908: case GXnand: ! 909: rop = RROP_INVERT; ! 910: break; ! 911: case GXset: ! 912: rop = RROP_WHITE; ! 913: break; ! 914: } ! 915: } ! 916: return rop; ! 917: } ! 918: ! 919: void ! 920: mfbDestroyClip(pGC) ! 921: GCPtr pGC; ! 922: { ! 923: if(pGC->clientClipType == CT_NONE) ! 924: return; ! 925: else if (pGC->clientClipType == CT_PIXMAP) ! 926: { ! 927: mfbDestroyPixmap((PixmapPtr)(pGC->clientClip)); ! 928: } ! 929: else ! 930: { ! 931: /* we know we'll never have a list of rectangles, since ! 932: ChangeClip immediately turns them into a region ! 933: */ ! 934: (*pGC->pScreen->RegionDestroy)(pGC->clientClip); ! 935: } ! 936: pGC->clientClip = NULL; ! 937: pGC->clientClipType = CT_NONE; ! 938: } ! 939: ! 940: void ! 941: mfbChangeClip(pGC, type, pvalue, nrects) ! 942: GCPtr pGC; ! 943: int type; ! 944: pointer pvalue; ! 945: int nrects; ! 946: { ! 947: /* ! 948: remember to bump the pixmap's refcnt before destroying the old ! 949: one, since the two may be the same. ! 950: regions that have been fed to the clip code are assumed to have ! 951: disappeared, so we'll never see the same one twice. ! 952: */ ! 953: ! 954: if (type == CT_PIXMAP) ! 955: { ! 956: /* so we can call destroy later, and leave this as ! 957: an example ! 958: */ ! 959: ((PixmapPtr)(pvalue))->refcnt++; ! 960: } ! 961: ! 962: mfbDestroyClip(pGC); ! 963: if(type == CT_PIXMAP) ! 964: { ! 965: /* convert the pixmap to a region */ ! 966: pGC->clientClip = (pointer) mfbPixmapToRegion(pvalue); ! 967: /* you wouldn't do this if you were leaving the pixmap in ! 968: rather than converting it. ! 969: */ ! 970: (*pGC->pScreen->DestroyPixmap)(pvalue); ! 971: } ! 972: else if (type == CT_REGION) ! 973: { ! 974: /* stuff the region in the GC */ ! 975: pGC->clientClip = pvalue; ! 976: } ! 977: else if (type != CT_NONE) ! 978: { ! 979: pGC->clientClip = (pointer) miRectsToRegion(pGC, nrects, pvalue, type); ! 980: Xfree(pvalue); ! 981: } ! 982: pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION : ! 983: CT_NONE; ! 984: pGC->stateChanges |= GCClipMask; ! 985: } ! 986: ! 987: void ! 988: mfbCopyClip (pgcDst, pgcSrc) ! 989: GCPtr pgcDst, pgcSrc; ! 990: { ! 991: RegionPtr prgnNew; ! 992: ! 993: switch(pgcSrc->clientClipType) ! 994: { ! 995: case CT_NONE: ! 996: case CT_PIXMAP: ! 997: mfbChangeClip(pgcDst, pgcSrc->clientClipType, pgcSrc->clientClip, 0); ! 998: break; ! 999: case CT_REGION: ! 1000: prgnNew = (*pgcSrc->pScreen->RegionCreate)(NULL, 1); ! 1001: (*pgcSrc->pScreen->RegionCopy)(prgnNew, ! 1002: (RegionPtr)(pgcSrc->clientClip)); ! 1003: mfbChangeClip(pgcDst, CT_REGION, prgnNew, 0); ! 1004: break; ! 1005: } ! 1006: } ! 1007: ! 1008: void ! 1009: mfbCopyGCDest (pGC, pQ, changes, pGCSrc) ! 1010: GCPtr pGC; ! 1011: GCInterestPtr pQ; ! 1012: Mask changes; ! 1013: GCPtr pGCSrc; ! 1014: { ! 1015: RegionPtr pClip; ! 1016: ! 1017: if(changes & GCClipMask) ! 1018: { ! 1019: if(pGC->clientClipType == CT_PIXMAP) ! 1020: { ! 1021: ((PixmapPtr)pGC->clientClip)->refcnt++; ! 1022: } ! 1023: else if(pGC->clientClipType == CT_REGION) ! 1024: { ! 1025: BoxRec pixbounds; ! 1026: ! 1027: pixbounds.x1 = 0; ! 1028: pixbounds.y1 = 0; ! 1029: pixbounds.x2 = 0; ! 1030: pixbounds.y2 = 0; ! 1031: ! 1032: pClip = (RegionPtr) pGC->clientClip; ! 1033: pGC->clientClip = ! 1034: (pointer)(* pGC->pScreen->RegionCreate)(&pixbounds, 1); ! 1035: (* pGC->pScreen->RegionCopy)(pGC->clientClip, pClip); ! 1036: } ! 1037: } ! 1038: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.