📄 mfbgc.c
字号:
new_fill = FALSE; mask = changes; while (mask) { index = lowbit (mask); mask &= ~index; /* this switch acculmulates a list of which procedures might have to change due to changes in the GC. in some cases (e.g. changing one 16 bit tile for another) we might not really need a change, but the code is being paranoid. this sort of batching wins if, for example, the alu and the font have been changed, or any other pair of items that both change the same thing. */ switch (index) { case GCFunction: case GCForeground: new_rrop = TRUE; break; case GCPlaneMask: break; case GCBackground: new_rrop = TRUE; /* for opaque stipples */ break; case GCLineStyle: case GCLineWidth: case GCJoinStyle: new_line = TRUE; break; case GCCapStyle: break; case GCFillStyle: new_fill = TRUE; break; case GCFillRule: break; case GCTile: if(pGC->tileIsPixel) break; new_rotate = TRUE; new_fill = TRUE; break; case GCStipple: if(pGC->stipple == (PixmapPtr)NULL) break; new_rotate = TRUE; new_fill = TRUE; break; case GCTileStipXOrigin: new_rotate = TRUE; break; case GCTileStipYOrigin: new_rotate = TRUE; break; case GCFont: new_text = TRUE; break; case GCSubwindowMode: break; case GCGraphicsExposures: break; case GCClipXOrigin: break; case GCClipYOrigin: break; case GCClipMask: break; case GCDashOffset: break; case GCDashList: break; case GCArcMode: break; default: break; } } /* deal with the changes we've collected . new_rrop must be done first because subsequent things depend on it. */ if(new_rotate || new_fill) { Bool new_pix = FALSE; /* figure out how much to rotate */ xrot = pGC->patOrg.x; yrot = pGC->patOrg.y; xrot += pDrawable->x; yrot += pDrawable->y; switch (pGC->fillStyle) { case FillTiled: /* copy current tile and stipple */ if (!pGC->tileIsPixel && (pGC->tile.pixmap->drawable.width <= 32) && !(pGC->tile.pixmap->drawable.width & (pGC->tile.pixmap->drawable.width - 1))) { mfbCopyRotatePixmap(pGC->tile.pixmap, &devPriv->pRotatedPixmap, xrot, yrot); new_pix = TRUE; } break; case FillStippled: case FillOpaqueStippled: if (pGC->stipple && (pGC->stipple->drawable.width <= 32) && !(pGC->stipple->drawable.width & (pGC->stipple->drawable.width - 1))) { if (pGC->stipple == pGC->pScreen->PixmapPerDepth[0]) { if (pGC->stipple->drawable.width != 32) mfbPadPixmap(pGC->stipple); if (devPriv->pRotatedPixmap) mfbDestroyPixmap(devPriv->pRotatedPixmap); devPriv->pRotatedPixmap = pGC->stipple; ++devPriv->pRotatedPixmap->refcnt; } else { mfbCopyRotatePixmap(pGC->stipple, &devPriv->pRotatedPixmap, xrot, yrot); } new_pix = TRUE; } } /* destroy any previously rotated tile or stipple */ if (!new_pix && devPriv->pRotatedPixmap) { mfbDestroyPixmap(devPriv->pRotatedPixmap); devPriv->pRotatedPixmap = (PixmapPtr)NULL; } } /* * duck out here when the GC is unchanged */ if (!changes) return; if (new_rrop || new_fill) { rrop = mfbReduceRop(pGC->alu, pGC->fgPixel); devPriv->rop = rrop; new_fill = TRUE; /* FillArea raster op is GC's for tile filling, and the reduced rop for solid and stipple */ if (pGC->fillStyle == FillTiled) devPriv->ropFillArea = pGC->alu; else devPriv->ropFillArea = rrop; /* opaque stipples: fg bg ropOpStip fill style 1 0 alu tile 0 1 inverseAlu tile 1 1 rrop(fg, alu) solid 0 0 rrop(fg, alu) solid Note that rrop(fg, alu) == mfbPrivGC.rop, so we don't really need to compute it. */ if (pGC->fillStyle == FillOpaqueStippled) { if ((pGC->fgPixel & 1) != (pGC->bgPixel & 1)) { if (pGC->fgPixel & 1) devPriv->ropOpStip = pGC->alu; else devPriv->ropOpStip = InverseAlu[pGC->alu]; } else devPriv->ropOpStip = rrop; devPriv->ropFillArea = devPriv->ropOpStip; } } else rrop = devPriv->rop; if (new_line || new_fill || new_text) { GCOps *newops; if (newops = matchCommon (pGC)) { if (pGC->ops->devPrivate.val) mfbDestroyOps (pGC->ops); pGC->ops = newops; new_line = new_fill = new_text = 0; } else { if (!pGC->ops->devPrivate.val) { pGC->ops = mfbCreateOps (pGC->ops); pGC->ops->devPrivate.val = 1; } } } if (new_line || new_fill) { if (pGC->lineWidth == 0) { if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid) && ((rrop == RROP_WHITE) || (rrop == RROP_BLACK))) pGC->ops->PolyArc = mfbZeroPolyArcSS; else pGC->ops->PolyArc = miZeroPolyArc; } else pGC->ops->PolyArc = miPolyArc; if (pGC->lineStyle == LineSolid) { if(pGC->lineWidth == 0) { if (pGC->fillStyle == FillSolid) { pGC->ops->PolySegment = mfbSegmentSS; pGC->ops->Polylines = mfbLineSS; } else { pGC->ops->PolySegment = miPolySegment; pGC->ops->Polylines = miZeroLine; } } else { pGC->ops->PolySegment = miPolySegment; pGC->ops->Polylines = miWideLine; } } else { if(pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) { pGC->ops->Polylines = mfbLineSD; pGC->ops->PolySegment = mfbSegmentSD; } else { pGC->ops->Polylines = miWideDash; pGC->ops->PolySegment = miPolySegment; } } } if (new_text || new_fill) { if ((pGC->font) && (FONTMAXBOUNDS(pGC->font,rightSideBearing) - FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 || FONTMINBOUNDS(pGC->font,characterWidth) < 0)) { pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; pGC->ops->ImageGlyphBlt = miImageGlyphBlt; } else { /* special case ImageGlyphBlt for terminal emulator fonts */ if ((pGC->font) && TERMINALFONT(pGC->font) && ((pGC->fgPixel & 1) != (pGC->bgPixel & 1))) { /* pcc bug makes this not compile... pGC->ops->ImageGlyphBlt = (pGC->fgPixel & 1) ? mfbTEGlyphBltWhite : mfbTEGlyphBltBlack; */ if (pGC->fgPixel & 1) pGC->ops->ImageGlyphBlt = mfbTEGlyphBltWhite; else pGC->ops->ImageGlyphBlt = mfbTEGlyphBltBlack; } else { if (pGC->fgPixel & 1) pGC->ops->ImageGlyphBlt = mfbImageGlyphBltWhite; else pGC->ops->ImageGlyphBlt = mfbImageGlyphBltBlack; } /* now do PolyGlyphBlt */ if (pGC->fillStyle == FillSolid || (pGC->fillStyle == FillOpaqueStippled && (pGC->fgPixel & 1) == (pGC->bgPixel & 1) ) ) { if (rrop == RROP_WHITE) pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltWhite; else if (rrop == RROP_BLACK) pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltBlack; else if (rrop == RROP_INVERT) pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltInvert; else pGC->ops->PolyGlyphBlt = NoopDDA; } else { pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; } } } if (new_fill) { /* install a suitable fillspans and pushpixels */ pGC->ops->PushPixels = mfbPushPixels; if ((pGC->fillStyle == FillSolid) || ((pGC->fillStyle == FillOpaqueStippled) && ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)))) { pGC->ops->PushPixels = mfbSolidPP; switch(devPriv->rop) { case RROP_WHITE: pGC->ops->FillSpans = mfbWhiteSolidFS; break; case RROP_BLACK: pGC->ops->FillSpans = mfbBlackSolidFS; break; case RROP_INVERT: pGC->ops->FillSpans = mfbInvertSolidFS; break; case RROP_NOP: pGC->ops->FillSpans = NoopDDA; break; } } /* beyond this point, opaqueStippled ==> fg != bg */ else if (((pGC->fillStyle == FillTiled) || (pGC->fillStyle == FillOpaqueStippled)) && !devPriv->pRotatedPixmap) { pGC->ops->FillSpans = mfbUnnaturalTileFS; } else if ((pGC->fillStyle == FillStippled) && !devPriv->pRotatedPixmap) { pGC->ops->FillSpans = mfbUnnaturalStippleFS; } else if (pGC->fillStyle == FillStippled) { switch(devPriv->rop) { case RROP_WHITE: pGC->ops->FillSpans = mfbWhiteStippleFS; break; case RROP_BLACK: pGC->ops->FillSpans = mfbBlackStippleFS; break; case RROP_INVERT: pGC->ops->FillSpans = mfbInvertStippleFS; break; case RROP_NOP: pGC->ops->FillSpans = NoopDDA; break; } } else /* overload tiles to do parti-colored opaque stipples */ { pGC->ops->FillSpans = mfbTileFS; } if (pGC->fillStyle == FillSolid) pGC->ops->PolyFillArc = mfbPolyFillArcSolid; else pGC->ops->PolyFillArc = miPolyFillArc; /* the rectangle code doesn't deal with opaque stipples that are two colors -- we can fool it for fg==bg, though */ if ((((pGC->fillStyle == FillTiled) || (pGC->fillStyle == FillStippled)) && !devPriv->pRotatedPixmap) || ((pGC->fillStyle == FillOpaqueStippled) && ((pGC->fgPixel & 1) != (pGC->bgPixel & 1))) ) { pGC->ops->PolyFillRect = miPolyFillRect; } else /* deal with solids and natural stipples and tiles */ { pGC->ops->PolyFillRect = mfbPolyFillRect; if ((pGC->fillStyle == FillSolid) || ((pGC->fillStyle == FillOpaqueStippled) && ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)))) { switch(devPriv->rop) { case RROP_WHITE: devPriv->FillArea = mfbSolidWhiteArea; break; case RROP_BLACK: devPriv->FillArea = mfbSolidBlackArea; break; case RROP_INVERT: devPriv->FillArea = mfbSolidInvertArea; break; case RROP_NOP: devPriv->FillArea = NoopDDA; break; } } else if (pGC->fillStyle == FillStippled) { switch(devPriv->rop) { case RROP_WHITE: devPriv->FillArea = mfbStippleWhiteArea; break; case RROP_BLACK: devPriv->FillArea = mfbStippleBlackArea; break; case RROP_INVERT: devPriv->FillArea = mfbStippleInvertArea; break; case RROP_NOP: devPriv->FillArea = NoopDDA; break; } } else /* deal with tiles */ { extern void mfbTileArea32Copy(), mfbTileArea32General(); switch (pGC->alu) { case GXcopy: devPriv->FillArea = mfbTileArea32Copy; break; default: devPriv->FillArea = mfbTileArea32General; break; } } } /* end of natural rectangles */ } /* end of new_fill */}/* table to map alu(src, dst) to alu(~src, dst) */int InverseAlu[16] = { GXclear, GXandInverted, GXnor, GXcopyInverted, GXand, GXnoop, GXequiv, GXorInverted, GXandReverse, GXxor, GXinvert, GXnand, GXcopy, GXor, GXorReverse, GXset};intmfbReduceRop(alu, src) register unsigned char alu; register Pixel src;{ int rop; if ((src & 1) == 0) /* src is black */ { switch(alu) { case GXclear: rop = RROP_BLACK; break; case GXand: rop = RROP_BLACK; break; case GXandReverse: rop = RROP_BLACK; break; case GXcopy: rop = RROP_BLACK; break; case GXandInverted: rop = RROP_NOP; break; case GXnoop: rop = RROP_NOP; break; case GXxor: rop = RROP_NOP; break; case GXor: rop = RROP_NOP; break; case GXnor: rop = RROP_INVERT; break; case GXequiv: rop = RROP_INVERT; break; case GXinvert: rop = RROP_INVERT; break; case GXorReverse: rop = RROP_INVERT; break; case GXcopyInverted: rop = RROP_WHITE; break; case GXorInverted: rop = RROP_WHITE; break; case GXnand: rop = RROP_WHITE; break; case GXset: rop = RROP_WHITE; break; } } else /* src is white */ { switch(alu) { case GXclear: rop = RROP_BLACK; break; case GXand: rop = RROP_NOP; break; case GXandReverse: rop = RROP_INVERT; break; case GXcopy: rop = RROP_WHITE; break; case GXandInverted: rop = RROP_BLACK; break; case GXnoop: rop = RROP_NOP; break; case GXxor: rop = RROP_INVERT; break; case GXor: rop = RROP_WHITE; break; case GXnor: rop = RROP_BLACK; break; case GXequiv: rop = RROP_NOP; break; case GXinvert: rop = RROP_INVERT; break; case GXorReverse: rop = RROP_WHITE; break; case GXcopyInverted: rop = RROP_BLACK; break; case GXorInverted: rop = RROP_NOP; break; case GXnand: rop = RROP_INVERT; break; case GXset: rop = RROP_WHITE; break; } } return rop;}voidmfbDestroyClip(pGC) GCPtr pGC;{ if(pGC->clientClipType == CT_NONE) return; else if (pGC->clientClipType == CT_PIXMAP) { mfbDestroyPixmap((PixmapPtr)(pGC->clientClip)); } else { /* we know we'll never have a list of rectangles, since ChangeClip immediately turns them into a region */ (*pGC->pScreen->RegionDestroy)(pGC->clientClip); } pGC->clientClip = NULL; pGC->clientClipType = CT_NONE;}voidmfbChangeClip(pGC, type, pvalue, nrects) GCPtr pGC; unsigned int type; pointer pvalue; int nrects;{ mfbDestroyClip(pGC); if(type == CT_PIXMAP) { /* convert the pixmap to a region */ pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr)pvalue); /* you wouldn't do this if you were leaving the pixmap in rather than converting it. */ (*pGC->pScreen->DestroyPixmap)(pvalue); } else if (type == CT_REGION) { /* stuff the region in the GC */ pGC->clientClip = pvalue; } else if (type != CT_NONE) { pGC->clientClip = (pointer) (*pGC->pScreen->RectsToRegion)(nrects, (xRectangle *)pvalue, type); xfree(pvalue); } pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION : CT_NONE; pGC->stateChanges |= GCClipMask;}voidmfbCopyClip (pgcDst, pgcSrc) GCPtr pgcDst, pgcSrc;{ RegionPtr prgnNew; switch(pgcSrc->clientClipType) { case CT_PIXMAP: ((PixmapPtr) pgcSrc->clientClip)->refcnt++; /* Fall through !! */ case CT_NONE: mfbChangeClip(pgcDst, pgcSrc->clientClipType, pgcSrc->clientClip, 0); break; case CT_REGION: prgnNew = (*pgcSrc->pScreen->RegionCreate)(NULL, 1); (*pgcSrc->pScreen->RegionCopy)(prgnNew, (RegionPtr)(pgcSrc->clientClip)); mfbChangeClip(pgcDst, CT_REGION, (pointer)prgnNew, 0); break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -