#define PSZ 32
#include "leo.h"
#include "leo_regs.h"
#include "leo_gc.h"
#include "X.h"
#include "Xmd.h"
#include "Xproto.h"
#include "cfb.h"
#include "fontstruct.h"
#include "dixfontstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "scrnintstr.h"
#include "region.h"
#include "mistruct.h"
#include "mibstore.h"
#include "migc.h"
#include "cfbmskbits.h"
#include "cfb8bit.h"
void LeoValidateGC(GCPtr, unsigned long, DrawablePtr);
static void LeoDestroyGC(GCPtr);
GCFuncs LeoGCFuncs = {
LeoValidateGC,
miChangeGC,
miCopyGC,
LeoDestroyGC,
miChangeClip,
miDestroyClip,
miCopyClip,
};
GCOps LeoTEOps1Rect = {
cfbSolidSpansCopy,
cfbSetSpans,
cfbPutImage,
LeoCopyArea,
cfbCopyPlane,
cfbPolyPoint,
cfb8LineSS1Rect,
cfb8SegmentSS1Rect,
miPolyRectangle,
cfbZeroPolyArcSS8Copy,
cfbFillPoly1RectCopy,
LeoPolyFillRect1Rect,
cfbPolyFillArcSolidCopy,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
LeoTEGlyphBlt,
LeoPolyTEGlyphBlt,
mfbPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps LeoNonTEOps1Rect = {
cfbSolidSpansCopy,
cfbSetSpans,
cfbPutImage,
LeoCopyArea,
cfbCopyPlane,
cfbPolyPoint,
cfb8LineSS1Rect,
cfb8SegmentSS1Rect,
miPolyRectangle,
cfbZeroPolyArcSS8Copy,
cfbFillPoly1RectCopy,
LeoPolyFillRect1Rect,
cfbPolyFillArcSolidCopy,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
cfbImageGlyphBlt8,
LeoPolyGlyphBlt,
mfbPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps LeoTEOps = {
cfbSolidSpansCopy,
cfbSetSpans,
cfbPutImage,
LeoCopyArea,
cfbCopyPlane,
cfbPolyPoint,
cfbLineSS,
cfbSegmentSS,
miPolyRectangle,
cfbZeroPolyArcSS8Copy,
miFillPolygon,
LeoPolyFillRect,
cfbPolyFillArcSolidCopy,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
LeoTEGlyphBlt,
LeoPolyTEGlyphBlt,
mfbPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps LeoNonTEOps = {
cfbSolidSpansCopy,
cfbSetSpans,
cfbPutImage,
LeoCopyArea,
cfbCopyPlane,
cfbPolyPoint,
cfbLineSS,
cfbSegmentSS,
miPolyRectangle,
cfbZeroPolyArcSS8Copy,
miFillPolygon,
LeoPolyFillRect,
cfbPolyFillArcSolidCopy,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
cfbImageGlyphBlt8,
LeoPolyGlyphBlt,
mfbPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps *
LeoMatchCommon (GCPtr pGC, cfbPrivGCPtr devPriv)
{
if (pGC->lineWidth != 0)
return 0;
if (pGC->lineStyle != LineSolid)
return 0;
if (pGC->fillStyle != FillSolid)
return 0;
if (devPriv->rop != GXcopy)
return 0;
if (pGC->font &&
FONTMAXBOUNDS(pGC->font,rightSideBearing) -
FONTMINBOUNDS(pGC->font,leftSideBearing) <= 32 &&
FONTMINBOUNDS(pGC->font,characterWidth) >= 0) {
if (TERMINALFONT(pGC->font))
if (devPriv->oneRect)
return &LeoTEOps1Rect;
else
return &LeoTEOps;
else
if (devPriv->oneRect)
return &LeoNonTEOps1Rect;
else
return &LeoNonTEOps;
}
return 0;
}
Bool
LeoCreateGC(GCPtr pGC)
{
LeoPrivGCPtr gcPriv;
if (pGC->depth == 1)
return mfbCreateGC (pGC);
if (!cfbCreateGC (pGC))
return FALSE;
pGC->ops = & LeoNonTEOps;
pGC->funcs = & LeoGCFuncs;
gcPriv = LeoGetGCPrivate (pGC);
gcPriv->type = DRAWABLE_WINDOW;
gcPriv->stipple = 0;
return TRUE;
}
static void
LeoDestroyGC (GCPtr pGC)
{
LeoPrivGCPtr gcPriv = LeoGetGCPrivate (pGC);
if (gcPriv->stipple)
xfree (gcPriv->stipple);
miDestroyGC (pGC);
}
void
LeoValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
int mask;
int index;
int new_rrop;
int new_line, new_text, new_fillspans, new_fillarea;
int new_rotate;
int xrot, yrot;
LeoPrivGCPtr gcPriv;
cfbPrivGCPtr devPriv;
int oneRect, type;
LeoPtr pLeo = LeoGetScreenPrivate (pDrawable->pScreen);
gcPriv = LeoGetGCPrivate (pGC);
type = pLeo->vtSema ? -1 : pDrawable->type;
if (type != DRAWABLE_WINDOW) {
if (gcPriv->type == DRAWABLE_WINDOW) {
extern GCOps cfbNonTEOps;
miDestroyGCOps (pGC->ops);
pGC->ops = &cfbNonTEOps;
changes = (1 << (GCLastBit+1)) - 1;
pGC->stateChanges = changes;
gcPriv->type = type;
}
cfbValidateGC (pGC, changes, pDrawable);
return;
}
if (gcPriv->type != DRAWABLE_WINDOW) {
changes = (1 << (GCLastBit+1)) - 1;
gcPriv->type = DRAWABLE_WINDOW;
}
new_rotate = pGC->lastWinOrg.x != pDrawable->x ||
pGC->lastWinOrg.y != pDrawable->y;
pGC->lastWinOrg.x = pDrawable->x;
pGC->lastWinOrg.y = pDrawable->y;
devPriv = cfbGetGCPrivate(pGC);
new_rrop = FALSE;
new_line = FALSE;
new_text = FALSE;
new_fillspans = FALSE;
new_fillarea = FALSE;
if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))) {
miComputeCompositeClip (pGC, pDrawable);
oneRect = REGION_NUM_RECTS(cfbGetCompositeClip(pGC)) == 1;
if (oneRect != devPriv->oneRect)
new_line = TRUE;
devPriv->oneRect = oneRect;
}
mask = changes;
while (mask) {
index = lowbit (mask);
mask &= ~index;
switch (index) {
case GCFunction:
case GCForeground:
new_rrop = TRUE;
break;
case GCPlaneMask:
new_rrop = TRUE;
new_text = TRUE;
break;
case GCBackground:
break;
case GCLineStyle:
case GCLineWidth:
new_line = TRUE;
break;
case GCJoinStyle:
case GCCapStyle:
break;
case GCFillStyle:
new_text = TRUE;
new_fillspans = TRUE;
new_line = TRUE;
new_fillarea = TRUE;
break;
case GCFillRule:
break;
case GCTile:
new_fillspans = TRUE;
new_fillarea = TRUE;
break;
case GCStipple:
if (pGC->stipple) {
int width = pGC->stipple->drawable.width;
PixmapPtr nstipple;
if ((width <= PGSZ) && !(width & (width - 1)) &&
(nstipple = cfbCopyPixmap(pGC->stipple))) {
cfbPadPixmap(nstipple);
(*pGC->pScreen->DestroyPixmap)(pGC->stipple);
pGC->stipple = nstipple;
}
}
new_fillspans = TRUE;
new_fillarea = 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;
}
}
if (pDrawable->serialNumber != (pGC->serialNumber & (DRAWABLE_SERIAL_BITS))) {
new_fillspans = TRUE;
}
if (new_rotate || new_fillspans) {
Bool new_pix = FALSE;
xrot = pGC->patOrg.x + pDrawable->x;
yrot = pGC->patOrg.y + pDrawable->y;
LeoCheckFill (pGC, pDrawable);
switch (pGC->fillStyle) {
case FillTiled:
if (!pGC->tileIsPixel) {
int width = pGC->tile.pixmap->drawable.width * PSZ;
if ((width <= 32) && !(width & (width - 1))) {
cfbCopyRotatePixmap(pGC->tile.pixmap,
&pGC->pRotatedPixmap,
xrot, yrot);
new_pix = TRUE;
}
}
break;
}
if (!new_pix && pGC->pRotatedPixmap) {
(*pGC->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
pGC->pRotatedPixmap = (PixmapPtr) NULL;
}
}
if (new_rrop) {
int old_rrop;
if (gcPriv->stipple) {
if (pGC->fillStyle == FillStippled)
gcPriv->stipple->alu = pGC->alu | 0x80;
else
gcPriv->stipple->alu = pGC->alu;
if (pGC->fillStyle != FillTiled) {
gcPriv->stipple->fg = pGC->fgPixel;
gcPriv->stipple->bg = pGC->bgPixel;
}
}
old_rrop = devPriv->rop;
devPriv->rop = cfbReduceRasterOp (pGC->alu, pGC->fgPixel,
pGC->planemask,
&devPriv->and, &devPriv->xor);
if (old_rrop == devPriv->rop)
new_rrop = FALSE;
else {
new_line = TRUE;
new_text = TRUE;
new_fillspans = TRUE;
new_fillarea = TRUE;
}
}
if (new_rrop || new_fillspans || new_text || new_fillarea || new_line) {
GCOps *newops;
if ((newops = LeoMatchCommon (pGC, devPriv)) != NULL) {
if (pGC->ops->devPrivate.val)
miDestroyGCOps (pGC->ops);
pGC->ops = newops;
new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0;
} else {
if (!pGC->ops->devPrivate.val) {
pGC->ops = miCreateGCOps (pGC->ops);
pGC->ops->devPrivate.val = 1;
}
pGC->ops->CopyArea = LeoCopyArea;
}
}
if (new_line) {
pGC->ops->FillPolygon = miFillPolygon;
if (devPriv->oneRect && pGC->fillStyle == FillSolid) {
switch (devPriv->rop) {
case GXcopy:
pGC->ops->FillPolygon = cfbFillPoly1RectCopy;
break;
default:
pGC->ops->FillPolygon = LeoFillPoly1RectGeneral;
break;
}
}
if (pGC->lineWidth == 0) {
if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)) {
switch (devPriv->rop) {
case GXcopy:
pGC->ops->PolyArc = cfbZeroPolyArcSS8Copy;
break;
default:
pGC->ops->PolyArc = LeoZeroPolyArcSS8General;
break;
}
} else
pGC->ops->PolyArc = miZeroPolyArc;
} else
pGC->ops->PolyArc = miPolyArc;
pGC->ops->PolySegment = miPolySegment;
switch (pGC->lineStyle) {
case LineSolid:
if(pGC->lineWidth == 0) {
if (pGC->fillStyle == FillSolid) {
if (devPriv->oneRect &&
((pDrawable->x >= pGC->pScreen->width - 32768) &&
(pDrawable->y >= pGC->pScreen->height - 32768))) {
pGC->ops->Polylines = cfb8LineSS1Rect;
pGC->ops->PolySegment = cfb8SegmentSS1Rect;
} else {
pGC->ops->Polylines = cfbLineSS;
pGC->ops->PolySegment = cfbSegmentSS;
}
} else
pGC->ops->Polylines = miZeroLine;
} else
pGC->ops->Polylines = miWideLine;
break;
case LineOnOffDash:
case LineDoubleDash:
if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) {
pGC->ops->Polylines = cfbLineSD;
pGC->ops->PolySegment = cfbSegmentSD;
} else
pGC->ops->Polylines = miWideDash;
break;
}
}
if (new_text && pGC->font) {
if (FONTMAXBOUNDS(pGC->font,rightSideBearing) -
FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
FONTMINBOUNDS(pGC->font,characterWidth) < 0) {
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
} else {
if (pGC->fillStyle == FillSolid) {
if (TERMINALFONT (pGC->font))
pGC->ops->PolyGlyphBlt = LeoPolyTEGlyphBlt;
else
pGC->ops->PolyGlyphBlt = LeoPolyGlyphBlt;
} else
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
if (TERMINALFONT (pGC->font))
pGC->ops->ImageGlyphBlt = LeoTEGlyphBlt;
else
pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
}
}
if (new_fillspans) {
switch (pGC->fillStyle) {
case FillSolid:
pGC->ops->FillSpans = LeoFillSpansSolid;
break;
case FillTiled:
if (pGC->pRotatedPixmap) {
if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK)
pGC->ops->FillSpans = cfbTile32FSCopy;
else
pGC->ops->FillSpans = LeoTile32FSGeneral;
} else
pGC->ops->FillSpans = cfbUnnaturalTileFS;
break;
case FillStippled:
pGC->ops->FillSpans = cfbUnnaturalStippleFS;
break;
case FillOpaqueStippled:
pGC->ops->FillSpans = cfbUnnaturalStippleFS;
break;
default:
FatalError("LeoValidateGC: illegal fillStyle\n");
}
if (gcPriv->stipple)
pGC->ops->FillSpans = LeoFillSpansStippled;
}
if (new_fillarea) {
pGC->ops->PolyFillRect = miPolyFillRect;
if (pGC->fillStyle == FillSolid) {
if (devPriv->oneRect)
pGC->ops->PolyFillRect = LeoPolyFillRect1Rect;
else
pGC->ops->PolyFillRect = LeoPolyFillRect;
} else if (gcPriv->stipple)
pGC->ops->PolyFillRect = LeoPolyFillStippledRect;
else if (pGC->fillStyle == FillTiled)
pGC->ops->PolyFillRect = cfbPolyFillRect;
pGC->ops->PolyFillArc = miPolyFillArc;
if (pGC->fillStyle == FillSolid) {
switch (devPriv->rop) {
case GXcopy:
pGC->ops->PolyFillArc = cfbPolyFillArcSolidCopy;
break;
default:
pGC->ops->PolyFillArc = LeoPolyFillArcSolidGeneral;
break;
}
}
}
}