# include "X.h"
# include "Xproto.h"
# include "misc.h"
# include "pixmapstr.h"
# include "input.h"
# include "mi.h"
# include "cursorstr.h"
# include "font.h"
# include "scrnintstr.h"
# include "colormapst.h"
# include "windowstr.h"
# include "gcstruct.h"
# include "mipointer.h"
# include "mispritest.h"
# include "dixfontstr.h"
# include "fontstruct.h"
#ifdef RENDER
# include "mipict.h"
#endif
static int miSpriteScreenIndex;
static unsigned long miSpriteGeneration = 0;
static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen);
static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
int w, int h, unsigned int format,
unsigned long planemask, char *pdstLine);
static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
DDXPointPtr ppt, int *pwidth, int nspans,
char *pdstStart);
static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
int width, int height);
static Bool miSpriteCreateGC(GCPtr pGC);
static void miSpriteBlockHandler(int i, pointer blockData,
pointer pTimeout,
pointer pReadMask);
static void miSpriteInstallColormap(ColormapPtr pMap);
static void miSpriteStoreColors(ColormapPtr pMap, int ndef,
xColorItem *pdef);
static void miSpritePaintWindowBackground(WindowPtr pWin,
RegionPtr pRegion, int what);
static void miSpritePaintWindowBorder(WindowPtr pWin,
RegionPtr pRegion, int what);
static void miSpriteCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
RegionPtr pRegion);
static void miSpriteClearToBackground(WindowPtr pWin, int x, int y,
int w, int h,
Bool generateExposures);
#ifdef RENDER
static void miSpriteComposite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
static void miSpriteGlyphs(CARD8 op,
PicturePtr pSrc,
PicturePtr pDst,
PictFormatPtr maskFormat,
INT16 xSrc,
INT16 ySrc,
int nlist,
GlyphListPtr list,
GlyphPtr *glyphs);
#endif
static void miSpriteSaveDoomedAreas(WindowPtr pWin,
RegionPtr pObscured, int dx,
int dy);
static RegionPtr miSpriteRestoreAreas(WindowPtr pWin, RegionPtr pRgnExposed);
static void miSpriteComputeSaved(ScreenPtr pScreen);
#define SCREEN_PROLOGUE(pScreen, field)\
((pScreen)->field = \
((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
((pScreen)->field = wrapper)
static int miSpriteGCIndex;
static void miSpriteValidateGC(GCPtr pGC, unsigned long stateChanges,
DrawablePtr pDrawable);
static void miSpriteCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
static void miSpriteDestroyGC(GCPtr pGC);
static void miSpriteChangeGC(GCPtr pGC, unsigned long mask);
static void miSpriteChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
static void miSpriteDestroyClip(GCPtr pGC);
static void miSpriteCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
static GCFuncs miSpriteGCFuncs = {
miSpriteValidateGC,
miSpriteChangeGC,
miSpriteCopyGC,
miSpriteDestroyGC,
miSpriteChangeClip,
miSpriteDestroyClip,
miSpriteCopyClip,
};
#define GC_FUNC_PROLOGUE(pGC) \
miSpriteGCPtr pGCPriv = \
(miSpriteGCPtr) (pGC)->devPrivates[miSpriteGCIndex].ptr;\
(pGC)->funcs = pGCPriv->wrapFuncs; \
if (pGCPriv->wrapOps) \
(pGC)->ops = pGCPriv->wrapOps;
#define GC_FUNC_EPILOGUE(pGC) \
pGCPriv->wrapFuncs = (pGC)->funcs; \
(pGC)->funcs = &miSpriteGCFuncs; \
if (pGCPriv->wrapOps) \
{ \
pGCPriv->wrapOps = (pGC)->ops; \
(pGC)->ops = &miSpriteGCOps; \
}
static void miSpriteFillSpans(DrawablePtr pDrawable, GCPtr pGC,
int nInit, DDXPointPtr pptInit,
int *pwidthInit, int fSorted);
static void miSpriteSetSpans(DrawablePtr pDrawable, GCPtr pGC,
char *psrc, DDXPointPtr ppt, int *pwidth,
int nspans, int fSorted);
static void miSpritePutImage(DrawablePtr pDrawable, GCPtr pGC,
int depth, int x, int y, int w, int h,
int leftPad, int format, char *pBits);
static RegionPtr miSpriteCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
GCPtr pGC, int srcx, int srcy, int w,
int h, int dstx, int dsty);
static RegionPtr miSpriteCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
GCPtr pGC, int srcx, int srcy, int w,
int h, int dstx, int dsty,
unsigned long plane);
static void miSpritePolyPoint(DrawablePtr pDrawable, GCPtr pGC,
int mode, int npt, xPoint *pptInit);
static void miSpritePolylines(DrawablePtr pDrawable, GCPtr pGC,
int mode, int npt, DDXPointPtr pptInit);
static void miSpritePolySegment(DrawablePtr pDrawable, GCPtr pGC,
int nseg, xSegment *pSegs);
static void miSpritePolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
int nrects, xRectangle *pRects);
static void miSpritePolyArc(DrawablePtr pDrawable, GCPtr pGC,
int narcs, xArc *parcs);
static void miSpriteFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
int shape, int mode, int count,
DDXPointPtr pPts);
static void miSpritePolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
int nrectFill, xRectangle *prectInit);
static void miSpritePolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
int narcs, xArc *parcs);
static int miSpritePolyText8(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count, char *chars);
static int miSpritePolyText16(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count,
unsigned short *chars);
static void miSpriteImageText8(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count, char *chars);
static void miSpriteImageText16(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count,
unsigned short *chars);
static void miSpriteImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci,
pointer pglyphBase);
static void miSpritePolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci,
pointer pglyphBase);
static void miSpritePushPixels(GCPtr pGC, PixmapPtr pBitMap,
DrawablePtr pDst, int w, int h,
int x, int y);
#ifdef NEED_LINEHELPER
static void miSpriteLineHelper(void);
#endif
static GCOps miSpriteGCOps = {
miSpriteFillSpans, miSpriteSetSpans, miSpritePutImage,
miSpriteCopyArea, miSpriteCopyPlane, miSpritePolyPoint,
miSpritePolylines, miSpritePolySegment, miSpritePolyRectangle,
miSpritePolyArc, miSpriteFillPolygon, miSpritePolyFillRect,
miSpritePolyFillArc, miSpritePolyText8, miSpritePolyText16,
miSpriteImageText8, miSpriteImageText16, miSpriteImageGlyphBlt,
miSpritePolyGlyphBlt, miSpritePushPixels
#ifdef NEED_LINEHELPER
, miSpriteLineHelper
#endif
};
#define GC_SETUP_CHEAP(pDrawable) \
miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr) \
(pDrawable)->pScreen->devPrivates[miSpriteScreenIndex].ptr; \
#define GC_SETUP(pDrawable, pGC) \
GC_SETUP_CHEAP(pDrawable) \
miSpriteGCPtr pGCPrivate = (miSpriteGCPtr) \
(pGC)->devPrivates[miSpriteGCIndex].ptr; \
GCFuncs *oldFuncs = pGC->funcs;
#define GC_SETUP_AND_CHECK(pDrawable, pGC) \
GC_SETUP(pDrawable, pGC); \
if (GC_CHECK((WindowPtr)pDrawable)) \
miSpriteRemoveCursor (pDrawable->pScreen);
#define GC_CHECK(pWin) \
(pScreenPriv->isUp && \
(pScreenPriv->pCacheWin == pWin ? \
pScreenPriv->isInCacheWin : ( \
(pScreenPriv->pCacheWin = (pWin)), \
(pScreenPriv->isInCacheWin = \
(pWin)->drawable.x < pScreenPriv->saved.x2 && \
pScreenPriv->saved.x1 < (pWin)->drawable.x + \
(int) (pWin)->drawable.width && \
(pWin)->drawable.y < pScreenPriv->saved.y2 && \
pScreenPriv->saved.y1 < (pWin)->drawable.y + \
(int) (pWin)->drawable.height &&\
RECT_IN_REGION((pWin)->drawable.pScreen, &(pWin)->borderClip, \
&pScreenPriv->saved) != rgnOUT))))
#define GC_OP_PROLOGUE(pGC) { \
(pGC)->funcs = pGCPrivate->wrapFuncs; \
(pGC)->ops = pGCPrivate->wrapOps; \
}
#define GC_OP_EPILOGUE(pGC) { \
pGCPrivate->wrapOps = (pGC)->ops; \
(pGC)->funcs = oldFuncs; \
(pGC)->ops = &miSpriteGCOps; \
}
static Bool miSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor,
int x, int y);
static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y);
miPointerSpriteFuncRec miSpritePointerFuncs = {
miSpriteRealizeCursor,
miSpriteUnrealizeCursor,
miSpriteSetCursor,
miSpriteMoveCursor,
};
static void miSpriteRemoveCursor(ScreenPtr pScreen);
static void miSpriteRestoreCursor(ScreenPtr pScreen);
Bool
miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
ScreenPtr pScreen;
miSpriteCursorFuncPtr cursorFuncs;
miPointerScreenFuncPtr screenFuncs;
{
miSpriteScreenPtr pPriv;
VisualPtr pVisual;
#ifdef RENDER
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
if (miSpriteGeneration != serverGeneration)
{
miSpriteScreenIndex = AllocateScreenPrivateIndex ();
if (miSpriteScreenIndex < 0)
return FALSE;
miSpriteGeneration = serverGeneration;
miSpriteGCIndex = AllocateGCPrivateIndex ();
}
if (!AllocateGCPrivate(pScreen, miSpriteGCIndex, sizeof(miSpriteGCRec)))
return FALSE;
pPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec));
if (!pPriv)
return FALSE;
if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
{
xfree ((pointer) pPriv);
return FALSE;
}
for (pVisual = pScreen->visuals;
pVisual->vid != pScreen->rootVisual;
pVisual++)
;
pPriv->pVisual = pVisual;
pPriv->CloseScreen = pScreen->CloseScreen;
pPriv->GetImage = pScreen->GetImage;
pPriv->GetSpans = pScreen->GetSpans;
pPriv->SourceValidate = pScreen->SourceValidate;
pPriv->CreateGC = pScreen->CreateGC;
pPriv->BlockHandler = pScreen->BlockHandler;
pPriv->InstallColormap = pScreen->InstallColormap;
pPriv->StoreColors = pScreen->StoreColors;
pPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
pPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
pPriv->CopyWindow = pScreen->CopyWindow;
pPriv->ClearToBackground = pScreen->ClearToBackground;
pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
pPriv->RestoreAreas = pScreen->RestoreAreas;
#ifdef RENDER
if (ps)
{
pPriv->Composite = ps->Composite;
pPriv->Glyphs = ps->Glyphs;
}
#endif
pPriv->pCursor = NULL;
pPriv->x = 0;
pPriv->y = 0;
pPriv->isUp = FALSE;
pPriv->shouldBeUp = FALSE;
pPriv->pCacheWin = NullWindow;
pPriv->isInCacheWin = FALSE;
pPriv->checkPixels = TRUE;
pPriv->pInstalledMap = NULL;
pPriv->pColormap = NULL;
pPriv->funcs = cursorFuncs;
pPriv->colors[SOURCE_COLOR].red = 0;
pPriv->colors[SOURCE_COLOR].green = 0;
pPriv->colors[SOURCE_COLOR].blue = 0;
pPriv->colors[MASK_COLOR].red = 0;
pPriv->colors[MASK_COLOR].green = 0;
pPriv->colors[MASK_COLOR].blue = 0;
pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pPriv;
pScreen->CloseScreen = miSpriteCloseScreen;
pScreen->GetImage = miSpriteGetImage;
pScreen->GetSpans = miSpriteGetSpans;
pScreen->SourceValidate = miSpriteSourceValidate;
pScreen->CreateGC = miSpriteCreateGC;
pScreen->BlockHandler = miSpriteBlockHandler;
pScreen->InstallColormap = miSpriteInstallColormap;
pScreen->StoreColors = miSpriteStoreColors;
pScreen->PaintWindowBackground = miSpritePaintWindowBackground;
pScreen->PaintWindowBorder = miSpritePaintWindowBorder;
pScreen->CopyWindow = miSpriteCopyWindow;
pScreen->ClearToBackground = miSpriteClearToBackground;
pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
pScreen->RestoreAreas = miSpriteRestoreAreas;
#ifdef RENDER
if (ps)
{
ps->Composite = miSpriteComposite;
ps->Glyphs = miSpriteGlyphs;
}
#endif
return TRUE;
}
static Bool
miSpriteCloseScreen (i, pScreen)
int i;
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
#ifdef RENDER
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pScreen->CloseScreen = pScreenPriv->CloseScreen;
pScreen->GetImage = pScreenPriv->GetImage;
pScreen->GetSpans = pScreenPriv->GetSpans;
pScreen->SourceValidate = pScreenPriv->SourceValidate;
pScreen->CreateGC = pScreenPriv->CreateGC;
pScreen->BlockHandler = pScreenPriv->BlockHandler;
pScreen->InstallColormap = pScreenPriv->InstallColormap;
pScreen->StoreColors = pScreenPriv->StoreColors;
pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground;
pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder;
pScreen->CopyWindow = pScreenPriv->CopyWindow;
pScreen->ClearToBackground = pScreenPriv->ClearToBackground;
pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
pScreen->RestoreAreas = pScreenPriv->RestoreAreas;
#ifdef RENDER
if (ps)
{
ps->Composite = pScreenPriv->Composite;
ps->Glyphs = pScreenPriv->Glyphs;
}
#endif
xfree ((pointer) pScreenPriv);
return (*pScreen->CloseScreen) (i, pScreen);
}
static void
miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
DrawablePtr pDrawable;
int sx, sy, w, h;
unsigned int format;
unsigned long planemask;
char *pdstLine;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, GetImage);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW &&
pScreenPriv->isUp &&
ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
{
miSpriteRemoveCursor (pScreen);
}
(*pScreen->GetImage) (pDrawable, sx, sy, w, h,
format, planemask, pdstLine);
SCREEN_EPILOGUE (pScreen, GetImage, miSpriteGetImage);
}
static void
miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
DrawablePtr pDrawable;
int wMax;
DDXPointPtr ppt;
int *pwidth;
int nspans;
char *pdstStart;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, GetSpans);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
{
register DDXPointPtr pts;
register int *widths;
register int nPts;
register int xorg,
yorg;
xorg = pDrawable->x;
yorg = pDrawable->y;
for (pts = ppt, widths = pwidth, nPts = nspans;
nPts--;
pts++, widths++)
{
if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
pts->x+xorg,*widths))
{
miSpriteRemoveCursor (pScreen);
break;
}
}
}
(*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
SCREEN_EPILOGUE (pScreen, GetSpans, miSpriteGetSpans);
}
static void
miSpriteSourceValidate (pDrawable, x, y, width, height)
DrawablePtr pDrawable;
int x, y, width, height;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, SourceValidate);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
x, y, width, height))
{
miSpriteRemoveCursor (pScreen);
}
if (pScreen->SourceValidate)
(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
SCREEN_EPILOGUE (pScreen, SourceValidate, miSpriteSourceValidate);
}
static Bool
miSpriteCreateGC (pGC)
GCPtr pGC;
{
ScreenPtr pScreen = pGC->pScreen;
Bool ret;
miSpriteGCPtr pPriv;
SCREEN_PROLOGUE (pScreen, CreateGC);
pPriv = (miSpriteGCPtr)pGC->devPrivates[miSpriteGCIndex].ptr;
ret = (*pScreen->CreateGC) (pGC);
pPriv->wrapOps = NULL;
pPriv->wrapFuncs = pGC->funcs;
pGC->funcs = &miSpriteGCFuncs;
SCREEN_EPILOGUE (pScreen, CreateGC, miSpriteCreateGC);
return ret;
}
static void
miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
int i;
pointer blockData;
pointer pTimeout;
pointer pReadmask;
{
ScreenPtr pScreen = screenInfo.screens[i];
miSpriteScreenPtr pPriv;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, BlockHandler);
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
SCREEN_EPILOGUE(pScreen, BlockHandler, miSpriteBlockHandler);
if (!pPriv->isUp && pPriv->shouldBeUp)
miSpriteRestoreCursor (pScreen);
}
static void
miSpriteInstallColormap (pMap)
ColormapPtr pMap;
{
ScreenPtr pScreen = pMap->pScreen;
miSpriteScreenPtr pPriv;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, InstallColormap);
(*pScreen->InstallColormap) (pMap);
SCREEN_EPILOGUE(pScreen, InstallColormap, miSpriteInstallColormap);
pPriv->pInstalledMap = pMap;
if (pPriv->pColormap != pMap)
{
pPriv->checkPixels = TRUE;
if (pPriv->isUp)
miSpriteRemoveCursor (pScreen);
}
}
static void
miSpriteStoreColors (pMap, ndef, pdef)
ColormapPtr pMap;
int ndef;
xColorItem *pdef;
{
ScreenPtr pScreen = pMap->pScreen;
miSpriteScreenPtr pPriv;
int i;
int updated;
VisualPtr pVisual;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, StoreColors);
(*pScreen->StoreColors) (pMap, ndef, pdef);
SCREEN_EPILOGUE(pScreen, StoreColors, miSpriteStoreColors);
if (pPriv->pColormap == pMap)
{
updated = 0;
pVisual = pMap->pVisual;
if (pVisual->class == DirectColor)
{
#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
#define UpdateDAC(plane,dac,mask) {\
if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\
pPriv->colors[plane].dac = pdef[i].dac; \
updated = 1; \
} \
}
#define CheckDirect(plane) \
UpdateDAC(plane,red,redMask) \
UpdateDAC(plane,green,greenMask) \
UpdateDAC(plane,blue,blueMask)
for (i = 0; i < ndef; i++)
{
CheckDirect (SOURCE_COLOR)
CheckDirect (MASK_COLOR)
}
}
else
{
for (i = 0; i < ndef; i++)
{
if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel)
{
pPriv->colors[SOURCE_COLOR] = pdef[i];
if (++updated == 2)
break;
}
if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
{
pPriv->colors[MASK_COLOR] = pdef[i];
if (++updated == 2)
break;
}
}
}
if (updated)
{
pPriv->checkPixels = TRUE;
if (pPriv->isUp)
miSpriteRemoveCursor (pScreen);
}
}
}
static void
miSpriteFindColors (ScreenPtr pScreen)
{
miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr)
pScreen->devPrivates[miSpriteScreenIndex].ptr;
CursorPtr pCursor;
xColorItem *sourceColor, *maskColor;
pCursor = pScreenPriv->pCursor;
sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
maskColor = &pScreenPriv->colors[MASK_COLOR];
if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
!(pCursor->foreRed == sourceColor->red &&
pCursor->foreGreen == sourceColor->green &&
pCursor->foreBlue == sourceColor->blue &&
pCursor->backRed == maskColor->red &&
pCursor->backGreen == maskColor->green &&
pCursor->backBlue == maskColor->blue))
{
pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
sourceColor->red = pCursor->foreRed;
sourceColor->green = pCursor->foreGreen;
sourceColor->blue = pCursor->foreBlue;
FakeAllocColor (pScreenPriv->pColormap, sourceColor);
maskColor->red = pCursor->backRed;
maskColor->green = pCursor->backGreen;
maskColor->blue = pCursor->backBlue;
FakeAllocColor (pScreenPriv->pColormap, maskColor);
FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
}
pScreenPriv->checkPixels = FALSE;
}
static void
miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
WindowPtr pWin;
RegionPtr pObscured;
int dx, dy;
{
ScreenPtr pScreen;
miSpriteScreenPtr pScreenPriv;
BoxRec cursorBox;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pScreenPriv->isUp)
{
cursorBox = pScreenPriv->saved;
if (dx || dy)
{
cursorBox.x1 += dx;
cursorBox.y1 += dy;
cursorBox.x2 += dx;
cursorBox.y2 += dy;
}
if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
miSpriteRemoveCursor (pScreen);
}
(*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, miSpriteSaveDoomedAreas);
}
static RegionPtr
miSpriteRestoreAreas (pWin, prgnExposed)
WindowPtr pWin;
RegionPtr prgnExposed;
{
ScreenPtr pScreen;
miSpriteScreenPtr pScreenPriv;
RegionPtr result;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, RestoreAreas);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pScreenPriv->isUp)
{
if (RECT_IN_REGION( pScreen, prgnExposed, &pScreenPriv->saved) != rgnOUT)
miSpriteRemoveCursor (pScreen);
}
result = (*pScreen->RestoreAreas) (pWin, prgnExposed);
SCREEN_EPILOGUE (pScreen, RestoreAreas, miSpriteRestoreAreas);
return result;
}
static void
miSpritePaintWindowBackground (pWin, pRegion, what)
WindowPtr pWin;
RegionPtr pRegion;
int what;
{
ScreenPtr pScreen;
miSpriteScreenPtr pScreenPriv;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, PaintWindowBackground);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pScreenPriv->isUp)
{
if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
miSpriteRemoveCursor (pScreen);
}
(*pScreen->PaintWindowBackground) (pWin, pRegion, what);
SCREEN_EPILOGUE (pScreen, PaintWindowBackground, miSpritePaintWindowBackground);
}
static void
miSpritePaintWindowBorder (pWin, pRegion, what)
WindowPtr pWin;
RegionPtr pRegion;
int what;
{
ScreenPtr pScreen;
miSpriteScreenPtr pScreenPriv;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, PaintWindowBorder);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pScreenPriv->isUp)
{
if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
miSpriteRemoveCursor (pScreen);
}
(*pScreen->PaintWindowBorder) (pWin, pRegion, what);
SCREEN_EPILOGUE (pScreen, PaintWindowBorder, miSpritePaintWindowBorder);
}
static void
miSpriteCopyWindow (pWin, ptOldOrg, pRegion)
WindowPtr pWin;
DDXPointRec ptOldOrg;
RegionPtr pRegion;
{
ScreenPtr pScreen;
miSpriteScreenPtr pScreenPriv;
BoxRec cursorBox;
int dx, dy;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, CopyWindow);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pScreenPriv->isUp)
{
cursorBox = pScreenPriv->saved;
dx = pWin->drawable.x - ptOldOrg.x;
dy = pWin->drawable.y - ptOldOrg.y;
cursorBox.x1 -= dx;
cursorBox.x2 -= dx;
cursorBox.y1 -= dy;
cursorBox.y2 -= dy;
if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT ||
RECT_IN_REGION( pScreen, pRegion, &cursorBox) != rgnOUT)
miSpriteRemoveCursor (pScreen);
}
(*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion);
SCREEN_EPILOGUE (pScreen, CopyWindow, miSpriteCopyWindow);
}
static void
miSpriteClearToBackground (pWin, x, y, w, h, generateExposures)
WindowPtr pWin;
int x,y;
int w,h;
Bool generateExposures;
{
ScreenPtr pScreen;
miSpriteScreenPtr pScreenPriv;
int realw, realh;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, ClearToBackground);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (GC_CHECK(pWin))
{
if (!(realw = w))
realw = (int) pWin->drawable.width - x;
if (!(realh = h))
realh = (int) pWin->drawable.height - y;
if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y,
x, y, realw, realh))
{
miSpriteRemoveCursor (pScreen);
}
}
(*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
SCREEN_EPILOGUE (pScreen, ClearToBackground, miSpriteClearToBackground);
}
static void
miSpriteValidateGC (pGC, changes, pDrawable)
GCPtr pGC;
unsigned long changes;
DrawablePtr pDrawable;
{
GC_FUNC_PROLOGUE (pGC);
(*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
pGCPriv->wrapOps = NULL;
if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable)
{
WindowPtr pWin;
RegionPtr pRegion;
pWin = (WindowPtr) pDrawable;
pRegion = &pWin->clipList;
if (pGC->subWindowMode == IncludeInferiors)
pRegion = &pWin->borderClip;
if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion))
pGCPriv->wrapOps = pGC->ops;
}
GC_FUNC_EPILOGUE (pGC);
}
static void
miSpriteChangeGC (pGC, mask)
GCPtr pGC;
unsigned long mask;
{
GC_FUNC_PROLOGUE (pGC);
(*pGC->funcs->ChangeGC) (pGC, mask);
GC_FUNC_EPILOGUE (pGC);
}
static void
miSpriteCopyGC (pGCSrc, mask, pGCDst)
GCPtr pGCSrc, pGCDst;
unsigned long mask;
{
GC_FUNC_PROLOGUE (pGCDst);
(*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
GC_FUNC_EPILOGUE (pGCDst);
}
static void
miSpriteDestroyGC (pGC)
GCPtr pGC;
{
GC_FUNC_PROLOGUE (pGC);
(*pGC->funcs->DestroyGC) (pGC);
GC_FUNC_EPILOGUE (pGC);
}
static void
miSpriteChangeClip (pGC, type, pvalue, nrects)
GCPtr pGC;
int type;
pointer pvalue;
int nrects;
{
GC_FUNC_PROLOGUE (pGC);
(*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
GC_FUNC_EPILOGUE (pGC);
}
static void
miSpriteCopyClip(pgcDst, pgcSrc)
GCPtr pgcDst, pgcSrc;
{
GC_FUNC_PROLOGUE (pgcDst);
(* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
GC_FUNC_EPILOGUE (pgcDst);
}
static void
miSpriteDestroyClip(pGC)
GCPtr pGC;
{
GC_FUNC_PROLOGUE (pGC);
(* pGC->funcs->DestroyClip)(pGC);
GC_FUNC_EPILOGUE (pGC);
}
static void
miSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
DrawablePtr pDrawable;
GCPtr pGC;
int nInit;
DDXPointPtr pptInit;
int *pwidthInit;
int fSorted;
{
GC_SETUP(pDrawable, pGC);
if (GC_CHECK((WindowPtr) pDrawable))
{
register DDXPointPtr pts;
register int *widths;
register int nPts;
for (pts = pptInit, widths = pwidthInit, nPts = nInit;
nPts--;
pts++, widths++)
{
if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
{
miSpriteRemoveCursor (pDrawable->pScreen);
break;
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
GC_OP_EPILOGUE (pGC);
}
static void
miSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
DrawablePtr pDrawable;
GCPtr pGC;
char *psrc;
register DDXPointPtr ppt;
int *pwidth;
int nspans;
int fSorted;
{
GC_SETUP(pDrawable, pGC);
if (GC_CHECK((WindowPtr) pDrawable))
{
register DDXPointPtr pts;
register int *widths;
register int nPts;
for (pts = ppt, widths = pwidth, nPts = nspans;
nPts--;
pts++, widths++)
{
if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
{
miSpriteRemoveCursor(pDrawable->pScreen);
break;
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
DrawablePtr pDrawable;
GCPtr pGC;
int depth;
int x;
int y;
int w;
int h;
int leftPad;
int format;
char *pBits;
{
GC_SETUP(pDrawable, pGC);
if (GC_CHECK((WindowPtr) pDrawable))
{
if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,
x,y,w,h))
{
miSpriteRemoveCursor (pDrawable->pScreen);
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits);
GC_OP_EPILOGUE (pGC);
}
static RegionPtr
miSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
DrawablePtr pSrc;
DrawablePtr pDst;
GCPtr pGC;
int srcx;
int srcy;
int w;
int h;
int dstx;
int dsty;
{
RegionPtr rgn;
GC_SETUP(pDst, pGC);
if (GC_CHECK((WindowPtr) pDst) &&
(ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
((pDst == pSrc) &&
ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
{
miSpriteRemoveCursor (pDst->pScreen);
}
GC_OP_PROLOGUE (pGC);
rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
dstx, dsty);
GC_OP_EPILOGUE (pGC);
return rgn;
}
static RegionPtr
miSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
DrawablePtr pSrc;
DrawablePtr pDst;
register GCPtr pGC;
int srcx,
srcy;
int w,
h;
int dstx,
dsty;
unsigned long plane;
{
RegionPtr rgn;
GC_SETUP(pDst, pGC);
if (GC_CHECK((WindowPtr) pDst) &&
(ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
((pDst == pSrc) &&
ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
{
miSpriteRemoveCursor (pDst->pScreen);
}
GC_OP_PROLOGUE (pGC);
rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
dstx, dsty, plane);
GC_OP_EPILOGUE (pGC);
return rgn;
}
static void
miSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit)
DrawablePtr pDrawable;
GCPtr pGC;
int mode;
int npt;
xPoint *pptInit;
{
xPoint t;
int n;
BoxRec cursor;
register xPoint *pts;
GC_SETUP (pDrawable, pGC);
if (npt && GC_CHECK((WindowPtr) pDrawable))
{
cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x;
cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y;
cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x;
cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y;
if (mode == CoordModePrevious)
{
t.x = 0;
t.y = 0;
for (pts = pptInit, n = npt; n--; pts++)
{
t.x += pts->x;
t.y += pts->y;
if (cursor.x1 <= t.x && t.x <= cursor.x2 &&
cursor.y1 <= t.y && t.y <= cursor.y2)
{
miSpriteRemoveCursor (pDrawable->pScreen);
break;
}
}
}
else
{
for (pts = pptInit, n = npt; n--; pts++)
{
if (cursor.x1 <= pts->x && pts->x <= cursor.x2 &&
cursor.y1 <= pts->y && pts->y <= cursor.y2)
{
miSpriteRemoveCursor (pDrawable->pScreen);
break;
}
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePolylines (pDrawable, pGC, mode, npt, pptInit)
DrawablePtr pDrawable;
GCPtr pGC;
int mode;
int npt;
DDXPointPtr pptInit;
{
BoxPtr cursor;
register DDXPointPtr pts;
int n;
int x, y, x1, y1, x2, y2;
int lw;
int extra;
GC_SETUP (pDrawable, pGC);
if (npt && GC_CHECK((WindowPtr) pDrawable))
{
cursor = &pScreenPriv->saved;
lw = pGC->lineWidth;
x = pptInit->x + pDrawable->x;
y = pptInit->y + pDrawable->y;
if (npt == 1)
{
extra = lw >> 1;
if (LINE_OVERLAP(cursor, x, y, x, y, extra))
miSpriteRemoveCursor (pDrawable->pScreen);
}
else
{
extra = lw >> 1;
if (pGC->joinStyle == JoinMiter)
extra = 6 * lw;
else if (pGC->capStyle == CapProjecting)
extra = lw;
for (pts = pptInit + 1, n = npt - 1; n--; pts++)
{
x1 = x;
y1 = y;
if (mode == CoordModeOrigin)
{
x2 = pDrawable->x + pts->x;
y2 = pDrawable->y + pts->y;
}
else
{
x2 = x + pts->x;
y2 = y + pts->y;
}
x = x2;
y = y2;
LINE_SORT(x1, y1, x2, y2);
if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
{
miSpriteRemoveCursor (pDrawable->pScreen);
break;
}
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePolySegment(pDrawable, pGC, nseg, pSegs)
DrawablePtr pDrawable;
GCPtr pGC;
int nseg;
xSegment *pSegs;
{
int n;
register xSegment *segs;
BoxPtr cursor;
int x1, y1, x2, y2;
int extra;
GC_SETUP(pDrawable, pGC);
if (nseg && GC_CHECK((WindowPtr) pDrawable))
{
cursor = &pScreenPriv->saved;
extra = pGC->lineWidth >> 1;
if (pGC->capStyle == CapProjecting)
extra = pGC->lineWidth;
for (segs = pSegs, n = nseg; n--; segs++)
{
x1 = segs->x1 + pDrawable->x;
y1 = segs->y1 + pDrawable->y;
x2 = segs->x2 + pDrawable->x;
y2 = segs->y2 + pDrawable->y;
LINE_SORT(x1, y1, x2, y2);
if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
{
miSpriteRemoveCursor (pDrawable->pScreen);
break;
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePolyRectangle(pDrawable, pGC, nrects, pRects)
DrawablePtr pDrawable;
GCPtr pGC;
int nrects;
xRectangle *pRects;
{
register xRectangle *rects;
BoxPtr cursor;
int lw;
int n;
int x1, y1, x2, y2;
GC_SETUP (pDrawable, pGC);
if (GC_CHECK((WindowPtr) pDrawable))
{
lw = pGC->lineWidth >> 1;
cursor = &pScreenPriv->saved;
for (rects = pRects, n = nrects; n--; rects++)
{
x1 = rects->x + pDrawable->x;
y1 = rects->y + pDrawable->y;
x2 = x1 + (int)rects->width;
y2 = y1 + (int)rects->height;
if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) ||
LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) ||
LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) ||
LINE_OVERLAP(cursor, x1, y1, x1, y2, lw))
{
miSpriteRemoveCursor (pDrawable->pScreen);
break;
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePolyArc(pDrawable, pGC, narcs, parcs)
DrawablePtr pDrawable;
register GCPtr pGC;
int narcs;
xArc *parcs;
{
BoxPtr cursor;
int lw;
int n;
register xArc *arcs;
GC_SETUP (pDrawable, pGC);
if (GC_CHECK((WindowPtr) pDrawable))
{
lw = pGC->lineWidth >> 1;
cursor = &pScreenPriv->saved;
for (arcs = parcs, n = narcs; n--; arcs++)
{
if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y,
arcs->x - lw, arcs->y - lw,
(int) arcs->width + pGC->lineWidth,
(int) arcs->height + pGC->lineWidth))
{
miSpriteRemoveCursor (pDrawable->pScreen);
break;
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs);
GC_OP_EPILOGUE (pGC);
}
static void
miSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
register DrawablePtr pDrawable;
register GCPtr pGC;
int shape, mode;
int count;
DDXPointPtr pPts;
{
int x, y, minx, miny, maxx, maxy;
register DDXPointPtr pts;
int n;
GC_SETUP (pDrawable, pGC);
if (count && GC_CHECK((WindowPtr) pDrawable))
{
x = pDrawable->x;
y = pDrawable->y;
pts = pPts;
minx = maxx = pts->x;
miny = maxy = pts->y;
pts++;
n = count - 1;
if (mode == CoordModeOrigin)
{
for (; n--; pts++)
{
if (pts->x < minx)
minx = pts->x;
else if (pts->x > maxx)
maxx = pts->x;
if (pts->y < miny)
miny = pts->y;
else if (pts->y > maxy)
maxy = pts->y;
}
minx += x;
miny += y;
maxx += x;
maxy += y;
}
else
{
x += minx;
y += miny;
minx = maxx = x;
miny = maxy = y;
for (; n--; pts++)
{
x += pts->x;
y += pts->y;
if (x < minx)
minx = x;
else if (x > maxx)
maxx = x;
if (y < miny)
miny = y;
else if (y > maxy)
maxy = y;
}
}
if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy))
miSpriteRemoveCursor (pDrawable->pScreen);
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit)
DrawablePtr pDrawable;
GCPtr pGC;
int nrectFill;
xRectangle *prectInit;
{
GC_SETUP(pDrawable, pGC);
if (GC_CHECK((WindowPtr) pDrawable))
{
register int nRect;
register xRectangle *pRect;
register int xorg, yorg;
xorg = pDrawable->x;
yorg = pDrawable->y;
for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) {
if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){
miSpriteRemoveCursor(pDrawable->pScreen);
break;
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePolyFillArc(pDrawable, pGC, narcs, parcs)
DrawablePtr pDrawable;
GCPtr pGC;
int narcs;
xArc *parcs;
{
GC_SETUP(pDrawable, pGC);
if (GC_CHECK((WindowPtr) pDrawable))
{
register int n;
BoxPtr cursor;
register xArc *arcs;
cursor = &pScreenPriv->saved;
for (arcs = parcs, n = narcs; n--; arcs++)
{
if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y,
arcs->x, arcs->y,
(int) arcs->width, (int) arcs->height))
{
miSpriteRemoveCursor (pDrawable->pScreen);
break;
}
}
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs);
GC_OP_EPILOGUE (pGC);
}
static Bool
miSpriteTextOverlap (
DrawablePtr pDraw,
FontPtr font,
int x,
int y,
unsigned int n,
CharInfoPtr *charinfo,
Bool imageblt,
unsigned int w,
BoxPtr cursorBox)
{
ExtentInfoRec extents;
x += pDraw->x;
y += pDraw->y;
if (FONTMINBOUNDS(font,characterWidth) >= 0)
{
if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0))
extents.overallLeft = charinfo[0]->metrics.leftSideBearing;
else
extents.overallLeft = 0;
if (w)
extents.overallRight = w - charinfo[n-1]->metrics.characterWidth;
else
extents.overallRight = FONTMAXBOUNDS(font,characterWidth)
* (n - 1);
if (imageblt && (charinfo[n-1]->metrics.characterWidth >
charinfo[n-1]->metrics.rightSideBearing))
extents.overallRight += charinfo[n-1]->metrics.characterWidth;
else
extents.overallRight += charinfo[n-1]->metrics.rightSideBearing;
if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent))
extents.overallAscent = FONTASCENT(font);
else
extents.overallAscent = FONTMAXBOUNDS(font, ascent);
if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent))
extents.overallDescent = FONTDESCENT(font);
else
extents.overallDescent = FONTMAXBOUNDS(font,descent);
if (!BOX_OVERLAP(cursorBox,
x + extents.overallLeft,
y - extents.overallAscent,
x + extents.overallRight,
y + extents.overallDescent))
return FALSE;
else if (imageblt && w)
return TRUE;
}
QueryGlyphExtents(font, charinfo, n, &extents);
if (imageblt)
{
if (extents.overallWidth > extents.overallRight)
extents.overallRight = extents.overallWidth;
if (extents.overallWidth < extents.overallLeft)
extents.overallLeft = extents.overallWidth;
if (extents.overallLeft > 0)
extents.overallLeft = 0;
if (extents.fontAscent > extents.overallAscent)
extents.overallAscent = extents.fontAscent;
if (extents.fontDescent > extents.overallDescent)
extents.overallDescent = extents.fontDescent;
}
return (BOX_OVERLAP(cursorBox,
x + extents.overallLeft,
y - extents.overallAscent,
x + extents.overallRight,
y + extents.overallDescent));
}
#define TT_POLY8 0
#define TT_IMAGE8 1
#define TT_POLY16 2
#define TT_IMAGE16 3
static int
miSpriteText (
DrawablePtr pDraw,
GCPtr pGC,
int x,
int y,
unsigned long count,
char *chars,
FontEncoding fontEncoding,
Bool textType,
BoxPtr cursorBox)
{
CharInfoPtr *charinfo;
register CharInfoPtr *info;
unsigned long i;
unsigned int n;
int w;
Bool imageblt;
imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
if (!charinfo)
return x;
GetGlyphs(pGC->font, count, (unsigned char *)chars,
fontEncoding, &i, charinfo);
n = (unsigned int)i;
w = 0;
if (!imageblt)
for (info = charinfo; i--; info++)
w += (*info)->metrics.characterWidth;
if (n != 0) {
if (miSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox))
miSpriteRemoveCursor(pDraw->pScreen);
#ifdef AVOID_GLYPHBLT
switch (textType)
{
case TT_POLY8:
(*pGC->ops->PolyText8)(pDraw, pGC, x, y, (int)count, chars);
break;
case TT_IMAGE8:
(*pGC->ops->ImageText8)(pDraw, pGC, x, y, (int)count, chars);
break;
case TT_POLY16:
(*pGC->ops->PolyText16)(pDraw, pGC, x, y, (int)count,
(unsigned short *)chars);
break;
case TT_IMAGE16:
(*pGC->ops->ImageText16)(pDraw, pGC, x, y, (int)count,
(unsigned short *)chars);
break;
}
#else
if (imageblt) {
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n, charinfo,
FONTGLYPHS(pGC->font));
} else {
(*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, n, charinfo,
FONTGLYPHS(pGC->font));
}
#endif
}
DEALLOCATE_LOCAL(charinfo);
return x + w;
}
static int
miSpritePolyText8(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
int ret;
GC_SETUP (pDrawable, pGC);
GC_OP_PROLOGUE (pGC);
if (GC_CHECK((WindowPtr) pDrawable))
ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars,
Linear8Bit, TT_POLY8, &pScreenPriv->saved);
else
ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
GC_OP_EPILOGUE (pGC);
return ret;
}
static int
miSpritePolyText16(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
unsigned short *chars;
{
int ret;
GC_SETUP(pDrawable, pGC);
GC_OP_PROLOGUE (pGC);
if (GC_CHECK((WindowPtr) pDrawable))
ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
(char *)chars,
FONTLASTROW(pGC->font) == 0 ?
Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved);
else
ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
GC_OP_EPILOGUE (pGC);
return ret;
}
static void
miSpriteImageText8(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
GC_SETUP(pDrawable, pGC);
GC_OP_PROLOGUE (pGC);
if (GC_CHECK((WindowPtr) pDrawable))
(void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved);
else
(*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
GC_OP_EPILOGUE (pGC);
}
static void
miSpriteImageText16(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
unsigned short *chars;
{
GC_SETUP(pDrawable, pGC);
GC_OP_PROLOGUE (pGC);
if (GC_CHECK((WindowPtr) pDrawable))
(void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
(char *)chars,
FONTLASTROW(pGC->font) == 0 ?
Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved);
else
(*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
GC_OP_EPILOGUE (pGC);
}
static void
miSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
unsigned int nglyph;
CharInfoPtr *ppci;
pointer pglyphBase;
{
GC_SETUP(pDrawable, pGC);
GC_OP_PROLOGUE (pGC);
if (GC_CHECK((WindowPtr) pDrawable) &&
miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved))
{
miSpriteRemoveCursor(pDrawable->pScreen);
}
(*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
unsigned int nglyph;
CharInfoPtr *ppci;
pointer pglyphBase;
{
GC_SETUP (pDrawable, pGC);
GC_OP_PROLOGUE (pGC);
if (GC_CHECK((WindowPtr) pDrawable) &&
miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved))
{
miSpriteRemoveCursor(pDrawable->pScreen);
}
(*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
GC_OP_EPILOGUE (pGC);
}
static void
miSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y)
GCPtr pGC;
PixmapPtr pBitMap;
DrawablePtr pDrawable;
int w, h, x, y;
{
GC_SETUP(pDrawable, pGC);
if (GC_CHECK((WindowPtr) pDrawable) &&
ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h))
{
miSpriteRemoveCursor (pDrawable->pScreen);
}
GC_OP_PROLOGUE (pGC);
(*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
GC_OP_EPILOGUE (pGC);
}
#ifdef NEED_LINEHELPER
static void
miSpriteLineHelper()
{
FatalError("miSpriteLineHelper called\n");
}
#endif
#ifdef RENDER
# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
static void
miSpritePictureOverlap (PicturePtr pPict,
INT16 x,
INT16 y,
CARD16 w,
CARD16 h)
{
if (pPict->pDrawable->type == DRAWABLE_WINDOW)
{
WindowPtr pWin = (WindowPtr) (pPict->pDrawable);
miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr)
pPict->pDrawable->pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (GC_CHECK(pWin))
{
if (pPict->repeat)
{
x = mod(x,pWin->drawable.width);
y = mod(y,pWin->drawable.height);
}
if (ORG_OVERLAP (&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y,
x, y, w, h))
miSpriteRemoveCursor (pWin->drawable.pScreen);
}
}
}
#define PICTURE_PROLOGUE(ps, pScreenPriv, field) \
ps->field = pScreenPriv->field
#define PICTURE_EPILOGUE(ps, field, wrap) \
ps->field = wrap
static void
miSpriteComposite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
ScreenPtr pScreen = pDst->pDrawable->pScreen;
PictureScreenPtr ps = GetPictureScreen(pScreen);
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
PICTURE_PROLOGUE(ps, pScreenPriv, Composite);
miSpritePictureOverlap (pSrc, xSrc, ySrc, width, height);
if (pMask)
miSpritePictureOverlap (pMask, xMask, yMask, width, height);
miSpritePictureOverlap (pDst, xDst, yDst, width, height);
(*ps->Composite) (op,
pSrc,
pMask,
pDst,
xSrc,
ySrc,
xMask,
yMask,
xDst,
yDst,
width,
height);
PICTURE_EPILOGUE(ps, Composite, miSpriteComposite);
}
static void
miSpriteGlyphs(CARD8 op,
PicturePtr pSrc,
PicturePtr pDst,
PictFormatPtr maskFormat,
INT16 xSrc,
INT16 ySrc,
int nlist,
GlyphListPtr list,
GlyphPtr *glyphs)
{
ScreenPtr pScreen = pDst->pDrawable->pScreen;
PictureScreenPtr ps = GetPictureScreen(pScreen);
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
PICTURE_PROLOGUE(ps, pScreenPriv, Glyphs);
if (pSrc->pDrawable->type == DRAWABLE_WINDOW)
{
WindowPtr pSrcWin = (WindowPtr) (pSrc->pDrawable);
if (GC_CHECK(pSrcWin))
miSpriteRemoveCursor (pScreen);
}
if (pDst->pDrawable->type == DRAWABLE_WINDOW)
{
WindowPtr pDstWin = (WindowPtr) (pDst->pDrawable);
if (GC_CHECK(pDstWin))
{
BoxRec extents;
miGlyphExtents (nlist, list, glyphs, &extents);
if (BOX_OVERLAP(&pScreenPriv->saved,
extents.x1 + pDstWin->drawable.x,
extents.y1 + pDstWin->drawable.y,
extents.x2 + pDstWin->drawable.x,
extents.y2 + pDstWin->drawable.y))
{
miSpriteRemoveCursor (pScreen);
}
}
}
(*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
PICTURE_EPILOGUE (ps, Glyphs, miSpriteGlyphs);
}
#endif
#define SPRITE_PAD 8
static Bool
miSpriteRealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pCursor == pScreenPriv->pCursor)
pScreenPriv->checkPixels = TRUE;
return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
}
static Bool
miSpriteUnrealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
}
static void
miSpriteSetCursor (pScreen, pCursor, x, y)
ScreenPtr pScreen;
CursorPtr pCursor;
int x;
int y;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (!pCursor)
{
pScreenPriv->shouldBeUp = FALSE;
if (pScreenPriv->isUp)
miSpriteRemoveCursor (pScreen);
pScreenPriv->pCursor = 0;
return;
}
pScreenPriv->shouldBeUp = TRUE;
if (pScreenPriv->x == x &&
pScreenPriv->y == y &&
pScreenPriv->pCursor == pCursor &&
!pScreenPriv->checkPixels)
{
return;
}
pScreenPriv->x = x;
pScreenPriv->y = y;
pScreenPriv->pCacheWin = NullWindow;
if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
{
pScreenPriv->pCursor = pCursor;
miSpriteFindColors (pScreen);
}
if (pScreenPriv->isUp) {
int sx, sy;
sx = pScreenPriv->x - (int)pCursor->bits->xhot;
sy = pScreenPriv->y - (int)pCursor->bits->yhot;
if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 &&
sx < pScreenPriv->saved.x2 &&
sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 &&
sy < pScreenPriv->saved.y2 &&
(int) pCursor->bits->width + (2 * SPRITE_PAD) ==
pScreenPriv->saved.x2 - pScreenPriv->saved.x1 &&
(int) pCursor->bits->height + (2 * SPRITE_PAD) ==
pScreenPriv->saved.y2 - pScreenPriv->saved.y1
)
{
pScreenPriv->isUp = FALSE;
if (!(sx >= pScreenPriv->saved.x1 &&
sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 &&
sy >= pScreenPriv->saved.y1 &&
sy + (int)pCursor->bits->height < pScreenPriv->saved.y2))
{
int oldx1, oldy1, dx, dy;
oldx1 = pScreenPriv->saved.x1;
oldy1 = pScreenPriv->saved.y1;
dx = oldx1 - (sx - SPRITE_PAD);
dy = oldy1 - (sy - SPRITE_PAD);
pScreenPriv->saved.x1 -= dx;
pScreenPriv->saved.y1 -= dy;
pScreenPriv->saved.x2 -= dx;
pScreenPriv->saved.y2 -= dy;
(void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
pScreenPriv->saved.x1,
pScreenPriv->saved.y1,
pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
dx, dy);
}
(void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
pScreenPriv->saved.x1,
pScreenPriv->saved.y1,
pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
sx - pScreenPriv->saved.x1,
sy - pScreenPriv->saved.y1,
pScreenPriv->colors[SOURCE_COLOR].pixel,
pScreenPriv->colors[MASK_COLOR].pixel);
pScreenPriv->isUp = TRUE;
}
else
{
miSpriteRemoveCursor (pScreen);
}
}
if (!pScreenPriv->isUp && pScreenPriv->pCursor)
miSpriteRestoreCursor (pScreen);
}
static void
miSpriteMoveCursor (pScreen, x, y)
ScreenPtr pScreen;
int x, y;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
}
static void
miSpriteRemoveCursor (pScreen)
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pScreenPriv->isUp = FALSE;
pScreenPriv->pCacheWin = NullWindow;
if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
pScreenPriv->saved.x1,
pScreenPriv->saved.y1,
pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
{
pScreenPriv->isUp = TRUE;
}
}
static void
miSpriteRestoreCursor (pScreen)
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
int x, y;
CursorPtr pCursor;
miSpriteComputeSaved (pScreen);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pCursor = pScreenPriv->pCursor;
x = pScreenPriv->x - (int)pCursor->bits->xhot;
y = pScreenPriv->y - (int)pCursor->bits->yhot;
if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
pScreenPriv->saved.x1,
pScreenPriv->saved.y1,
pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
{
if (pScreenPriv->checkPixels)
miSpriteFindColors (pScreen);
if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
pScreenPriv->colors[SOURCE_COLOR].pixel,
pScreenPriv->colors[MASK_COLOR].pixel))
pScreenPriv->isUp = TRUE;
}
}
static void
miSpriteComputeSaved (pScreen)
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
int x, y, w, h;
int wpad, hpad;
CursorPtr pCursor;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pCursor = pScreenPriv->pCursor;
x = pScreenPriv->x - (int)pCursor->bits->xhot;
y = pScreenPriv->y - (int)pCursor->bits->yhot;
w = pCursor->bits->width;
h = pCursor->bits->height;
wpad = SPRITE_PAD;
hpad = SPRITE_PAD;
pScreenPriv->saved.x1 = x - wpad;
pScreenPriv->saved.y1 = y - hpad;
pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2;
pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2;
}