#include "X.h"
#include "Xmd.h"
#include "Xproto.h"
#include "ilbm.h"
#include "dixfontstr.h"
#include "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 ilbmFuncs = {
ilbmValidateGC,
miChangeGC,
miCopyGC,
ilbmDestroyGC,
miChangeClip,
miDestroyClip,
miCopyClip
};
static GCOps ilbmGCOps = {
ilbmSolidFS,
ilbmSetSpans,
ilbmPutImage,
ilbmCopyArea,
miCopyPlane,
ilbmPolyPoint,
ilbmLineSS,
ilbmSegmentSS,
miPolyRectangle,
ilbmZeroPolyArcSS,
ilbmFillPolygonSolid,
ilbmPolyFillRect,
ilbmPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
ilbmTEGlyphBlt,
ilbmPolyGlyphBlt,
ilbmPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
Bool
ilbmCreateGC(pGC)
register GCPtr pGC;
{
ilbmPrivGC *pPriv;
pGC->clientClip = NULL;
pGC->clientClipType = CT_NONE;
pGC->ops = &ilbmGCOps;
pGC->funcs = &ilbmFuncs;
pGC->miTranslate = 1;
pPriv = (ilbmPrivGC *)(pGC->devPrivates[ilbmGCPrivateIndex].ptr);
ilbmReduceRop(pGC->alu, pGC->fgPixel, pGC->planemask, pGC->depth,
pPriv->rrops);
ilbmReduceOpaqueStipple(pGC->fgPixel, pGC->bgPixel, pGC->planemask,
pGC->depth, pPriv->rropOS);
pGC->fExpose = TRUE;
pGC->pRotatedPixmap = NullPixmap;
pGC->freeCompClip = FALSE;
return TRUE;
}
void
ilbmValidateGC(pGC, changes, pDrawable)
register GCPtr pGC;
unsigned long changes;
DrawablePtr pDrawable;
{
register ilbmPrivGCPtr devPriv;
int mask;
int index;
int xrot, yrot;
int rrop;
int new_rotate, new_rrop, new_line, new_text, new_fill;
DDXPointRec oldOrg;
oldOrg = pGC->lastWinOrg;
pGC->lastWinOrg.x = pDrawable->x;
pGC->lastWinOrg.y = pDrawable->y;
new_rotate = (oldOrg.x != pGC->lastWinOrg.x) ||
(oldOrg.y != pGC->lastWinOrg.y);
devPriv = ((ilbmPrivGCPtr)(pGC->devPrivates[ilbmGCPrivateIndex].ptr));
if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)))
ilbmComputeCompositeClip(pGC, pDrawable);
new_rrop = FALSE;
new_line = FALSE;
new_text = FALSE;
new_fill = FALSE;
mask = changes;
while (mask) {
index = lowbit(mask);
mask &= ~index;
switch (index) {
case GCPlaneMask:
case GCFunction:
case GCForeground:
new_rrop = TRUE;
break;
case GCBackground:
new_rrop = TRUE;
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;
}
}
if (new_rotate || new_fill) {
Bool new_pix = FALSE;
xrot = pGC->patOrg.x;
yrot = pGC->patOrg.y;
xrot += pDrawable->x;
yrot += pDrawable->y;
switch (pGC->fillStyle) {
case FillTiled:
if (!pGC->tileIsPixel &&
(pGC->tile.pixmap->drawable.width <= PPW) &&
!(pGC->tile.pixmap->drawable.width &
(pGC->tile.pixmap->drawable.width - 1))) {
ilbmCopyRotatePixmap(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))) {
ilbmCopyRotatePixmap(pGC->stipple, &pGC->pRotatedPixmap,
xrot, yrot);
new_pix = TRUE;
}
}
if (!new_pix && pGC->pRotatedPixmap) {
(*pDrawable->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
pGC->pRotatedPixmap = (PixmapPtr)NULL;
}
}
if (!changes)
return;
if (new_rrop || new_fill) {
ilbmReduceRop(pGC->alu, pGC->fgPixel, pGC->planemask, pDrawable->depth,
devPriv->rrops);
ilbmReduceOpaqueStipple(pGC->fgPixel, pGC->bgPixel, pGC->planemask,
pGC->depth, devPriv->rropOS);
new_fill = TRUE;
}
if (new_line || new_fill || new_text) {
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)
pGC->ops->PolyArc = ilbmZeroPolyArcSS;
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 = ilbmSegmentSS;
pGC->ops->Polylines = ilbmLineSS;
} 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->PolySegment = ilbmSegmentSD;
pGC->ops->Polylines = ilbmLineSD;
} else {
pGC->ops->PolySegment = miPolySegment;
pGC->ops->Polylines = miWideDash;
}
}
}
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 {
if ((pGC->font) &&
TERMINALFONT(pGC->font)) {
pGC->ops->ImageGlyphBlt = ilbmTEGlyphBlt;
} else {
pGC->ops->ImageGlyphBlt = ilbmImageGlyphBlt;
}
if (pGC->fillStyle == FillSolid) {
pGC->ops->PolyGlyphBlt = ilbmPolyGlyphBlt;
} else {
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
}
}
}
if (new_fill) {
pGC->ops->PushPixels = ilbmPushPixels;
pGC->ops->FillPolygon = miFillPolygon;
pGC->ops->PolyFillArc = miPolyFillArc;
switch (pGC->fillStyle) {
case FillSolid:
pGC->ops->FillSpans = ilbmSolidFS;
pGC->ops->FillPolygon = ilbmFillPolygonSolid;
pGC->ops->PolyFillArc = ilbmPolyFillArcSolid;
break;
case FillTiled:
if (pGC->pRotatedPixmap)
pGC->ops->FillSpans = ilbmTileFS;
else
pGC->ops->FillSpans = ilbmUnnaturalTileFS;
break;
case FillOpaqueStippled:
if (pGC->pRotatedPixmap)
pGC->ops->FillSpans = ilbmOpaqueStippleFS;
else
pGC->ops->FillSpans = ilbmUnnaturalOpaqueStippleFS;
break;
case FillStippled:
if (pGC->pRotatedPixmap)
pGC->ops->FillSpans = ilbmStippleFS;
else
pGC->ops->FillSpans = ilbmUnnaturalStippleFS;
break;
}
}
}
void
ilbmDestroyGC(pGC)
GCPtr pGC;
{
if (pGC->pRotatedPixmap)
(*pGC->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
if (pGC->freeCompClip)
REGION_DESTROY(pGC->pScreen, pGC->pCompositeClip);
miDestroyGCOps(pGC->ops);
}
int ilbmInverseAlu[16] = {
GXclear,
GXandInverted,
GXnor,
GXcopyInverted,
GXand,
GXnoop,
GXequiv,
GXorInverted,
GXandReverse,
GXxor,
GXinvert,
GXnand,
GXcopy,
GXor,
GXorReverse,
GXset
};
void
ilbmReduceOpaqueStipple(fg, bg, planemask, depth, rop)
register PixelType fg;
register PixelType bg;
register unsigned long planemask;
int depth;
register unsigned char *rop;
{
register int d;
register Pixel mask = 1;
bg ^= fg;
for (d = 0; d < depth; d++, mask <<= 1) {
if (!(planemask & mask))
rop[d] = RROP_NOP;
else if (!(bg & mask)) {
if (fg & mask)
rop[d] = RROP_WHITE;
else
rop[d] = RROP_BLACK;
} else {
if (fg & mask)
rop[d] = RROP_COPY;
else
rop[d] = RROP_INVERT;
}
}
}
void
ilbmReduceRop(alu, src, planemask, depth, rop)
register int alu;
register Pixel src;
register unsigned long planemask;
int depth;
register unsigned char *rop;
{
register int d;
register Pixel mask = 1;
for (d = 0; d < depth; d++, mask <<= 1) {
if (!(planemask & mask))
rop[d] = RROP_NOP;
else if ((src & mask) == 0)
switch (alu) {
case GXclear:
rop[d] = RROP_BLACK;
break;
case GXand:
rop[d] = RROP_BLACK;
break;
case GXandReverse:
rop[d] = RROP_BLACK;
break;
case GXcopy:
rop[d] = RROP_BLACK;
break;
case GXandInverted:
rop[d] = RROP_NOP;
break;
case GXnoop:
rop[d] = RROP_NOP;
break;
case GXxor:
rop[d] = RROP_NOP;
break;
case GXor:
rop[d] = RROP_NOP;
break;
case GXnor:
rop[d] = RROP_INVERT;
break;
case GXequiv:
rop[d] = RROP_INVERT;
break;
case GXinvert:
rop[d] = RROP_INVERT;
break;
case GXorReverse:
rop[d] = RROP_INVERT;
break;
case GXcopyInverted:
rop[d] = RROP_WHITE;
break;
case GXorInverted:
rop[d] = RROP_WHITE;
break;
case GXnand:
rop[d] = RROP_WHITE;
break;
case GXset:
rop[d] = RROP_WHITE;
break;
}
else
switch (alu) {
case GXclear:
rop[d] = RROP_BLACK;
break;
case GXand:
rop[d] = RROP_NOP;
break;
case GXandReverse:
rop[d] = RROP_INVERT;
break;
case GXcopy:
rop[d] = RROP_WHITE;
break;
case GXandInverted:
rop[d] = RROP_BLACK;
break;
case GXnoop:
rop[d] = RROP_NOP;
break;
case GXxor:
rop[d] = RROP_INVERT;
break;
case GXor:
rop[d] = RROP_WHITE;
break;
case GXnor:
rop[d] = RROP_BLACK;
break;
case GXequiv:
rop[d] = RROP_NOP;
break;
case GXinvert:
rop[d] = RROP_INVERT;
break;
case GXorReverse:
rop[d] = RROP_WHITE;
break;
case GXcopyInverted:
rop[d] = RROP_BLACK;
break;
case GXorInverted:
rop[d] = RROP_NOP;
break;
case GXnand:
rop[d] = RROP_INVERT;
break;
case GXset:
rop[d] = RROP_WHITE;
break;
}
}
}
void
ilbmComputeCompositeClip(pGC, pDrawable)
GCPtr pGC;
DrawablePtr pDrawable;
{
ScreenPtr pScreen = pGC->pScreen;
if (pDrawable->type == DRAWABLE_WINDOW) {
WindowPtr pWin = (WindowPtr) pDrawable;
RegionPtr pregWin;
Bool freeTmpClip, freeCompClip;
if (pGC->subWindowMode == IncludeInferiors) {
pregWin = NotClippedByChildren(pWin);
freeTmpClip = TRUE;
} else {
pregWin = &pWin->clipList;
freeTmpClip = FALSE;
}
freeCompClip = pGC->freeCompClip;
if (pGC->clientClipType == CT_NONE) {
if (freeCompClip)
REGION_DESTROY(pScreen, pGC->pCompositeClip);
pGC->pCompositeClip = pregWin;
pGC->freeCompClip = freeTmpClip;
} else {
REGION_TRANSLATE(pScreen, pGC->clientClip,
pDrawable->x + pGC->clipOrg.x,
pDrawable->y + pGC->clipOrg.y);
if (freeCompClip) {
REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip, pregWin,
pGC->clientClip);
if (freeTmpClip)
REGION_DESTROY(pScreen, pregWin);
} else if (freeTmpClip) {
REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip);
pGC->pCompositeClip = pregWin;
} else {
pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
REGION_INTERSECT(pScreen, pGC->pCompositeClip,
pregWin, pGC->clientClip);
}
pGC->freeCompClip = TRUE;
REGION_TRANSLATE(pScreen, pGC->clientClip,
-(pDrawable->x + pGC->clipOrg.x),
-(pDrawable->y + pGC->clipOrg.y));
}
}
else {
BoxRec pixbounds;
pixbounds.x1 = 0;
pixbounds.y1 = 0;
pixbounds.x2 = pDrawable->width;
pixbounds.y2 = pDrawable->height;
if (pGC->freeCompClip) {
REGION_RESET(pScreen, pGC->pCompositeClip, &pixbounds);
} else {
pGC->freeCompClip = TRUE;
pGC->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1);
}
if (pGC->clientClipType == CT_REGION) {
REGION_TRANSLATE(pScreen, pGC->pCompositeClip, -pGC->clipOrg.x,
-pGC->clipOrg.y);
REGION_INTERSECT(pScreen, pGC->pCompositeClip,
pGC->pCompositeClip, pGC->clientClip);
REGION_TRANSLATE(pScreen, pGC->pCompositeClip, pGC->clipOrg.x,
pGC->clipOrg.y);
}
}
}