summaryrefslogtreecommitdiff
path: root/mi/misprite.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
commitded6147bfb5d75ff1e67c858040a628b61bc17d1 (patch)
tree82355105e93cdac89ef7d987424351c77545faf0 /mi/misprite.c
parentcb6ef07bf01e72d1a6e6e83ceb7f76d6534da941 (diff)
R6.6 is the Xorg base-lineXORG-MAIN
Diffstat (limited to 'mi/misprite.c')
-rw-r--r--mi/misprite.c2067
1 files changed, 2067 insertions, 0 deletions
diff --git a/mi/misprite.c b/mi/misprite.c
new file mode 100644
index 000000000..2fc6da8dd
--- /dev/null
+++ b/mi/misprite.c
@@ -0,0 +1,2067 @@
+/*
+ * misprite.c
+ *
+ * machine independent software sprite routines
+ */
+
+/* $Xorg: misprite.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */
+
+/*
+
+Copyright 1989, 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.
+*/
+
+# 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"
+
+/*
+ * screen wrappers
+ */
+
+static int miSpriteScreenIndex;
+static unsigned long miSpriteGeneration = 0;
+
+static Bool miSpriteCloseScreen();
+static void miSpriteGetImage();
+static void miSpriteGetSpans();
+static void miSpriteSourceValidate();
+static Bool miSpriteCreateGC();
+static void miSpriteBlockHandler();
+static void miSpriteInstallColormap();
+static void miSpriteStoreColors();
+
+static void miSpritePaintWindowBackground();
+static void miSpritePaintWindowBorder();
+static void miSpriteCopyWindow();
+static void miSpriteClearToBackground();
+
+static void miSpriteSaveDoomedAreas();
+static RegionPtr miSpriteRestoreAreas();
+static void miSpriteComputeSaved();
+
+#define SCREEN_PROLOGUE(pScreen, field)\
+ ((pScreen)->field = \
+ ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
+
+#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
+ ((pScreen)->field = wrapper)
+
+/*
+ * GC func wrappers
+ */
+
+static int miSpriteGCIndex;
+
+static void miSpriteValidateGC (), miSpriteCopyGC ();
+static void miSpriteDestroyGC(), miSpriteChangeGC();
+static void miSpriteChangeClip(), miSpriteDestroyClip();
+static void miSpriteCopyClip();
+
+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; \
+ }
+
+/*
+ * GC op wrappers
+ */
+
+static void miSpriteFillSpans(), miSpriteSetSpans();
+static void miSpritePutImage();
+static RegionPtr miSpriteCopyArea(), miSpriteCopyPlane();
+static void miSpritePolyPoint(), miSpritePolylines();
+static void miSpritePolySegment(), miSpritePolyRectangle();
+static void miSpritePolyArc(), miSpriteFillPolygon();
+static void miSpritePolyFillRect(), miSpritePolyFillArc();
+static int miSpritePolyText8(), miSpritePolyText16();
+static void miSpriteImageText8(), miSpriteImageText16();
+static void miSpriteImageGlyphBlt(), miSpritePolyGlyphBlt();
+static void miSpritePushPixels();
+#ifdef NEED_LINEHELPER
+static void miSpriteLineHelper();
+#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
+};
+
+/*
+ * testing only -- remove cursor for every draw. Eventually,
+ * each draw operation will perform a bounding box check against
+ * the saved cursor area
+ */
+
+#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 : ( \
+ ((int) (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; \
+ }
+
+/*
+ * pointer-sprite method table
+ */
+
+static Bool miSpriteRealizeCursor (), miSpriteUnrealizeCursor ();
+static void miSpriteSetCursor (), miSpriteMoveCursor ();
+
+miPointerSpriteFuncRec miSpritePointerFuncs = {
+ miSpriteRealizeCursor,
+ miSpriteUnrealizeCursor,
+ miSpriteSetCursor,
+ miSpriteMoveCursor,
+};
+
+/*
+ * other misc functions
+ */
+
+static void miSpriteRemoveCursor (), miSpriteRestoreCursor();
+
+/*
+ * miSpriteInitialize -- called from device-dependent screen
+ * initialization proc after all of the function pointers have
+ * been stored in the screen structure.
+ */
+
+Bool
+miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
+ ScreenPtr pScreen;
+ miSpriteCursorFuncPtr cursorFuncs;
+ miPointerScreenFuncPtr screenFuncs;
+{
+ miSpriteScreenPtr pPriv;
+ VisualPtr pVisual;
+
+ 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;
+
+ 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;
+
+ return TRUE;
+}
+
+/*
+ * Screen wrappers
+ */
+
+/*
+ * CloseScreen wrapper -- unwrap everything, free the private data
+ * and call the wrapped function
+ */
+
+static Bool
+miSpriteCloseScreen (i, pScreen)
+ ScreenPtr pScreen;
+{
+ miSpriteScreenPtr pScreenPriv;
+
+ 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;
+
+ 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;
+ OSTimePtr 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)
+ {
+ /* Direct color - match on any of the subfields */
+
+#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
+ {
+ /* PseudoColor/GrayScale - match on exact pixel */
+ 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 (pScreen)
+ 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);
+ /* "free" the pixels right away, don't let this confuse you */
+ FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
+ FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
+ }
+ pScreenPriv->checkPixels = FALSE;
+}
+
+/*
+ * BackingStore wrappers
+ */
+
+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;
+}
+
+/*
+ * Window wrappers
+ */
+
+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 the cursor is on the same screen as the window, check the
+ * region to paint for the cursor and remove it as necessary
+ */
+ 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 the cursor is on the same screen as the window, check the
+ * region to paint for the cursor and remove it as necessary
+ */
+ 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)
+ {
+ /*
+ * check both the source and the destination areas. The given
+ * region is source relative, so offset the cursor box by
+ * the delta position
+ */
+ 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;
+ short x,y;
+ unsigned short 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);
+}
+
+/*
+ * GC Func wrappers
+ */
+
+static void
+miSpriteValidateGC (pGC, changes, pDrawable)
+ GCPtr pGC;
+ Mask 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);
+}
+
+/*
+ * GC Op wrappers
+ */
+
+static void
+miSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int nInit; /* number of spans to fill */
+ DDXPointPtr pptInit; /* pointer to list of start points */
+ int *pwidthInit; /* pointer to list of n widths */
+ 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 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);
+
+ /* check destination/source overlap. */
+ 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);
+
+ /*
+ * check destination/source for overlap.
+ */
+ 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; /* Origin or Previous */
+ 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;
+ /*
+ * mitered joins can project quite a way from
+ * the line end; the 11 degree miter limit limits
+ * this extension to 10.43 * lw / 2, rounded up
+ * and converted to int yields 6 * lw
+ */
+ 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; /* number of rectangles to fill */
+ xRectangle *prectInit; /* Pointer to first rectangle to fill */
+{
+ 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);
+}
+
+/*
+ * general Poly/Image text function. Extract glyph information,
+ * compute bounding box and remove cursor if it is overlapped.
+ */
+
+static Bool
+miSpriteTextOverlap (pDraw, font, x, y, n, charinfo, imageblt, w, cursorBox)
+ DrawablePtr pDraw;
+ FontPtr font;
+ int x, 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)
+ {
+ /* compute an approximate (but covering) bounding box */
+ 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;
+ /* if it does overlap, fall through and compute exactly, because
+ * taking down the cursor is expensive enough to make this worth it
+ */
+ }
+ 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));
+}
+
+/*
+ * values for textType:
+ */
+#define TT_POLY8 0
+#define TT_IMAGE8 1
+#define TT_POLY16 2
+#define TT_IMAGE16 3
+
+static int
+miSpriteText (pDraw, pGC, x, y, count, chars, fontEncoding, textType, cursorBox)
+ DrawablePtr pDraw;
+ GCPtr pGC;
+ int x,
+ 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;
+ void (*drawFunc)();
+
+ 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
+ /*
+ * On displays like Apollos, which do not optimize the GlyphBlt functions because they
+ * convert fonts to their internal form in RealizeFont and optimize text directly, we
+ * want to invoke the text functions here, not the GlyphBlt functions.
+ */
+ switch (textType)
+ {
+ case TT_POLY8:
+ drawFunc = (void (*)())pGC->ops->PolyText8;
+ break;
+ case TT_IMAGE8:
+ drawFunc = pGC->ops->ImageText8;
+ break;
+ case TT_POLY16:
+ drawFunc = (void (*)())pGC->ops->PolyText16;
+ break;
+ case TT_IMAGE16:
+ drawFunc = pGC->ops->ImageText16;
+ break;
+ }
+ (*drawFunc) (pDraw, pGC, x, y, (int) count, chars);
+#else /* don't AVOID_GLYPHBLT */
+ /*
+ * On the other hand, if the device does use GlyphBlt ultimately to do text, we
+ * don't want to slow it down by invoking the text functions and having them call
+ * GetGlyphs all over again, so we go directly to the GlyphBlt functions here.
+ */
+ drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt;
+ (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
+#endif /* AVOID_GLYPHBLT */
+ }
+ 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; /* array of character info */
+ pointer pglyphBase; /* start of array of glyphs */
+{
+ 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; /* array of character info */
+ pointer pglyphBase; /* start of array of glyphs */
+{
+ 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
+/*
+ * I don't expect this routine will ever be called, as the GC
+ * will have been unwrapped for the line drawing
+ */
+
+static void
+miSpriteLineHelper()
+{
+ FatalError("miSpriteLineHelper called\n");
+}
+#endif
+
+/*
+ * miPointer interface routines
+ */
+
+#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;
+{
+ miSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+ pScreenPriv->shouldBeUp = TRUE;
+ if (pScreenPriv->x == x &&
+ pScreenPriv->y == y &&
+ pScreenPriv->pCursor == pCursor &&
+ !pScreenPriv->checkPixels)
+ {
+ return;
+ }
+ if (!pCursor)
+ {
+ pScreenPriv->shouldBeUp = FALSE;
+ if (pScreenPriv->isUp)
+ miSpriteRemoveCursor (pScreen);
+ pScreenPriv->pCursor = 0;
+ 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;
+ /*
+ * check to see if the old saved region
+ * encloses the new sprite, in which case we use
+ * the flicker-free MoveCursor primitive.
+ */
+ 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);
+}
+
+/*
+ * undraw/draw cursor
+ */
+
+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;
+ }
+}
+
+/*
+ * Called from the block handler, restores the cursor
+ * before waiting for something to do.
+ */
+
+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;
+ }
+}
+
+/*
+ * compute the desired area of the screen to save
+ */
+
+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;
+}