2325 lines
59 KiB
C
2325 lines
59 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
/* $XFree86: xc/programs/Xserver/mi/misprite.c,v 3.11 2002/12/09 04:10:58 tsi Exp $ */
|
|
|
|
# include "X.h"
|
|
# include "Xproto.h"
|
|
# include "misc.h"
|
|
# include "pixmapstr.h"
|
|
# include "input.h"
|
|
# include "mi.h"
|
|
# include "cursorstr.h"
|
|
# include "font.h"
|
|
# include "scrnintstr.h"
|
|
# include "colormapst.h"
|
|
# include "windowstr.h"
|
|
# include "gcstruct.h"
|
|
# include "mipointer.h"
|
|
# include "mispritest.h"
|
|
# include "dixfontstr.h"
|
|
# include "fontstruct.h"
|
|
#ifdef RENDER
|
|
# include "mipict.h"
|
|
#endif
|
|
|
|
/*
|
|
* screen wrappers
|
|
*/
|
|
|
|
static int miSpriteScreenIndex;
|
|
static unsigned long miSpriteGeneration = 0;
|
|
|
|
static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen);
|
|
static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
|
|
int w, int h, unsigned int format,
|
|
unsigned long planemask, char *pdstLine);
|
|
static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
|
|
DDXPointPtr ppt, int *pwidth, int nspans,
|
|
char *pdstStart);
|
|
static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
|
|
int width, int height);
|
|
static Bool miSpriteCreateGC(GCPtr pGC);
|
|
static void miSpriteBlockHandler(int i, pointer blockData,
|
|
pointer pTimeout,
|
|
pointer pReadMask);
|
|
static void miSpriteInstallColormap(ColormapPtr pMap);
|
|
static void miSpriteStoreColors(ColormapPtr pMap, int ndef,
|
|
xColorItem *pdef);
|
|
|
|
static void miSpritePaintWindowBackground(WindowPtr pWin,
|
|
RegionPtr pRegion, int what);
|
|
static void miSpritePaintWindowBorder(WindowPtr pWin,
|
|
RegionPtr pRegion, int what);
|
|
static void miSpriteCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
|
|
RegionPtr pRegion);
|
|
static void miSpriteClearToBackground(WindowPtr pWin, int x, int y,
|
|
int w, int h,
|
|
Bool generateExposures);
|
|
|
|
#ifdef RENDER
|
|
static void miSpriteComposite(CARD8 op,
|
|
PicturePtr pSrc,
|
|
PicturePtr pMask,
|
|
PicturePtr pDst,
|
|
INT16 xSrc,
|
|
INT16 ySrc,
|
|
INT16 xMask,
|
|
INT16 yMask,
|
|
INT16 xDst,
|
|
INT16 yDst,
|
|
CARD16 width,
|
|
CARD16 height);
|
|
|
|
static void miSpriteGlyphs(CARD8 op,
|
|
PicturePtr pSrc,
|
|
PicturePtr pDst,
|
|
PictFormatPtr maskFormat,
|
|
INT16 xSrc,
|
|
INT16 ySrc,
|
|
int nlist,
|
|
GlyphListPtr list,
|
|
GlyphPtr *glyphs);
|
|
#endif
|
|
|
|
static void miSpriteSaveDoomedAreas(WindowPtr pWin,
|
|
RegionPtr pObscured, int dx,
|
|
int dy);
|
|
static RegionPtr miSpriteRestoreAreas(WindowPtr pWin, RegionPtr pRgnExposed);
|
|
static void miSpriteComputeSaved(ScreenPtr pScreen);
|
|
|
|
#define SCREEN_PROLOGUE(pScreen, field)\
|
|
((pScreen)->field = \
|
|
((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
|
|
|
|
#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
|
|
((pScreen)->field = wrapper)
|
|
|
|
/*
|
|
* GC func wrappers
|
|
*/
|
|
|
|
static int miSpriteGCIndex;
|
|
|
|
static void miSpriteValidateGC(GCPtr pGC, unsigned long stateChanges,
|
|
DrawablePtr pDrawable);
|
|
static void miSpriteCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
|
|
static void miSpriteDestroyGC(GCPtr pGC);
|
|
static void miSpriteChangeGC(GCPtr pGC, unsigned long mask);
|
|
static void miSpriteChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
|
|
static void miSpriteDestroyClip(GCPtr pGC);
|
|
static void miSpriteCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
|
|
|
|
static GCFuncs miSpriteGCFuncs = {
|
|
miSpriteValidateGC,
|
|
miSpriteChangeGC,
|
|
miSpriteCopyGC,
|
|
miSpriteDestroyGC,
|
|
miSpriteChangeClip,
|
|
miSpriteDestroyClip,
|
|
miSpriteCopyClip,
|
|
};
|
|
|
|
#define GC_FUNC_PROLOGUE(pGC) \
|
|
miSpriteGCPtr pGCPriv = \
|
|
(miSpriteGCPtr) (pGC)->devPrivates[miSpriteGCIndex].ptr;\
|
|
(pGC)->funcs = pGCPriv->wrapFuncs; \
|
|
if (pGCPriv->wrapOps) \
|
|
(pGC)->ops = pGCPriv->wrapOps;
|
|
|
|
#define GC_FUNC_EPILOGUE(pGC) \
|
|
pGCPriv->wrapFuncs = (pGC)->funcs; \
|
|
(pGC)->funcs = &miSpriteGCFuncs; \
|
|
if (pGCPriv->wrapOps) \
|
|
{ \
|
|
pGCPriv->wrapOps = (pGC)->ops; \
|
|
(pGC)->ops = &miSpriteGCOps; \
|
|
}
|
|
|
|
/*
|
|
* GC op wrappers
|
|
*/
|
|
|
|
static void miSpriteFillSpans(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nInit, DDXPointPtr pptInit,
|
|
int *pwidthInit, int fSorted);
|
|
static void miSpriteSetSpans(DrawablePtr pDrawable, GCPtr pGC,
|
|
char *psrc, DDXPointPtr ppt, int *pwidth,
|
|
int nspans, int fSorted);
|
|
static void miSpritePutImage(DrawablePtr pDrawable, GCPtr pGC,
|
|
int depth, int x, int y, int w, int h,
|
|
int leftPad, int format, char *pBits);
|
|
static RegionPtr miSpriteCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
|
|
GCPtr pGC, int srcx, int srcy, int w,
|
|
int h, int dstx, int dsty);
|
|
static RegionPtr miSpriteCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
|
|
GCPtr pGC, int srcx, int srcy, int w,
|
|
int h, int dstx, int dsty,
|
|
unsigned long plane);
|
|
static void miSpritePolyPoint(DrawablePtr pDrawable, GCPtr pGC,
|
|
int mode, int npt, xPoint *pptInit);
|
|
static void miSpritePolylines(DrawablePtr pDrawable, GCPtr pGC,
|
|
int mode, int npt, DDXPointPtr pptInit);
|
|
static void miSpritePolySegment(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nseg, xSegment *pSegs);
|
|
static void miSpritePolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nrects, xRectangle *pRects);
|
|
static void miSpritePolyArc(DrawablePtr pDrawable, GCPtr pGC,
|
|
int narcs, xArc *parcs);
|
|
static void miSpriteFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
|
|
int shape, int mode, int count,
|
|
DDXPointPtr pPts);
|
|
static void miSpritePolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nrectFill, xRectangle *prectInit);
|
|
static void miSpritePolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
|
|
int narcs, xArc *parcs);
|
|
static int miSpritePolyText8(DrawablePtr pDrawable, GCPtr pGC,
|
|
int x, int y, int count, char *chars);
|
|
static int miSpritePolyText16(DrawablePtr pDrawable, GCPtr pGC,
|
|
int x, int y, int count,
|
|
unsigned short *chars);
|
|
static void miSpriteImageText8(DrawablePtr pDrawable, GCPtr pGC,
|
|
int x, int y, int count, char *chars);
|
|
static void miSpriteImageText16(DrawablePtr pDrawable, GCPtr pGC,
|
|
int x, int y, int count,
|
|
unsigned short *chars);
|
|
static void miSpriteImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
|
int x, int y, unsigned int nglyph,
|
|
CharInfoPtr *ppci,
|
|
pointer pglyphBase);
|
|
static void miSpritePolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
|
int x, int y, unsigned int nglyph,
|
|
CharInfoPtr *ppci,
|
|
pointer pglyphBase);
|
|
static void miSpritePushPixels(GCPtr pGC, PixmapPtr pBitMap,
|
|
DrawablePtr pDst, int w, int h,
|
|
int x, int y);
|
|
#ifdef NEED_LINEHELPER
|
|
static void miSpriteLineHelper(void);
|
|
#endif
|
|
|
|
static GCOps miSpriteGCOps = {
|
|
miSpriteFillSpans, miSpriteSetSpans, miSpritePutImage,
|
|
miSpriteCopyArea, miSpriteCopyPlane, miSpritePolyPoint,
|
|
miSpritePolylines, miSpritePolySegment, miSpritePolyRectangle,
|
|
miSpritePolyArc, miSpriteFillPolygon, miSpritePolyFillRect,
|
|
miSpritePolyFillArc, miSpritePolyText8, miSpritePolyText16,
|
|
miSpriteImageText8, miSpriteImageText16, miSpriteImageGlyphBlt,
|
|
miSpritePolyGlyphBlt, miSpritePushPixels
|
|
#ifdef NEED_LINEHELPER
|
|
, miSpriteLineHelper
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* 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 : ( \
|
|
(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(ScreenPtr pScreen, CursorPtr pCursor);
|
|
static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
|
|
static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor,
|
|
int x, int y);
|
|
static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y);
|
|
|
|
miPointerSpriteFuncRec miSpritePointerFuncs = {
|
|
miSpriteRealizeCursor,
|
|
miSpriteUnrealizeCursor,
|
|
miSpriteSetCursor,
|
|
miSpriteMoveCursor,
|
|
};
|
|
|
|
/*
|
|
* other misc functions
|
|
*/
|
|
|
|
static void miSpriteRemoveCursor(ScreenPtr pScreen);
|
|
static void miSpriteRestoreCursor(ScreenPtr pScreen);
|
|
|
|
/*
|
|
* 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;
|
|
#ifdef RENDER
|
|
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
|
|
#endif
|
|
|
|
if (miSpriteGeneration != serverGeneration)
|
|
{
|
|
miSpriteScreenIndex = AllocateScreenPrivateIndex ();
|
|
if (miSpriteScreenIndex < 0)
|
|
return FALSE;
|
|
miSpriteGeneration = serverGeneration;
|
|
miSpriteGCIndex = AllocateGCPrivateIndex ();
|
|
}
|
|
if (!AllocateGCPrivate(pScreen, miSpriteGCIndex, sizeof(miSpriteGCRec)))
|
|
return FALSE;
|
|
pPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec));
|
|
if (!pPriv)
|
|
return FALSE;
|
|
if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
|
|
{
|
|
xfree ((pointer) pPriv);
|
|
return FALSE;
|
|
}
|
|
for (pVisual = pScreen->visuals;
|
|
pVisual->vid != pScreen->rootVisual;
|
|
pVisual++)
|
|
;
|
|
pPriv->pVisual = pVisual;
|
|
pPriv->CloseScreen = pScreen->CloseScreen;
|
|
pPriv->GetImage = pScreen->GetImage;
|
|
pPriv->GetSpans = pScreen->GetSpans;
|
|
pPriv->SourceValidate = pScreen->SourceValidate;
|
|
pPriv->CreateGC = pScreen->CreateGC;
|
|
pPriv->BlockHandler = pScreen->BlockHandler;
|
|
pPriv->InstallColormap = pScreen->InstallColormap;
|
|
pPriv->StoreColors = pScreen->StoreColors;
|
|
|
|
pPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
|
|
pPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
|
|
pPriv->CopyWindow = pScreen->CopyWindow;
|
|
pPriv->ClearToBackground = pScreen->ClearToBackground;
|
|
|
|
pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
|
|
pPriv->RestoreAreas = pScreen->RestoreAreas;
|
|
#ifdef RENDER
|
|
if (ps)
|
|
{
|
|
pPriv->Composite = ps->Composite;
|
|
pPriv->Glyphs = ps->Glyphs;
|
|
}
|
|
#endif
|
|
|
|
pPriv->pCursor = NULL;
|
|
pPriv->x = 0;
|
|
pPriv->y = 0;
|
|
pPriv->isUp = FALSE;
|
|
pPriv->shouldBeUp = FALSE;
|
|
pPriv->pCacheWin = NullWindow;
|
|
pPriv->isInCacheWin = FALSE;
|
|
pPriv->checkPixels = TRUE;
|
|
pPriv->pInstalledMap = NULL;
|
|
pPriv->pColormap = NULL;
|
|
pPriv->funcs = cursorFuncs;
|
|
pPriv->colors[SOURCE_COLOR].red = 0;
|
|
pPriv->colors[SOURCE_COLOR].green = 0;
|
|
pPriv->colors[SOURCE_COLOR].blue = 0;
|
|
pPriv->colors[MASK_COLOR].red = 0;
|
|
pPriv->colors[MASK_COLOR].green = 0;
|
|
pPriv->colors[MASK_COLOR].blue = 0;
|
|
pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pPriv;
|
|
pScreen->CloseScreen = miSpriteCloseScreen;
|
|
pScreen->GetImage = miSpriteGetImage;
|
|
pScreen->GetSpans = miSpriteGetSpans;
|
|
pScreen->SourceValidate = miSpriteSourceValidate;
|
|
pScreen->CreateGC = miSpriteCreateGC;
|
|
pScreen->BlockHandler = miSpriteBlockHandler;
|
|
pScreen->InstallColormap = miSpriteInstallColormap;
|
|
pScreen->StoreColors = miSpriteStoreColors;
|
|
|
|
pScreen->PaintWindowBackground = miSpritePaintWindowBackground;
|
|
pScreen->PaintWindowBorder = miSpritePaintWindowBorder;
|
|
pScreen->CopyWindow = miSpriteCopyWindow;
|
|
pScreen->ClearToBackground = miSpriteClearToBackground;
|
|
|
|
pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
|
|
pScreen->RestoreAreas = miSpriteRestoreAreas;
|
|
#ifdef RENDER
|
|
if (ps)
|
|
{
|
|
ps->Composite = miSpriteComposite;
|
|
ps->Glyphs = miSpriteGlyphs;
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Screen wrappers
|
|
*/
|
|
|
|
/*
|
|
* CloseScreen wrapper -- unwrap everything, free the private data
|
|
* and call the wrapped function
|
|
*/
|
|
|
|
static Bool
|
|
miSpriteCloseScreen (i, pScreen)
|
|
int i;
|
|
ScreenPtr pScreen;
|
|
{
|
|
miSpriteScreenPtr pScreenPriv;
|
|
#ifdef RENDER
|
|
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
|
|
#endif
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
pScreen->CloseScreen = pScreenPriv->CloseScreen;
|
|
pScreen->GetImage = pScreenPriv->GetImage;
|
|
pScreen->GetSpans = pScreenPriv->GetSpans;
|
|
pScreen->SourceValidate = pScreenPriv->SourceValidate;
|
|
pScreen->CreateGC = pScreenPriv->CreateGC;
|
|
pScreen->BlockHandler = pScreenPriv->BlockHandler;
|
|
pScreen->InstallColormap = pScreenPriv->InstallColormap;
|
|
pScreen->StoreColors = pScreenPriv->StoreColors;
|
|
|
|
pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground;
|
|
pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder;
|
|
pScreen->CopyWindow = pScreenPriv->CopyWindow;
|
|
pScreen->ClearToBackground = pScreenPriv->ClearToBackground;
|
|
|
|
pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
|
|
pScreen->RestoreAreas = pScreenPriv->RestoreAreas;
|
|
#ifdef RENDER
|
|
if (ps)
|
|
{
|
|
ps->Composite = pScreenPriv->Composite;
|
|
ps->Glyphs = pScreenPriv->Glyphs;
|
|
}
|
|
#endif
|
|
xfree ((pointer) pScreenPriv);
|
|
|
|
return (*pScreen->CloseScreen) (i, pScreen);
|
|
}
|
|
|
|
static void
|
|
miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
|
|
DrawablePtr pDrawable;
|
|
int sx, sy, w, h;
|
|
unsigned int format;
|
|
unsigned long planemask;
|
|
char *pdstLine;
|
|
{
|
|
ScreenPtr pScreen = pDrawable->pScreen;
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
SCREEN_PROLOGUE (pScreen, GetImage);
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW &&
|
|
pScreenPriv->isUp &&
|
|
ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
|
|
{
|
|
miSpriteRemoveCursor (pScreen);
|
|
}
|
|
|
|
(*pScreen->GetImage) (pDrawable, sx, sy, w, h,
|
|
format, planemask, pdstLine);
|
|
|
|
SCREEN_EPILOGUE (pScreen, GetImage, miSpriteGetImage);
|
|
}
|
|
|
|
static void
|
|
miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
|
|
DrawablePtr pDrawable;
|
|
int wMax;
|
|
DDXPointPtr ppt;
|
|
int *pwidth;
|
|
int nspans;
|
|
char *pdstStart;
|
|
{
|
|
ScreenPtr pScreen = pDrawable->pScreen;
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
SCREEN_PROLOGUE (pScreen, GetSpans);
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
|
|
{
|
|
register DDXPointPtr pts;
|
|
register int *widths;
|
|
register int nPts;
|
|
register int xorg,
|
|
yorg;
|
|
|
|
xorg = pDrawable->x;
|
|
yorg = pDrawable->y;
|
|
|
|
for (pts = ppt, widths = pwidth, nPts = nspans;
|
|
nPts--;
|
|
pts++, widths++)
|
|
{
|
|
if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
|
|
pts->x+xorg,*widths))
|
|
{
|
|
miSpriteRemoveCursor (pScreen);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
(*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
|
|
|
|
SCREEN_EPILOGUE (pScreen, GetSpans, miSpriteGetSpans);
|
|
}
|
|
|
|
static void
|
|
miSpriteSourceValidate (pDrawable, x, y, width, height)
|
|
DrawablePtr pDrawable;
|
|
int x, y, width, height;
|
|
{
|
|
ScreenPtr pScreen = pDrawable->pScreen;
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
SCREEN_PROLOGUE (pScreen, SourceValidate);
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
|
|
ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
|
|
x, y, width, height))
|
|
{
|
|
miSpriteRemoveCursor (pScreen);
|
|
}
|
|
|
|
if (pScreen->SourceValidate)
|
|
(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
|
|
|
|
SCREEN_EPILOGUE (pScreen, SourceValidate, miSpriteSourceValidate);
|
|
}
|
|
|
|
static Bool
|
|
miSpriteCreateGC (pGC)
|
|
GCPtr pGC;
|
|
{
|
|
ScreenPtr pScreen = pGC->pScreen;
|
|
Bool ret;
|
|
miSpriteGCPtr pPriv;
|
|
|
|
SCREEN_PROLOGUE (pScreen, CreateGC);
|
|
|
|
pPriv = (miSpriteGCPtr)pGC->devPrivates[miSpriteGCIndex].ptr;
|
|
|
|
ret = (*pScreen->CreateGC) (pGC);
|
|
|
|
pPriv->wrapOps = NULL;
|
|
pPriv->wrapFuncs = pGC->funcs;
|
|
pGC->funcs = &miSpriteGCFuncs;
|
|
|
|
SCREEN_EPILOGUE (pScreen, CreateGC, miSpriteCreateGC);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
|
|
int i;
|
|
pointer blockData;
|
|
pointer pTimeout;
|
|
pointer pReadmask;
|
|
{
|
|
ScreenPtr pScreen = screenInfo.screens[i];
|
|
miSpriteScreenPtr pPriv;
|
|
|
|
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
SCREEN_PROLOGUE(pScreen, BlockHandler);
|
|
|
|
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
|
|
|
|
SCREEN_EPILOGUE(pScreen, BlockHandler, miSpriteBlockHandler);
|
|
|
|
if (!pPriv->isUp && pPriv->shouldBeUp)
|
|
miSpriteRestoreCursor (pScreen);
|
|
}
|
|
|
|
static void
|
|
miSpriteInstallColormap (pMap)
|
|
ColormapPtr pMap;
|
|
{
|
|
ScreenPtr pScreen = pMap->pScreen;
|
|
miSpriteScreenPtr pPriv;
|
|
|
|
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
SCREEN_PROLOGUE(pScreen, InstallColormap);
|
|
|
|
(*pScreen->InstallColormap) (pMap);
|
|
|
|
SCREEN_EPILOGUE(pScreen, InstallColormap, miSpriteInstallColormap);
|
|
|
|
pPriv->pInstalledMap = pMap;
|
|
if (pPriv->pColormap != pMap)
|
|
{
|
|
pPriv->checkPixels = TRUE;
|
|
if (pPriv->isUp)
|
|
miSpriteRemoveCursor (pScreen);
|
|
}
|
|
}
|
|
|
|
static void
|
|
miSpriteStoreColors (pMap, ndef, pdef)
|
|
ColormapPtr pMap;
|
|
int ndef;
|
|
xColorItem *pdef;
|
|
{
|
|
ScreenPtr pScreen = pMap->pScreen;
|
|
miSpriteScreenPtr pPriv;
|
|
int i;
|
|
int updated;
|
|
VisualPtr pVisual;
|
|
|
|
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
|
|
SCREEN_PROLOGUE(pScreen, StoreColors);
|
|
|
|
(*pScreen->StoreColors) (pMap, ndef, pdef);
|
|
|
|
SCREEN_EPILOGUE(pScreen, StoreColors, miSpriteStoreColors);
|
|
|
|
if (pPriv->pColormap == pMap)
|
|
{
|
|
updated = 0;
|
|
pVisual = pMap->pVisual;
|
|
if (pVisual->class == DirectColor)
|
|
{
|
|
/* 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 (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;
|
|
int x,y;
|
|
int w,h;
|
|
Bool generateExposures;
|
|
{
|
|
ScreenPtr pScreen;
|
|
miSpriteScreenPtr pScreenPriv;
|
|
int realw, realh;
|
|
|
|
pScreen = pWin->drawable.pScreen;
|
|
|
|
SCREEN_PROLOGUE (pScreen, ClearToBackground);
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
if (GC_CHECK(pWin))
|
|
{
|
|
if (!(realw = w))
|
|
realw = (int) pWin->drawable.width - x;
|
|
if (!(realh = h))
|
|
realh = (int) pWin->drawable.height - y;
|
|
if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y,
|
|
x, y, realw, realh))
|
|
{
|
|
miSpriteRemoveCursor (pScreen);
|
|
}
|
|
}
|
|
|
|
(*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
|
|
|
|
SCREEN_EPILOGUE (pScreen, ClearToBackground, miSpriteClearToBackground);
|
|
}
|
|
|
|
/*
|
|
* GC Func wrappers
|
|
*/
|
|
|
|
static void
|
|
miSpriteValidateGC (pGC, changes, pDrawable)
|
|
GCPtr pGC;
|
|
unsigned long changes;
|
|
DrawablePtr pDrawable;
|
|
{
|
|
GC_FUNC_PROLOGUE (pGC);
|
|
|
|
(*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
|
|
|
|
pGCPriv->wrapOps = NULL;
|
|
if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable)
|
|
{
|
|
WindowPtr pWin;
|
|
RegionPtr pRegion;
|
|
|
|
pWin = (WindowPtr) pDrawable;
|
|
pRegion = &pWin->clipList;
|
|
if (pGC->subWindowMode == IncludeInferiors)
|
|
pRegion = &pWin->borderClip;
|
|
if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion))
|
|
pGCPriv->wrapOps = pGC->ops;
|
|
}
|
|
|
|
GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
miSpriteChangeGC (pGC, mask)
|
|
GCPtr pGC;
|
|
unsigned long mask;
|
|
{
|
|
GC_FUNC_PROLOGUE (pGC);
|
|
|
|
(*pGC->funcs->ChangeGC) (pGC, mask);
|
|
|
|
GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
miSpriteCopyGC (pGCSrc, mask, pGCDst)
|
|
GCPtr pGCSrc, pGCDst;
|
|
unsigned long mask;
|
|
{
|
|
GC_FUNC_PROLOGUE (pGCDst);
|
|
|
|
(*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
|
|
|
|
GC_FUNC_EPILOGUE (pGCDst);
|
|
}
|
|
|
|
static void
|
|
miSpriteDestroyGC (pGC)
|
|
GCPtr pGC;
|
|
{
|
|
GC_FUNC_PROLOGUE (pGC);
|
|
|
|
(*pGC->funcs->DestroyGC) (pGC);
|
|
|
|
GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
miSpriteChangeClip (pGC, type, pvalue, nrects)
|
|
GCPtr pGC;
|
|
int type;
|
|
pointer pvalue;
|
|
int nrects;
|
|
{
|
|
GC_FUNC_PROLOGUE (pGC);
|
|
|
|
(*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
|
|
|
|
GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
miSpriteCopyClip(pgcDst, pgcSrc)
|
|
GCPtr pgcDst, pgcSrc;
|
|
{
|
|
GC_FUNC_PROLOGUE (pgcDst);
|
|
|
|
(* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
|
|
|
|
GC_FUNC_EPILOGUE (pgcDst);
|
|
}
|
|
|
|
static void
|
|
miSpriteDestroyClip(pGC)
|
|
GCPtr pGC;
|
|
{
|
|
GC_FUNC_PROLOGUE (pGC);
|
|
|
|
(* pGC->funcs->DestroyClip)(pGC);
|
|
|
|
GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
/*
|
|
* 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 leftPad;
|
|
int format;
|
|
char *pBits;
|
|
{
|
|
GC_SETUP(pDrawable, pGC);
|
|
|
|
if (GC_CHECK((WindowPtr) pDrawable))
|
|
{
|
|
if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,
|
|
x,y,w,h))
|
|
{
|
|
miSpriteRemoveCursor (pDrawable->pScreen);
|
|
}
|
|
}
|
|
|
|
GC_OP_PROLOGUE (pGC);
|
|
|
|
(*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits);
|
|
|
|
GC_OP_EPILOGUE (pGC);
|
|
}
|
|
|
|
static RegionPtr
|
|
miSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
|
|
DrawablePtr pSrc;
|
|
DrawablePtr pDst;
|
|
GCPtr pGC;
|
|
int srcx;
|
|
int srcy;
|
|
int w;
|
|
int h;
|
|
int dstx;
|
|
int dsty;
|
|
{
|
|
RegionPtr rgn;
|
|
|
|
GC_SETUP(pDst, pGC);
|
|
|
|
/* 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 (
|
|
DrawablePtr pDraw,
|
|
FontPtr font,
|
|
int x,
|
|
int y,
|
|
unsigned int n,
|
|
CharInfoPtr *charinfo,
|
|
Bool imageblt,
|
|
unsigned int w,
|
|
BoxPtr cursorBox)
|
|
{
|
|
ExtentInfoRec extents;
|
|
|
|
x += pDraw->x;
|
|
y += pDraw->y;
|
|
|
|
if (FONTMINBOUNDS(font,characterWidth) >= 0)
|
|
{
|
|
/* 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 (
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
unsigned long count,
|
|
char *chars,
|
|
FontEncoding fontEncoding,
|
|
Bool textType,
|
|
BoxPtr cursorBox)
|
|
{
|
|
CharInfoPtr *charinfo;
|
|
register CharInfoPtr *info;
|
|
unsigned long i;
|
|
unsigned int n;
|
|
int w;
|
|
|
|
Bool imageblt;
|
|
|
|
imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
|
|
|
|
charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
|
|
if (!charinfo)
|
|
return x;
|
|
|
|
GetGlyphs(pGC->font, count, (unsigned char *)chars,
|
|
fontEncoding, &i, charinfo);
|
|
n = (unsigned int)i;
|
|
w = 0;
|
|
if (!imageblt)
|
|
for (info = charinfo; i--; info++)
|
|
w += (*info)->metrics.characterWidth;
|
|
|
|
if (n != 0) {
|
|
if (miSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox))
|
|
miSpriteRemoveCursor(pDraw->pScreen);
|
|
|
|
#ifdef AVOID_GLYPHBLT
|
|
/*
|
|
* 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:
|
|
(*pGC->ops->PolyText8)(pDraw, pGC, x, y, (int)count, chars);
|
|
break;
|
|
case TT_IMAGE8:
|
|
(*pGC->ops->ImageText8)(pDraw, pGC, x, y, (int)count, chars);
|
|
break;
|
|
case TT_POLY16:
|
|
(*pGC->ops->PolyText16)(pDraw, pGC, x, y, (int)count,
|
|
(unsigned short *)chars);
|
|
break;
|
|
case TT_IMAGE16:
|
|
(*pGC->ops->ImageText16)(pDraw, pGC, x, y, (int)count,
|
|
(unsigned short *)chars);
|
|
break;
|
|
}
|
|
#else /* 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.
|
|
*/
|
|
if (imageblt) {
|
|
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n, charinfo,
|
|
FONTGLYPHS(pGC->font));
|
|
} else {
|
|
(*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, n, charinfo,
|
|
FONTGLYPHS(pGC->font));
|
|
}
|
|
#endif /* 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
|
|
|
|
#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
|
|
|
|
/*
|
|
* 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;
|
|
int x;
|
|
int y;
|
|
{
|
|
miSpriteScreenPtr pScreenPriv;
|
|
|
|
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
|
|
if (!pCursor)
|
|
{
|
|
pScreenPriv->shouldBeUp = FALSE;
|
|
if (pScreenPriv->isUp)
|
|
miSpriteRemoveCursor (pScreen);
|
|
pScreenPriv->pCursor = 0;
|
|
return;
|
|
}
|
|
pScreenPriv->shouldBeUp = TRUE;
|
|
if (pScreenPriv->x == x &&
|
|
pScreenPriv->y == y &&
|
|
pScreenPriv->pCursor == pCursor &&
|
|
!pScreenPriv->checkPixels)
|
|
{
|
|
return;
|
|
}
|
|
pScreenPriv->x = x;
|
|
pScreenPriv->y = y;
|
|
pScreenPriv->pCacheWin = NullWindow;
|
|
if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
|
|
{
|
|
pScreenPriv->pCursor = pCursor;
|
|
miSpriteFindColors (pScreen);
|
|
}
|
|
if (pScreenPriv->isUp) {
|
|
int sx, sy;
|
|
/*
|
|
* 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;
|
|
}
|