xserver-multidpi/mi/misprite.c

2325 lines
59 KiB
C
Raw Normal View History

2003-11-14 16:54:54 +01:00
/*
* 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.
*/
2004-04-23 21:54:30 +02:00
/* $XFree86: xc/programs/Xserver/mi/misprite.c,v 3.10tsi Exp $ */
2003-11-14 16:54:54 +01:00
# 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"
2003-11-14 17:49:22 +01:00
#ifdef RENDER
# include "mipict.h"
#endif
2003-11-14 16:54:54 +01:00
/*
* screen wrappers
*/
static int miSpriteScreenIndex;
static unsigned long miSpriteGeneration = 0;
2003-11-14 17:49:22 +01:00
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
2003-11-14 16:54:54 +01:00
2003-11-14 17:49:22 +01:00
static void miSpriteSaveDoomedAreas(WindowPtr pWin,
RegionPtr pObscured, int dx,
int dy);
static RegionPtr miSpriteRestoreAreas(WindowPtr pWin, RegionPtr pRgnExposed);
static void miSpriteComputeSaved(ScreenPtr pScreen);
2003-11-14 16:54:54 +01:00
#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;
2003-11-14 17:49:22 +01:00
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);
2003-11-14 16:54:54 +01:00
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
*/
2003-11-14 17:49:22 +01:00
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);
2003-11-14 16:54:54 +01:00
#ifdef NEED_LINEHELPER
2003-11-14 17:49:22 +01:00
static void miSpriteLineHelper(void);
2003-11-14 16:54:54 +01:00
#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 : ( \
2003-11-14 17:49:22 +01:00
(pScreenPriv->pCacheWin = (pWin)), \
2003-11-14 16:54:54 +01:00
(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
*/
2003-11-14 17:49:22 +01:00
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);
2003-11-14 16:54:54 +01:00
miPointerSpriteFuncRec miSpritePointerFuncs = {
miSpriteRealizeCursor,
miSpriteUnrealizeCursor,
miSpriteSetCursor,
miSpriteMoveCursor,
};
/*
* other misc functions
*/
2003-11-14 17:49:22 +01:00
static void miSpriteRemoveCursor(ScreenPtr pScreen);
static void miSpriteRestoreCursor(ScreenPtr pScreen);
2003-11-14 16:54:54 +01:00
/*
* 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;
2003-11-14 17:49:22 +01:00
#ifdef RENDER
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
2003-11-14 16:54:54 +01:00
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;
2003-11-14 17:49:22 +01:00
#ifdef RENDER
if (ps)
{
pPriv->Composite = ps->Composite;
pPriv->Glyphs = ps->Glyphs;
}
#endif
2003-11-14 16:54:54 +01:00
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;
2003-11-14 17:49:22 +01:00
#ifdef RENDER
if (ps)
{
ps->Composite = miSpriteComposite;
ps->Glyphs = miSpriteGlyphs;
}
#endif
2003-11-14 16:54:54 +01:00
return TRUE;
}
/*
* Screen wrappers
*/
/*
* CloseScreen wrapper -- unwrap everything, free the private data
* and call the wrapped function
*/
static Bool
miSpriteCloseScreen (i, pScreen)
2003-11-14 17:49:22 +01:00
int i;
2003-11-14 16:54:54 +01:00
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
2003-11-14 17:49:22 +01:00
#ifdef RENDER
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
2003-11-14 16:54:54 +01:00
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;
2003-11-14 17:49:22 +01:00
#ifdef RENDER
if (ps)
{
ps->Composite = pScreenPriv->Composite;
ps->Glyphs = pScreenPriv->Glyphs;
}
#endif
2003-11-14 16:54:54 +01:00
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;
2003-11-14 17:49:22 +01:00
pointer pTimeout;
2003-11-14 16:54:54 +01:00
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 */
2003-11-14 17:49:22 +01:00
#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
2003-11-14 16:54:54 +01:00
#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
2003-11-14 17:49:22 +01:00
miSpriteFindColors (ScreenPtr pScreen)
2003-11-14 16:54:54 +01:00
{
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;
2003-11-14 17:49:22 +01:00
int x,y;
int w,h;
2003-11-14 16:54:54 +01:00
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;
2003-11-14 17:49:22 +01:00
unsigned long changes;
2003-11-14 16:54:54 +01:00
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;
2003-11-14 17:49:22 +01:00
int leftPad;
2003-11-14 16:54:54 +01:00
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
2003-11-14 17:49:22 +01:00
miSpriteTextOverlap (
DrawablePtr pDraw,
FontPtr font,
int x,
int y,
unsigned int n,
CharInfoPtr *charinfo,
Bool imageblt,
unsigned int w,
BoxPtr cursorBox)
2003-11-14 16:54:54 +01:00
{
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
2003-11-14 17:49:22 +01:00
miSpriteText (
DrawablePtr pDraw,
GCPtr pGC,
2003-11-14 16:54:54 +01:00
int x,
2003-11-14 17:49:22 +01:00
int y,
unsigned long count,
char *chars,
FontEncoding fontEncoding,
Bool textType,
BoxPtr cursorBox)
2003-11-14 16:54:54 +01:00
{
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
/*
* 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:
2003-11-14 17:49:22 +01:00
(*pGC->ops->PolyText8)(pDraw, pGC, x, y, (int)count, chars);
2003-11-14 16:54:54 +01:00
break;
case TT_IMAGE8:
2003-11-14 17:49:22 +01:00
(*pGC->ops->ImageText8)(pDraw, pGC, x, y, (int)count, chars);
2003-11-14 16:54:54 +01:00
break;
case TT_POLY16:
2003-11-14 17:49:22 +01:00
(*pGC->ops->PolyText16)(pDraw, pGC, x, y, (int)count,
(unsigned short *)chars);
2003-11-14 16:54:54 +01:00
break;
case TT_IMAGE16:
2003-11-14 17:49:22 +01:00
(*pGC->ops->ImageText16)(pDraw, pGC, x, y, (int)count,
(unsigned short *)chars);
2003-11-14 16:54:54 +01:00
break;
}
#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.
*/
2003-11-14 17:49:22 +01:00
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));
}
2003-11-14 16:54:54 +01:00
#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
2003-11-14 17:49:22 +01:00
#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
2003-11-14 16:54:54 +01:00
/*
* 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;
2003-11-14 17:49:22 +01:00
int x;
int y;
2003-11-14 16:54:54 +01:00
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (!pCursor)
{
pScreenPriv->shouldBeUp = FALSE;
if (pScreenPriv->isUp)
miSpriteRemoveCursor (pScreen);
pScreenPriv->pCursor = 0;
return;
}
2003-11-14 17:49:22 +01:00
pScreenPriv->shouldBeUp = TRUE;
if (pScreenPriv->x == x &&
pScreenPriv->y == y &&
pScreenPriv->pCursor == pCursor &&
!pScreenPriv->checkPixels)
{
return;
}
2003-11-14 16:54:54 +01:00
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;
}