aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/mfb/mfbgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/mfb/mfbgc.c')
-rw-r--r--xorg-server/mfb/mfbgc.c1120
1 files changed, 1120 insertions, 0 deletions
diff --git a/xorg-server/mfb/mfbgc.c b/xorg-server/mfb/mfbgc.c
new file mode 100644
index 000000000..7492d7c04
--- /dev/null
+++ b/xorg-server/mfb/mfbgc.c
@@ -0,0 +1,1120 @@
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include <X11/Xproto.h>
+#include "mfb.h"
+#include "dixfontstr.h"
+#include <X11/fonts/fontstruct.h>
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+#include "region.h"
+
+#include "mistruct.h"
+#include "migc.h"
+
+#include "maskbits.h"
+
+static GCFuncs mfbFuncs = {
+ mfbValidateGC,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+
+static GCOps whiteTECopyOps = {
+ mfbWhiteSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ mfbZeroPolyArcSS,
+ mfbFillPolyWhite,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ mfbTEGlyphBltWhite,
+ mfbPolyGlyphBltWhite,
+ mfbSolidPP
+};
+
+static GCOps blackTECopyOps = {
+ mfbBlackSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ mfbZeroPolyArcSS,
+ mfbFillPolyBlack,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ mfbTEGlyphBltBlack,
+ mfbPolyGlyphBltBlack,
+ mfbSolidPP
+};
+
+static GCOps whiteTEInvertOps = {
+ mfbInvertSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ miCopyArea,
+ miCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ miZeroPolyArc,
+ mfbFillPolyInvert,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ mfbTEGlyphBltWhite,
+ mfbPolyGlyphBltInvert,
+ mfbSolidPP
+};
+
+static GCOps blackTEInvertOps = {
+ mfbInvertSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ miZeroPolyArc,
+ mfbFillPolyInvert,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ mfbTEGlyphBltBlack,
+ mfbPolyGlyphBltInvert,
+ mfbSolidPP
+};
+
+static GCOps whiteCopyOps = {
+ mfbWhiteSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ mfbZeroPolyArcSS,
+ mfbFillPolyWhite,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ mfbImageGlyphBltWhite,
+ mfbPolyGlyphBltWhite,
+ mfbSolidPP
+};
+
+static GCOps blackCopyOps = {
+ mfbBlackSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ mfbZeroPolyArcSS,
+ mfbFillPolyBlack,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ mfbImageGlyphBltBlack,
+ mfbPolyGlyphBltBlack,
+ mfbSolidPP
+};
+
+static GCOps whiteInvertOps = {
+ mfbInvertSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ miZeroPolyArc,
+ mfbFillPolyInvert,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ mfbImageGlyphBltWhite,
+ mfbPolyGlyphBltInvert,
+ mfbSolidPP
+};
+
+static GCOps blackInvertOps = {
+ mfbInvertSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ miZeroPolyArc,
+ mfbFillPolyInvert,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ mfbImageGlyphBltBlack,
+ mfbPolyGlyphBltInvert,
+ mfbSolidPP
+};
+
+static GCOps whiteWhiteCopyOps = {
+ mfbWhiteSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ mfbZeroPolyArcSS,
+ mfbFillPolyWhite,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ miImageGlyphBlt,
+ mfbPolyGlyphBltWhite,
+ mfbSolidPP
+};
+
+static GCOps blackBlackCopyOps = {
+ mfbBlackSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ mfbZeroPolyArcSS,
+ mfbFillPolyBlack,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ miImageGlyphBlt,
+ mfbPolyGlyphBltBlack,
+ mfbSolidPP
+};
+
+static GCOps fgEqBgInvertOps = {
+ mfbInvertSolidFS,
+ mfbSetSpans,
+ mfbPutImage,
+ mfbCopyArea,
+ mfbCopyPlane,
+ mfbPolyPoint,
+ mfbLineSS,
+ mfbSegmentSS,
+ miPolyRectangle,
+ miZeroPolyArc,
+ mfbFillPolyInvert,
+ mfbPolyFillRect,
+ mfbPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ miImageGlyphBlt,
+ mfbPolyGlyphBltInvert,
+ mfbSolidPP
+};
+
+
+struct commonOps {
+ int fg, bg;
+ int rrop;
+ int terminalFont;
+ GCOps *ops;
+ void (*fillArea)(
+ DrawablePtr /*pDraw*/,
+ int /*nbox*/,
+ BoxPtr /*pbox*/,
+ int /*alu*/,
+ PixmapPtr /*nop*/);
+};
+
+static struct commonOps mfbCommonOps[] = {
+ { 1, 0, RROP_WHITE, 1, &whiteTECopyOps, mfbSolidWhiteArea },
+ { 0, 1, RROP_BLACK, 1, &blackTECopyOps, mfbSolidBlackArea },
+ { 1, 0, RROP_INVERT, 1, &whiteTEInvertOps, mfbSolidInvertArea },
+ { 0, 1, RROP_INVERT, 1, &blackTEInvertOps, mfbSolidInvertArea },
+ { 1, 0, RROP_WHITE, 0, &whiteCopyOps, mfbSolidWhiteArea },
+ { 0, 1, RROP_BLACK, 0, &blackCopyOps, mfbSolidBlackArea },
+ { 1, 0, RROP_INVERT, 0, &whiteInvertOps, mfbSolidInvertArea },
+ { 0, 1, RROP_INVERT, 0, &blackInvertOps, mfbSolidInvertArea },
+ { 1, 1, RROP_WHITE, 0, &whiteWhiteCopyOps, mfbSolidWhiteArea },
+ { 0, 0, RROP_BLACK, 0, &blackBlackCopyOps, mfbSolidBlackArea },
+ { 1, 1, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea },
+ { 0, 0, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea },
+};
+
+#define numberCommonOps (sizeof (mfbCommonOps) / sizeof (mfbCommonOps[0]))
+
+static GCOps *
+matchCommon (
+ GCPtr pGC)
+{
+ int i;
+ struct commonOps *cop;
+ mfbPrivGC *priv;
+
+ if (pGC->lineWidth != 0)
+ return 0;
+ if (pGC->lineStyle != LineSolid)
+ return 0;
+ if (pGC->fillStyle != FillSolid)
+ return 0;
+ if (!pGC->font ||
+ FONTMAXBOUNDS(pGC->font,rightSideBearing) -
+ FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
+ FONTMINBOUNDS(pGC->font,characterWidth) < 0)
+ return 0;
+ priv = (mfbPrivGC *)dixLookupPrivate(&pGC->devPrivates,
+ mfbGetGCPrivateKey());
+ for (i = 0; i < numberCommonOps; i++) {
+ cop = &mfbCommonOps[i];
+ if ((pGC->fgPixel & 1) != cop->fg)
+ continue;
+ if ((pGC->bgPixel & 1) != cop->bg)
+ continue;
+ if (priv->rop != cop->rrop)
+ continue;
+ if (cop->terminalFont && !TERMINALFONT(pGC->font))
+ continue;
+ priv->FillArea = cop->fillArea;
+ return cop->ops;
+ }
+ return 0;
+}
+
+
+Bool
+mfbCreateGC(pGC)
+ register GCPtr pGC;
+{
+ mfbPrivGC *pPriv;
+
+ pGC->clientClip = NULL;
+ pGC->clientClipType = CT_NONE;
+
+ /* some of the output primitives aren't really necessary, since
+ they will be filled in ValidateGC because of dix/CreateGC()
+ setting all the change bits. Others are necessary because although
+ they depend on being a monochrome frame buffer, they don't change
+ */
+
+ pGC->ops = &whiteCopyOps;
+ pGC->funcs = &mfbFuncs;
+
+ /* mfb wants to translate before scan convesion */
+ pGC->miTranslate = 1;
+
+ pPriv = (mfbPrivGC *)dixLookupPrivate(&pGC->devPrivates,
+ mfbGetGCPrivateKey());
+ pPriv->rop = mfbReduceRop(pGC->alu, pGC->fgPixel);
+ pGC->fExpose = TRUE;
+ pGC->pRotatedPixmap = NullPixmap;
+ pGC->freeCompClip = FALSE;
+ pPriv->FillArea = mfbSolidInvertArea;
+ return TRUE;
+}
+
+/* some noop functions */
+static void
+mfbPolyGlyphBltNoop(
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr * ppci,
+ pointer pglyphBase)
+{
+ /* this is a no-op function */
+}
+
+static void
+mfbNoopFS(
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nInit,
+ DDXPointPtr pptInit,
+ int * pwidthInit,
+ int fSorted)
+{
+ /* this is a no-op function */
+}
+
+static void
+mfbFillPolyNoop(
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ int shape,
+ int mode,
+ int count,
+ DDXPointPtr ptsIn)
+{
+ /* this is a no-op function */
+}
+
+
+/* Clipping conventions
+ if the drawable is a window
+ CT_REGION ==> pCompositeClip really is the composite
+ CT_other ==> pCompositeClip is the window clip region
+ if the drawable is a pixmap
+ CT_REGION ==> pCompositeClip is the translated client region
+ clipped to the pixmap boundary
+ CT_other ==> pCompositeClip is the pixmap bounding box
+*/
+
+/*ARGSUSED*/
+void
+mfbValidateGC(pGC, changes, pDrawable)
+ register GCPtr pGC;
+ unsigned long changes;
+ DrawablePtr pDrawable;
+{
+ register mfbPrivGCPtr devPriv;
+ int mask; /* stateChanges */
+ int index; /* used for stepping through bitfields */
+ int xrot, yrot; /* rotations for tile and stipple pattern */
+ int rrop; /* reduced rasterop */
+ /* flags for changing the proc vector
+ and updating things in devPriv
+ */
+ int new_rotate, new_rrop, new_line, new_text, new_fill;
+ DDXPointRec oldOrg; /* origin of thing GC was last used with */
+
+ oldOrg = pGC->lastWinOrg;
+
+ pGC->lastWinOrg.x = pDrawable->x;
+ pGC->lastWinOrg.y = pDrawable->y;
+
+ /* we need to re-rotate the tile if the previous window/pixmap
+ origin (oldOrg) differs from the new window/pixmap origin
+ (pGC->lastWinOrg)
+ */
+ new_rotate = (oldOrg.x != pGC->lastWinOrg.x) ||
+ (oldOrg.y != pGC->lastWinOrg.y);
+
+ devPriv = (mfbPrivGCPtr)dixLookupPrivate(&pGC->devPrivates,
+ mfbGetGCPrivateKey());
+ /*
+ if the client clip is different or moved OR
+ the subwindowMode has changed OR
+ the window's clip has changed since the last validation
+ we need to recompute the composite clip
+ */
+ if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
+ (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
+ )
+ {
+ miComputeCompositeClip(pGC, pDrawable);
+ }
+
+ new_rrop = FALSE;
+ new_line = FALSE;
+ new_text = FALSE;
+ 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 <= PPW) &&
+ !(pGC->tile.pixmap->drawable.width & (pGC->tile.pixmap->drawable.width - 1)))
+ {
+ mfbCopyRotatePixmap(pGC->tile.pixmap,
+ &pGC->pRotatedPixmap, xrot, yrot);
+ new_pix = TRUE;
+ }
+ break;
+ case FillStippled:
+ case FillOpaqueStippled:
+ if (pGC->stipple && (pGC->stipple->drawable.width <= PPW) &&
+ !(pGC->stipple->drawable.width & (pGC->stipple->drawable.width - 1)))
+ {
+ mfbCopyRotatePixmap(pGC->stipple,
+ &pGC->pRotatedPixmap, xrot, yrot);
+ new_pix = TRUE;
+ }
+ }
+ /* destroy any previously rotated tile or stipple */
+ if (!new_pix && pGC->pRotatedPixmap)
+ {
+ (*pDrawable->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
+ pGC->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)
+ miDestroyGCOps (pGC->ops);
+ pGC->ops = newops;
+ new_line = new_fill = new_text = 0;
+ }
+ else
+ {
+ if (!pGC->ops->devPrivate.val)
+ {
+ pGC->ops = miCreateGCOps (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 = mfbPolyGlyphBltNoop;
+ }
+ else
+ {
+ pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
+ }
+ }
+ }
+
+ if (new_fill)
+
+
+ {
+ /* install a suitable fillspans and pushpixels */
+ pGC->ops->PushPixels = mfbPushPixels;
+ pGC->ops->FillPolygon = miFillPolygon;
+ 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;
+ pGC->ops->FillPolygon = mfbFillPolyWhite;
+ break;
+ case RROP_BLACK:
+ pGC->ops->FillSpans = mfbBlackSolidFS;
+ pGC->ops->FillPolygon = mfbFillPolyBlack;
+ break;
+ case RROP_INVERT:
+ pGC->ops->FillSpans = mfbInvertSolidFS;
+ pGC->ops->FillPolygon = mfbFillPolyInvert;
+ break;
+ case RROP_NOP:
+ pGC->ops->FillSpans = mfbNoopFS;
+ pGC->ops->FillPolygon = mfbFillPolyNoop;
+ break;
+ }
+ }
+ /* beyond this point, opaqueStippled ==> fg != bg */
+ else if (((pGC->fillStyle == FillTiled) ||
+ (pGC->fillStyle == FillOpaqueStippled)) &&
+ !pGC->pRotatedPixmap)
+ {
+ pGC->ops->FillSpans = mfbUnnaturalTileFS;
+ }
+ else if ((pGC->fillStyle == FillStippled) && !pGC->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 = mfbNoopFS;
+ 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)) &&
+ !pGC->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 = (mfbFillAreaProcPtr)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 = (mfbFillAreaProcPtr)NoopDDA;
+ break;
+ }
+ }
+ else /* deal with tiles */
+ {
+ switch (pGC->alu)
+ {
+ case GXcopy:
+ devPriv->FillArea = mfbTileAreaPPWCopy;
+ break;
+ default:
+ devPriv->FillArea = mfbTileAreaPPWGeneral;
+ 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
+};
+
+int mfbGetInverseAlu(i)
+ int i;
+{
+ return InverseAlu[i];
+}
+
+int
+mfbReduceRop(alu, src)
+ register int alu;
+ register Pixel src;
+{
+ int rop = 0;
+ 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;
+}