1746 lines
40 KiB
C
1746 lines
40 KiB
C
/*
|
|
Copyright (C) 1999. The XFree86 Project Inc.
|
|
|
|
Written by Mark Vojkovich (mvojkovi@ucsd.edu)
|
|
|
|
Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com)
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_XORG_CONFIG_H
|
|
#include <xorg-config.h>
|
|
#endif
|
|
|
|
#include <X11/X.h>
|
|
#include <X11/Xproto.h>
|
|
#include "misc.h"
|
|
#include "pixmapstr.h"
|
|
#include "input.h"
|
|
#include <X11/fonts/font.h>
|
|
#include "mi.h"
|
|
#include "scrnintstr.h"
|
|
#include "windowstr.h"
|
|
#include "gcstruct.h"
|
|
#include "dixfontstr.h"
|
|
#include <X11/fonts/fontstruct.h>
|
|
#include "xf86.h"
|
|
#include "xf86str.h"
|
|
#include "shadowfb.h"
|
|
|
|
#ifdef RENDER
|
|
# include "picturestr.h"
|
|
#endif
|
|
|
|
static Bool ShadowCloseScreen (int i, ScreenPtr pScreen);
|
|
static void ShadowCopyWindow(
|
|
WindowPtr pWin,
|
|
DDXPointRec ptOldOrg,
|
|
RegionPtr prgn
|
|
);
|
|
static Bool ShadowCreateGC(GCPtr pGC);
|
|
static Bool ShadowModifyPixmapHeader(
|
|
PixmapPtr pPixmap,
|
|
int width,
|
|
int height,
|
|
int depth,
|
|
int bitsPerPixel,
|
|
int devKind,
|
|
pointer pPixData
|
|
);
|
|
|
|
static Bool ShadowEnterVT(int index, int flags);
|
|
static void ShadowLeaveVT(int index, int flags);
|
|
|
|
#ifdef RENDER
|
|
static void ShadowComposite(
|
|
CARD8 op,
|
|
PicturePtr pSrc,
|
|
PicturePtr pMask,
|
|
PicturePtr pDst,
|
|
INT16 xSrc,
|
|
INT16 ySrc,
|
|
INT16 xMask,
|
|
INT16 yMask,
|
|
INT16 xDst,
|
|
INT16 yDst,
|
|
CARD16 width,
|
|
CARD16 height
|
|
);
|
|
#endif /* RENDER */
|
|
|
|
|
|
typedef struct {
|
|
ScrnInfoPtr pScrn;
|
|
RefreshAreaFuncPtr preRefresh;
|
|
RefreshAreaFuncPtr postRefresh;
|
|
CloseScreenProcPtr CloseScreen;
|
|
CopyWindowProcPtr CopyWindow;
|
|
CreateGCProcPtr CreateGC;
|
|
ModifyPixmapHeaderProcPtr ModifyPixmapHeader;
|
|
#ifdef RENDER
|
|
CompositeProcPtr Composite;
|
|
#endif /* RENDER */
|
|
Bool (*EnterVT)(int, int);
|
|
void (*LeaveVT)(int, int);
|
|
Bool vtSema;
|
|
} ShadowScreenRec, *ShadowScreenPtr;
|
|
|
|
typedef struct {
|
|
GCOps *ops;
|
|
GCFuncs *funcs;
|
|
} ShadowGCRec, *ShadowGCPtr;
|
|
|
|
|
|
static int ShadowScreenKeyIndex;
|
|
static DevPrivateKey ShadowScreenKey = &ShadowScreenKeyIndex;
|
|
static int ShadowGCKeyIndex;
|
|
static DevPrivateKey ShadowGCKey = &ShadowGCKeyIndex;
|
|
|
|
#define GET_SCREEN_PRIVATE(pScreen) \
|
|
(ShadowScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, ShadowScreenKey)
|
|
#define GET_GC_PRIVATE(pGC) \
|
|
(ShadowGCPtr)dixLookupPrivate(&(pGC)->devPrivates, ShadowGCKey)
|
|
|
|
#define SHADOW_GC_FUNC_PROLOGUE(pGC)\
|
|
ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\
|
|
(pGC)->funcs = pGCPriv->funcs;\
|
|
if(pGCPriv->ops)\
|
|
(pGC)->ops = pGCPriv->ops
|
|
|
|
#define SHADOW_GC_FUNC_EPILOGUE(pGC)\
|
|
pGCPriv->funcs = (pGC)->funcs;\
|
|
(pGC)->funcs = &ShadowGCFuncs;\
|
|
if(pGCPriv->ops) {\
|
|
pGCPriv->ops = (pGC)->ops;\
|
|
(pGC)->ops = &ShadowGCOps;\
|
|
}
|
|
|
|
#define SHADOW_GC_OP_PROLOGUE(pGC)\
|
|
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pGC->pScreen); \
|
|
ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\
|
|
GCFuncs *oldFuncs = pGC->funcs;\
|
|
pGC->funcs = pGCPriv->funcs;\
|
|
pGC->ops = pGCPriv->ops
|
|
|
|
|
|
#define SHADOW_GC_OP_EPILOGUE(pGC)\
|
|
pGCPriv->ops = pGC->ops;\
|
|
pGC->funcs = oldFuncs;\
|
|
pGC->ops = &ShadowGCOps
|
|
|
|
#define IS_VISIBLE(pWin) (pPriv->vtSema && \
|
|
(((WindowPtr)pWin)->visibility != VisibilityFullyObscured))
|
|
|
|
#define TRIM_BOX(box, pGC) { \
|
|
BoxPtr extents = &pGC->pCompositeClip->extents;\
|
|
if(box.x1 < extents->x1) box.x1 = extents->x1; \
|
|
if(box.x2 > extents->x2) box.x2 = extents->x2; \
|
|
if(box.y1 < extents->y1) box.y1 = extents->y1; \
|
|
if(box.y2 > extents->y2) box.y2 = extents->y2; \
|
|
}
|
|
|
|
#define TRANSLATE_BOX(box, pDraw) { \
|
|
box.x1 += pDraw->x; \
|
|
box.x2 += pDraw->x; \
|
|
box.y1 += pDraw->y; \
|
|
box.y2 += pDraw->y; \
|
|
}
|
|
|
|
#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
|
|
TRANSLATE_BOX(box, pDraw); \
|
|
TRIM_BOX(box, pGC); \
|
|
}
|
|
|
|
#define BOX_NOT_EMPTY(box) \
|
|
(((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
|
|
|
|
|
|
|
|
Bool
|
|
ShadowFBInit2 (
|
|
ScreenPtr pScreen,
|
|
RefreshAreaFuncPtr preRefreshArea,
|
|
RefreshAreaFuncPtr postRefreshArea
|
|
){
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
ShadowScreenPtr pPriv;
|
|
#ifdef RENDER
|
|
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
|
|
#endif /* RENDER */
|
|
|
|
if(!preRefreshArea && !postRefreshArea) return FALSE;
|
|
|
|
if(!dixRequestPrivate(ShadowGCKey, sizeof(ShadowGCRec)))
|
|
return FALSE;
|
|
|
|
if(!(pPriv = (ShadowScreenPtr)xalloc(sizeof(ShadowScreenRec))))
|
|
return FALSE;
|
|
|
|
dixSetPrivate(&pScreen->devPrivates, ShadowScreenKey, pPriv);
|
|
|
|
pPriv->pScrn = pScrn;
|
|
pPriv->preRefresh = preRefreshArea;
|
|
pPriv->postRefresh = postRefreshArea;
|
|
pPriv->vtSema = TRUE;
|
|
|
|
pPriv->CloseScreen = pScreen->CloseScreen;
|
|
pPriv->CopyWindow = pScreen->CopyWindow;
|
|
pPriv->CreateGC = pScreen->CreateGC;
|
|
pPriv->ModifyPixmapHeader = pScreen->ModifyPixmapHeader;
|
|
|
|
pPriv->EnterVT = pScrn->EnterVT;
|
|
pPriv->LeaveVT = pScrn->LeaveVT;
|
|
|
|
pScreen->CloseScreen = ShadowCloseScreen;
|
|
pScreen->CopyWindow = ShadowCopyWindow;
|
|
pScreen->CreateGC = ShadowCreateGC;
|
|
pScreen->ModifyPixmapHeader = ShadowModifyPixmapHeader;
|
|
|
|
pScrn->EnterVT = ShadowEnterVT;
|
|
pScrn->LeaveVT = ShadowLeaveVT;
|
|
|
|
#ifdef RENDER
|
|
if(ps) {
|
|
pPriv->Composite = ps->Composite;
|
|
ps->Composite = ShadowComposite;
|
|
}
|
|
#endif /* RENDER */
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
ShadowFBInit (
|
|
ScreenPtr pScreen,
|
|
RefreshAreaFuncPtr refreshArea
|
|
){
|
|
return ShadowFBInit2(pScreen, NULL, refreshArea);
|
|
}
|
|
|
|
/**********************************************************/
|
|
|
|
static Bool
|
|
ShadowEnterVT(int index, int flags)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[index];
|
|
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen);
|
|
|
|
if((*pPriv->EnterVT)(index, flags)) {
|
|
pPriv->vtSema = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
ShadowLeaveVT(int index, int flags)
|
|
{
|
|
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(xf86Screens[index]->pScreen);
|
|
|
|
pPriv->vtSema = FALSE;
|
|
|
|
(*pPriv->LeaveVT)(index, flags);
|
|
}
|
|
|
|
/**********************************************************/
|
|
|
|
|
|
static Bool
|
|
ShadowCloseScreen (int i, ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
|
|
#ifdef RENDER
|
|
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
|
|
#endif /* RENDER */
|
|
|
|
pScreen->CloseScreen = pPriv->CloseScreen;
|
|
pScreen->CopyWindow = pPriv->CopyWindow;
|
|
pScreen->CreateGC = pPriv->CreateGC;
|
|
pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader;
|
|
|
|
pScrn->EnterVT = pPriv->EnterVT;
|
|
pScrn->LeaveVT = pPriv->LeaveVT;
|
|
|
|
#ifdef RENDER
|
|
if(ps) {
|
|
ps->Composite = pPriv->Composite;
|
|
}
|
|
#endif /* RENDER */
|
|
|
|
xfree((pointer)pPriv);
|
|
|
|
return (*pScreen->CloseScreen) (i, pScreen);
|
|
}
|
|
|
|
static void
|
|
ShadowCopyWindow(
|
|
WindowPtr pWin,
|
|
DDXPointRec ptOldOrg,
|
|
RegionPtr prgn
|
|
){
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
|
|
int num = 0;
|
|
RegionRec rgnDst;
|
|
|
|
if (pPriv->vtSema) {
|
|
REGION_NULL(pWin->drawable.pScreen, &rgnDst);
|
|
REGION_COPY(pWin->drawable.pScreen, &rgnDst, prgn);
|
|
|
|
REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst,
|
|
pWin->drawable.x - ptOldOrg.x,
|
|
pWin->drawable.y - ptOldOrg.y);
|
|
REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, &rgnDst);
|
|
if ((num = REGION_NUM_RECTS(&rgnDst))) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst));
|
|
} else {
|
|
REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
|
|
}
|
|
}
|
|
|
|
pScreen->CopyWindow = pPriv->CopyWindow;
|
|
(*pScreen->CopyWindow) (pWin, ptOldOrg, prgn);
|
|
pScreen->CopyWindow = ShadowCopyWindow;
|
|
|
|
if (num) {
|
|
if (pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst));
|
|
REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
|
|
}
|
|
}
|
|
|
|
static Bool
|
|
ShadowModifyPixmapHeader(
|
|
PixmapPtr pPixmap,
|
|
int width,
|
|
int height,
|
|
int depth,
|
|
int bitsPerPixel,
|
|
int devKind,
|
|
pointer pPixData
|
|
)
|
|
{
|
|
ScreenPtr pScreen;
|
|
ScrnInfoPtr pScrn;
|
|
ShadowScreenPtr pPriv;
|
|
Bool retval;
|
|
PixmapPtr pScreenPix;
|
|
|
|
if (!pPixmap)
|
|
return FALSE;
|
|
|
|
pScreen = pPixmap->drawable.pScreen;
|
|
pScrn = xf86Screens[pScreen->myNum];
|
|
|
|
pScreenPix = (*pScreen->GetScreenPixmap)(pScreen);
|
|
|
|
if (pPixmap == pScreenPix && !pScrn->vtSema)
|
|
pScreenPix->devPrivate = pScrn->pixmapPrivate;
|
|
|
|
pPriv = GET_SCREEN_PRIVATE(pScreen);
|
|
|
|
pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader;
|
|
retval = (*pScreen->ModifyPixmapHeader)(pPixmap,
|
|
width, height, depth, bitsPerPixel, devKind, pPixData);
|
|
pScreen->ModifyPixmapHeader = ShadowModifyPixmapHeader;
|
|
|
|
if (pPixmap == pScreenPix && !pScrn->vtSema)
|
|
{
|
|
pScrn->pixmapPrivate = pScreenPix->devPrivate;
|
|
pScreenPix->devPrivate.ptr = 0;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
#ifdef RENDER
|
|
static void
|
|
ShadowComposite(
|
|
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;
|
|
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
|
|
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
|
BoxRec box;
|
|
BoxPtr extents;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
if (pPriv->vtSema
|
|
&& pDst->pDrawable->type == DRAWABLE_WINDOW) {
|
|
|
|
box.x1 = pDst->pDrawable->x + xDst;
|
|
box.y1 = pDst->pDrawable->y + yDst;
|
|
box.x2 = box.x1 + width;
|
|
box.y2 = box.y1 + height;
|
|
|
|
extents = &pDst->pCompositeClip->extents;
|
|
if(box.x1 < extents->x1) box.x1 = extents->x1;
|
|
if(box.x2 > extents->x2) box.x2 = extents->x2;
|
|
if(box.y1 < extents->y1) box.y1 = extents->y1;
|
|
if(box.y2 > extents->y2) box.y2 = extents->y2;
|
|
|
|
if (BOX_NOT_EMPTY(box)) {
|
|
if (pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
ps->Composite = pPriv->Composite;
|
|
(*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
|
|
xMask, yMask, xDst, yDst, width, height);
|
|
ps->Composite = ShadowComposite;
|
|
|
|
if (pPriv->postRefresh && boxNotEmpty) {
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
}
|
|
}
|
|
#endif /* RENDER */
|
|
|
|
/**********************************************************/
|
|
|
|
static void ShadowValidateGC(GCPtr, unsigned long, DrawablePtr);
|
|
static void ShadowChangeGC(GCPtr, unsigned long);
|
|
static void ShadowCopyGC(GCPtr, unsigned long, GCPtr);
|
|
static void ShadowDestroyGC(GCPtr);
|
|
static void ShadowChangeClip(GCPtr, int, pointer, int);
|
|
static void ShadowDestroyClip(GCPtr);
|
|
static void ShadowCopyClip(GCPtr, GCPtr);
|
|
|
|
GCFuncs ShadowGCFuncs = {
|
|
ShadowValidateGC, ShadowChangeGC, ShadowCopyGC, ShadowDestroyGC,
|
|
ShadowChangeClip, ShadowDestroyClip, ShadowCopyClip
|
|
};
|
|
|
|
|
|
extern GCOps ShadowGCOps;
|
|
|
|
static Bool
|
|
ShadowCreateGC(GCPtr pGC)
|
|
{
|
|
ScreenPtr pScreen = pGC->pScreen;
|
|
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
|
|
ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);
|
|
Bool ret;
|
|
|
|
pScreen->CreateGC = pPriv->CreateGC;
|
|
if((ret = (*pScreen->CreateGC) (pGC))) {
|
|
pGCPriv->ops = NULL;
|
|
pGCPriv->funcs = pGC->funcs;
|
|
pGC->funcs = &ShadowGCFuncs;
|
|
}
|
|
pScreen->CreateGC = ShadowCreateGC;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static void
|
|
ShadowValidateGC(
|
|
GCPtr pGC,
|
|
unsigned long changes,
|
|
DrawablePtr pDraw
|
|
){
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
|
|
if(pDraw->type == DRAWABLE_WINDOW)
|
|
pGCPriv->ops = pGC->ops; /* just so it's not NULL */
|
|
else
|
|
pGCPriv->ops = NULL;
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
|
|
static void
|
|
ShadowDestroyGC(GCPtr pGC)
|
|
{
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(*pGC->funcs->DestroyGC)(pGC);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowChangeGC (
|
|
GCPtr pGC,
|
|
unsigned long mask
|
|
){
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(*pGC->funcs->ChangeGC) (pGC, mask);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowCopyGC (
|
|
GCPtr pGCSrc,
|
|
unsigned long mask,
|
|
GCPtr pGCDst
|
|
){
|
|
SHADOW_GC_FUNC_PROLOGUE (pGCDst);
|
|
(*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGCDst);
|
|
}
|
|
|
|
static void
|
|
ShadowChangeClip (
|
|
GCPtr pGC,
|
|
int type,
|
|
pointer pvalue,
|
|
int nrects
|
|
){
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
|
|
{
|
|
SHADOW_GC_FUNC_PROLOGUE (pgcDst);
|
|
(* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
|
|
SHADOW_GC_FUNC_EPILOGUE (pgcDst);
|
|
}
|
|
|
|
static void
|
|
ShadowDestroyClip(GCPtr pGC)
|
|
{
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(* pGC->funcs->DestroyClip)(pGC);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**********************************************************/
|
|
|
|
|
|
static void
|
|
ShadowFillSpans(
|
|
DrawablePtr pDraw,
|
|
GC *pGC,
|
|
int nInit,
|
|
DDXPointPtr pptInit,
|
|
int *pwidthInit,
|
|
int fSorted
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nInit) {
|
|
DDXPointPtr ppt = pptInit;
|
|
int *pwidth = pwidthInit;
|
|
int i = nInit;
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
box.x1 = ppt->x;
|
|
box.x2 = box.x1 + *pwidth;
|
|
box.y2 = box.y1 = ppt->y;
|
|
|
|
while(--i) {
|
|
ppt++;
|
|
pwidth++;
|
|
if(box.x1 > ppt->x) box.x1 = ppt->x;
|
|
if(box.x2 < (ppt->x + *pwidth))
|
|
box.x2 = ppt->x + *pwidth;
|
|
if(box.y1 > ppt->y) box.y1 = ppt->y;
|
|
else if(box.y2 < ppt->y) box.y2 = ppt->y;
|
|
}
|
|
|
|
box.y2++;
|
|
|
|
if(!pGC->miTranslate) {
|
|
TRANSLATE_BOX(box, pDraw);
|
|
}
|
|
TRIM_BOX(box, pGC);
|
|
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
|
|
(*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
} else
|
|
(*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowSetSpans(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
char *pcharsrc,
|
|
DDXPointPtr pptInit,
|
|
int *pwidthInit,
|
|
int nspans,
|
|
int fSorted
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nspans) {
|
|
DDXPointPtr ppt = pptInit;
|
|
int *pwidth = pwidthInit;
|
|
int i = nspans;
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
box.x1 = ppt->x;
|
|
box.x2 = box.x1 + *pwidth;
|
|
box.y2 = box.y1 = ppt->y;
|
|
|
|
while(--i) {
|
|
ppt++;
|
|
pwidth++;
|
|
if(box.x1 > ppt->x) box.x1 = ppt->x;
|
|
if(box.x2 < (ppt->x + *pwidth))
|
|
box.x2 = ppt->x + *pwidth;
|
|
if(box.y1 > ppt->y) box.y1 = ppt->y;
|
|
else if(box.y2 < ppt->y) box.y2 = ppt->y;
|
|
}
|
|
|
|
box.y2++;
|
|
|
|
if(!pGC->miTranslate) {
|
|
TRANSLATE_BOX(box, pDraw);
|
|
}
|
|
TRIM_BOX(box, pGC);
|
|
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
|
|
(*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
|
|
pwidthInit, nspans, fSorted);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
} else
|
|
(*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
|
|
pwidthInit, nspans, fSorted);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowPutImage(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int depth,
|
|
int x, int y, int w, int h,
|
|
int leftPad,
|
|
int format,
|
|
char *pImage
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw)) {
|
|
box.x1 = x + pDraw->x;
|
|
box.x2 = box.x1 + w;
|
|
box.y1 = y + pDraw->y;
|
|
box.y2 = box.y1 + h;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h,
|
|
leftPad, format, pImage);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
|
|
}
|
|
|
|
static RegionPtr
|
|
ShadowCopyArea(
|
|
DrawablePtr pSrc,
|
|
DrawablePtr pDst,
|
|
GC *pGC,
|
|
int srcx, int srcy,
|
|
int width, int height,
|
|
int dstx, int dsty
|
|
){
|
|
RegionPtr ret;
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDst)) {
|
|
box.x1 = dstx + pDst->x;
|
|
box.x2 = box.x1 + width;
|
|
box.y1 = dsty + pDst->y;
|
|
box.y2 = box.y1 + height;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
ret = (*pGC->ops->CopyArea)(pSrc, pDst,
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static RegionPtr
|
|
ShadowCopyPlane(
|
|
DrawablePtr pSrc,
|
|
DrawablePtr pDst,
|
|
GCPtr pGC,
|
|
int srcx, int srcy,
|
|
int width, int height,
|
|
int dstx, int dsty,
|
|
unsigned long bitPlane
|
|
){
|
|
RegionPtr ret;
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDst)) {
|
|
box.x1 = dstx + pDst->x;
|
|
box.x2 = box.x1 + width;
|
|
box.y1 = dsty + pDst->y;
|
|
box.y2 = box.y1 + height;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
|
|
pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
ShadowPolyPoint(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int mode,
|
|
int nptInit,
|
|
xPoint *pptInit
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nptInit) {
|
|
xPoint *ppt = pptInit;
|
|
int npt = nptInit;
|
|
|
|
box.x2 = box.x1 = pptInit->x;
|
|
box.y2 = box.y1 = pptInit->y;
|
|
|
|
/* this could be slow if the points were spread out */
|
|
|
|
while(--npt) {
|
|
ppt++;
|
|
if(box.x1 > ppt->x) box.x1 = ppt->x;
|
|
else if(box.x2 < ppt->x) box.x2 = ppt->x;
|
|
if(box.y1 > ppt->y) box.y1 = ppt->y;
|
|
else if(box.y2 < ppt->y) box.y2 = ppt->y;
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->PolyPoint)(pDraw, pGC, mode, nptInit, pptInit);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowPolylines(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int mode,
|
|
int nptInit,
|
|
DDXPointPtr pptInit
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nptInit) {
|
|
DDXPointPtr ppt = pptInit;
|
|
int npt = nptInit;
|
|
int extra = pGC->lineWidth >> 1;
|
|
|
|
box.x2 = box.x1 = pptInit->x;
|
|
box.y2 = box.y1 = pptInit->y;
|
|
|
|
if(npt > 1) {
|
|
if(pGC->joinStyle == JoinMiter)
|
|
extra = 6 * pGC->lineWidth;
|
|
else if(pGC->capStyle == CapProjecting)
|
|
extra = pGC->lineWidth;
|
|
}
|
|
|
|
if(mode == CoordModePrevious) {
|
|
int x = box.x1;
|
|
int y = box.y1;
|
|
while(--npt) {
|
|
ppt++;
|
|
x += ppt->x;
|
|
y += ppt->y;
|
|
if(box.x1 > x) box.x1 = x;
|
|
else if(box.x2 < x) box.x2 = x;
|
|
if(box.y1 > y) box.y1 = y;
|
|
else if(box.y2 < y) box.y2 = y;
|
|
}
|
|
} else {
|
|
while(--npt) {
|
|
ppt++;
|
|
if(box.x1 > ppt->x) box.x1 = ppt->x;
|
|
else if(box.x2 < ppt->x) box.x2 = ppt->x;
|
|
if(box.y1 > ppt->y) box.y1 = ppt->y;
|
|
else if(box.y2 < ppt->y) box.y2 = ppt->y;
|
|
}
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
if(extra) {
|
|
box.x1 -= extra;
|
|
box.x2 += extra;
|
|
box.y1 -= extra;
|
|
box.y2 += extra;
|
|
}
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->Polylines)(pDraw, pGC, mode, nptInit, pptInit);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowPolySegment(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int nsegInit,
|
|
xSegment *pSegInit
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nsegInit) {
|
|
int extra = pGC->lineWidth;
|
|
xSegment *pSeg = pSegInit;
|
|
int nseg = nsegInit;
|
|
|
|
if(pGC->capStyle != CapProjecting)
|
|
extra >>= 1;
|
|
|
|
if(pSeg->x2 > pSeg->x1) {
|
|
box.x1 = pSeg->x1;
|
|
box.x2 = pSeg->x2;
|
|
} else {
|
|
box.x2 = pSeg->x1;
|
|
box.x1 = pSeg->x2;
|
|
}
|
|
|
|
if(pSeg->y2 > pSeg->y1) {
|
|
box.y1 = pSeg->y1;
|
|
box.y2 = pSeg->y2;
|
|
} else {
|
|
box.y2 = pSeg->y1;
|
|
box.y1 = pSeg->y2;
|
|
}
|
|
|
|
while(--nseg) {
|
|
pSeg++;
|
|
if(pSeg->x2 > pSeg->x1) {
|
|
if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
|
|
if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
|
|
} else {
|
|
if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
|
|
if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
|
|
}
|
|
if(pSeg->y2 > pSeg->y1) {
|
|
if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
|
|
if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
|
|
} else {
|
|
if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
|
|
if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
|
|
}
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
if(extra) {
|
|
box.x1 -= extra;
|
|
box.x2 += extra;
|
|
box.y1 -= extra;
|
|
box.y2 += extra;
|
|
}
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->PolySegment)(pDraw, pGC, nsegInit, pSegInit);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowPolyRectangle(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int nRectsInit,
|
|
xRectangle *pRectsInit
|
|
){
|
|
BoxRec box;
|
|
BoxPtr pBoxInit = NULL;
|
|
Bool boxNotEmpty = FALSE;
|
|
int num = 0;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nRectsInit) {
|
|
xRectangle *pRects = pRectsInit;
|
|
int nRects = nRectsInit;
|
|
|
|
if(nRects >= 32) {
|
|
int extra = pGC->lineWidth >> 1;
|
|
|
|
box.x1 = pRects->x;
|
|
box.x2 = box.x1 + pRects->width;
|
|
box.y1 = pRects->y;
|
|
box.y2 = box.y1 + pRects->height;
|
|
|
|
while(--nRects) {
|
|
pRects++;
|
|
if(box.x1 > pRects->x) box.x1 = pRects->x;
|
|
if(box.x2 < (pRects->x + pRects->width))
|
|
box.x2 = pRects->x + pRects->width;
|
|
if(box.y1 > pRects->y) box.y1 = pRects->y;
|
|
if(box.y2 < (pRects->y + pRects->height))
|
|
box.y2 = pRects->y + pRects->height;
|
|
}
|
|
|
|
if(extra) {
|
|
box.x1 -= extra;
|
|
box.x2 += extra;
|
|
box.y1 -= extra;
|
|
box.y2 += extra;
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
} else {
|
|
BoxPtr pbox;
|
|
int offset1, offset2, offset3;
|
|
|
|
offset2 = pGC->lineWidth;
|
|
if(!offset2) offset2 = 1;
|
|
offset1 = offset2 >> 1;
|
|
offset3 = offset2 - offset1;
|
|
|
|
pBoxInit = (BoxPtr)xalloc(nRects * 4 * sizeof(BoxRec));
|
|
pbox = pBoxInit;
|
|
|
|
while(nRects--) {
|
|
pbox->x1 = pRects->x - offset1;
|
|
pbox->y1 = pRects->y - offset1;
|
|
pbox->x2 = pbox->x1 + pRects->width + offset2;
|
|
pbox->y2 = pbox->y1 + offset2;
|
|
TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
|
|
if(BOX_NOT_EMPTY((*pbox))) {
|
|
num++;
|
|
pbox++;
|
|
}
|
|
|
|
pbox->x1 = pRects->x - offset1;
|
|
pbox->y1 = pRects->y + offset3;
|
|
pbox->x2 = pbox->x1 + offset2;
|
|
pbox->y2 = pbox->y1 + pRects->height - offset2;
|
|
TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
|
|
if(BOX_NOT_EMPTY((*pbox))) {
|
|
num++;
|
|
pbox++;
|
|
}
|
|
|
|
pbox->x1 = pRects->x + pRects->width - offset1;
|
|
pbox->y1 = pRects->y + offset3;
|
|
pbox->x2 = pbox->x1 + offset2;
|
|
pbox->y2 = pbox->y1 + pRects->height - offset2;
|
|
TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
|
|
if(BOX_NOT_EMPTY((*pbox))) {
|
|
num++;
|
|
pbox++;
|
|
}
|
|
|
|
pbox->x1 = pRects->x - offset1;
|
|
pbox->y1 = pRects->y + pRects->height - offset1;
|
|
pbox->x2 = pbox->x1 + pRects->width + offset2;
|
|
pbox->y2 = pbox->y1 + offset2;
|
|
TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
|
|
if(BOX_NOT_EMPTY((*pbox))) {
|
|
num++;
|
|
pbox++;
|
|
}
|
|
|
|
pRects++;
|
|
}
|
|
|
|
if(num) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, num, pBoxInit);
|
|
} else {
|
|
xfree(pBoxInit);
|
|
}
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh) {
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
} else if(num) {
|
|
if(pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, num, pBoxInit);
|
|
xfree(pBoxInit);
|
|
}
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
|
|
}
|
|
|
|
static void
|
|
ShadowPolyArc(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int narcsInit,
|
|
xArc *parcsInit
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && narcsInit) {
|
|
int narcs = narcsInit;
|
|
xArc *parcs = parcsInit;
|
|
int extra = pGC->lineWidth >> 1;
|
|
|
|
box.x1 = parcs->x;
|
|
box.x2 = box.x1 + parcs->width;
|
|
box.y1 = parcs->y;
|
|
box.y2 = box.y1 + parcs->height;
|
|
|
|
/* should I break these up instead ? */
|
|
|
|
while(--narcs) {
|
|
parcs++;
|
|
if(box.x1 > parcs->x) box.x1 = parcs->x;
|
|
if(box.x2 < (parcs->x + parcs->width))
|
|
box.x2 = parcs->x + parcs->width;
|
|
if(box.y1 > parcs->y) box.y1 = parcs->y;
|
|
if(box.y2 < (parcs->y + parcs->height))
|
|
box.y2 = parcs->y + parcs->height;
|
|
}
|
|
|
|
if(extra) {
|
|
box.x1 -= extra;
|
|
box.x2 += extra;
|
|
box.y1 -= extra;
|
|
box.y2 += extra;
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->PolyArc)(pDraw, pGC, narcsInit, parcsInit);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
|
|
}
|
|
|
|
static void
|
|
ShadowFillPolygon(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int shape,
|
|
int mode,
|
|
int count,
|
|
DDXPointPtr pptInit
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && (count > 2)) {
|
|
DDXPointPtr ppt = pptInit;
|
|
int i = count;
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
box.x2 = box.x1 = ppt->x;
|
|
box.y2 = box.y1 = ppt->y;
|
|
|
|
if(mode != CoordModeOrigin) {
|
|
int x = box.x1;
|
|
int y = box.y1;
|
|
while(--i) {
|
|
ppt++;
|
|
x += ppt->x;
|
|
y += ppt->y;
|
|
if(box.x1 > x) box.x1 = x;
|
|
else if(box.x2 < x) box.x2 = x;
|
|
if(box.y1 > y) box.y1 = y;
|
|
else if(box.y2 < y) box.y2 = y;
|
|
}
|
|
} else {
|
|
while(--i) {
|
|
ppt++;
|
|
if(box.x1 > ppt->x) box.x1 = ppt->x;
|
|
else if(box.x2 < ppt->x) box.x2 = ppt->x;
|
|
if(box.y1 > ppt->y) box.y1 = ppt->y;
|
|
else if(box.y2 < ppt->y) box.y2 = ppt->y;
|
|
}
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
|
|
(*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
} else
|
|
(*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
|
|
static void
|
|
ShadowPolyFillRect(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int nRectsInit,
|
|
xRectangle *pRectsInit
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nRectsInit) {
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
xRectangle *pRects = pRectsInit;
|
|
int nRects = nRectsInit;
|
|
|
|
box.x1 = pRects->x;
|
|
box.x2 = box.x1 + pRects->width;
|
|
box.y1 = pRects->y;
|
|
box.y2 = box.y1 + pRects->height;
|
|
|
|
while(--nRects) {
|
|
pRects++;
|
|
if(box.x1 > pRects->x) box.x1 = pRects->x;
|
|
if(box.x2 < (pRects->x + pRects->width))
|
|
box.x2 = pRects->x + pRects->width;
|
|
if(box.y1 > pRects->y) box.y1 = pRects->y;
|
|
if(box.y2 < (pRects->y + pRects->height))
|
|
box.y2 = pRects->y + pRects->height;
|
|
}
|
|
|
|
/* cfb messes with the pRectsInit so we have to do our
|
|
calculations first */
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
|
|
(*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
} else
|
|
(*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
|
|
static void
|
|
ShadowPolyFillArc(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int narcsInit,
|
|
xArc *parcsInit
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && narcsInit) {
|
|
xArc *parcs = parcsInit;
|
|
int narcs = narcsInit;
|
|
|
|
box.x1 = parcs->x;
|
|
box.x2 = box.x1 + parcs->width;
|
|
box.y1 = parcs->y;
|
|
box.y2 = box.y1 + parcs->height;
|
|
|
|
/* should I break these up instead ? */
|
|
|
|
while(--narcs) {
|
|
parcs++;
|
|
if(box.x1 > parcs->x) box.x1 = parcs->x;
|
|
if(box.x2 < (parcs->x + parcs->width))
|
|
box.x2 = parcs->x + parcs->width;
|
|
if(box.y1 > parcs->y) box.y1 = parcs->y;
|
|
if(box.y2 < (parcs->y + parcs->height))
|
|
box.y2 = parcs->y + parcs->height;
|
|
}
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->PolyFillArc)(pDraw, pGC, narcsInit, parcsInit);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowTextExtent(FontPtr pFont, int count, char* chars,
|
|
FontEncoding fontEncoding, BoxPtr box)
|
|
{
|
|
unsigned long n, i;
|
|
int w;
|
|
CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */
|
|
|
|
GetGlyphs(pFont, (unsigned long)count, (unsigned char *)chars,
|
|
fontEncoding, &n, charinfo);
|
|
w = 0;
|
|
for (i=0; i < n; i++) {
|
|
w += charinfo[i]->metrics.characterWidth;
|
|
}
|
|
if (i) {
|
|
w += charinfo[i - 1]->metrics.rightSideBearing;
|
|
}
|
|
|
|
box->x1 = 0;
|
|
if (n) {
|
|
if (charinfo[0]->metrics.leftSideBearing < 0) {
|
|
box->x1 = charinfo[0]->metrics.leftSideBearing;
|
|
}
|
|
}
|
|
box->x2 = w;
|
|
box->y1 = -FONTMAXBOUNDS(pFont,ascent);
|
|
box->y2 = FONTMAXBOUNDS(pFont,descent);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
ShadowFontToBox(BoxPtr BB, DrawablePtr pDrawable, GCPtr pGC, int x, int y,
|
|
int count, char *chars, int wide)
|
|
{
|
|
FontPtr pFont;
|
|
|
|
pFont = pGC->font;
|
|
if (pFont->info.constantWidth) {
|
|
int ascent, descent, left, right = 0;
|
|
|
|
ascent = max(pFont->info.fontAscent, pFont->info.maxbounds.ascent);
|
|
descent = max(pFont->info.fontDescent, pFont->info.maxbounds.descent);
|
|
left = pFont->info.maxbounds.leftSideBearing;
|
|
if (count > 0) {
|
|
right = (count - 1) * pFont->info.maxbounds.characterWidth;
|
|
}
|
|
right += pFont->info.maxbounds.rightSideBearing;
|
|
BB->x1 =
|
|
max(pDrawable->x + x - left, (REGION_EXTENTS(pGC->pScreen,
|
|
&((WindowPtr) pDrawable)->winSize))->x1);
|
|
BB->y1 =
|
|
max(pDrawable->y + y - ascent,
|
|
(REGION_EXTENTS(pGC->pScreen,
|
|
&((WindowPtr) pDrawable)->winSize))->y1);
|
|
BB->x2 =
|
|
min(pDrawable->x + x + right,
|
|
(REGION_EXTENTS(pGC->pScreen,
|
|
&((WindowPtr) pDrawable)->winSize))->x2);
|
|
BB->y2 =
|
|
min(pDrawable->y + y + descent,
|
|
(REGION_EXTENTS(pGC->pScreen,
|
|
&((WindowPtr) pDrawable)->winSize))->y2);
|
|
} else {
|
|
ShadowTextExtent(pFont, count, chars, wide ? (FONTLASTROW(pFont) == 0)
|
|
? Linear16Bit : TwoD16Bit : Linear8Bit, BB);
|
|
BB->x1 =
|
|
max(pDrawable->x + x + BB->x1, (REGION_EXTENTS(pGC->pScreen,
|
|
&((WindowPtr) pDrawable)->winSize))->x1);
|
|
BB->y1 =
|
|
max(pDrawable->y + y + BB->y1,
|
|
(REGION_EXTENTS(pGC->pScreen,
|
|
&((WindowPtr) pDrawable)->winSize))->y1);
|
|
BB->x2 =
|
|
min(pDrawable->x + x + BB->x2,
|
|
(REGION_EXTENTS(pGC->pScreen,
|
|
&((WindowPtr) pDrawable)->winSize))->x2);
|
|
BB->y2 =
|
|
min(pDrawable->y + y + BB->y2,
|
|
(REGION_EXTENTS(pGC->pScreen,
|
|
&((WindowPtr) pDrawable)->winSize))->y2);
|
|
}
|
|
}
|
|
|
|
static int
|
|
ShadowPolyText8(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
char *chars
|
|
){
|
|
int width;
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw)) {
|
|
ShadowFontToBox(&box, pDraw, pGC, x, y, count, chars, 0);
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
|
|
return width;
|
|
}
|
|
|
|
static int
|
|
ShadowPolyText16(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
unsigned short *chars
|
|
){
|
|
int width;
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw)) {
|
|
ShadowFontToBox(&box, pDraw, pGC, x, y, count, (char*)chars, 1);
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
|
|
return width;
|
|
}
|
|
|
|
static void
|
|
ShadowImageText8(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
char *chars
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && count) {
|
|
int top, bot, Min, Max;
|
|
|
|
top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
|
|
bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
|
|
|
|
Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
|
|
if(Min > 0) Min = 0;
|
|
Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
|
|
if(Max < 0) Max = 0;
|
|
|
|
/* ugh */
|
|
box.x1 = pDraw->x + x + Min +
|
|
FONTMINBOUNDS(pGC->font, leftSideBearing);
|
|
box.x2 = pDraw->x + x + Max +
|
|
FONTMAXBOUNDS(pGC->font, rightSideBearing);
|
|
|
|
box.y1 = pDraw->y + y - top;
|
|
box.y2 = pDraw->y + y + bot;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
static void
|
|
ShadowImageText16(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
unsigned short *chars
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && count) {
|
|
int top, bot, Min, Max;
|
|
|
|
top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
|
|
bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
|
|
|
|
Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
|
|
if(Min > 0) Min = 0;
|
|
Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
|
|
if(Max < 0) Max = 0;
|
|
|
|
/* ugh */
|
|
box.x1 = pDraw->x + x + Min +
|
|
FONTMINBOUNDS(pGC->font, leftSideBearing);
|
|
box.x2 = pDraw->x + x + Max +
|
|
FONTMAXBOUNDS(pGC->font, rightSideBearing);
|
|
|
|
box.y1 = pDraw->y + y - top;
|
|
box.y2 = pDraw->y + y + bot;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
|
|
static void
|
|
ShadowImageGlyphBlt(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x, int y,
|
|
unsigned int nglyphInit,
|
|
CharInfoPtr *ppciInit,
|
|
pointer pglyphBase
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nglyphInit) {
|
|
CharInfoPtr *ppci = ppciInit;
|
|
unsigned int nglyph = nglyphInit;
|
|
int top, bot, width = 0;
|
|
|
|
top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
|
|
bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
|
|
|
|
box.x1 = ppci[0]->metrics.leftSideBearing;
|
|
if(box.x1 > 0) box.x1 = 0;
|
|
box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
|
|
ppci[nglyph - 1]->metrics.characterWidth;
|
|
if(box.x2 < 0) box.x2 = 0;
|
|
|
|
box.x2 += pDraw->x + x;
|
|
box.x1 += pDraw->x + x;
|
|
|
|
while(nglyph--) {
|
|
width += (*ppci)->metrics.characterWidth;
|
|
ppci++;
|
|
}
|
|
|
|
if(width > 0)
|
|
box.x2 += width;
|
|
else
|
|
box.x1 += width;
|
|
|
|
box.y1 = pDraw->y + y - top;
|
|
box.y2 = pDraw->y + y + bot;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyphInit,
|
|
ppciInit, pglyphBase);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowPolyGlyphBlt(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x, int y,
|
|
unsigned int nglyphInit,
|
|
CharInfoPtr *ppciInit,
|
|
pointer pglyphBase
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw) && nglyphInit) {
|
|
CharInfoPtr *ppci = ppciInit;
|
|
unsigned int nglyph = nglyphInit;
|
|
|
|
/* ugh */
|
|
box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing;
|
|
box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
|
|
|
|
if(nglyph > 1) {
|
|
int width = 0;
|
|
|
|
while(--nglyph) {
|
|
width += (*ppci)->metrics.characterWidth;
|
|
ppci++;
|
|
}
|
|
|
|
if(width > 0) box.x2 += width;
|
|
else box.x1 += width;
|
|
}
|
|
|
|
box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
|
|
box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyphInit,
|
|
ppciInit, pglyphBase);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
static void
|
|
ShadowPushPixels(
|
|
GCPtr pGC,
|
|
PixmapPtr pBitMap,
|
|
DrawablePtr pDraw,
|
|
int dx, int dy, int xOrg, int yOrg
|
|
){
|
|
BoxRec box;
|
|
Bool boxNotEmpty = FALSE;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC);
|
|
|
|
if(IS_VISIBLE(pDraw)) {
|
|
box.x1 = xOrg;
|
|
box.y1 = yOrg;
|
|
|
|
if(!pGC->miTranslate) {
|
|
box.x1 += pDraw->x;
|
|
box.y1 += pDraw->y;
|
|
}
|
|
|
|
box.x2 = box.x1 + dx;
|
|
box.y2 = box.y1 + dy;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box)) {
|
|
if(pPriv->preRefresh)
|
|
(*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
|
|
boxNotEmpty = TRUE;
|
|
}
|
|
}
|
|
|
|
(*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
|
|
|
|
if(boxNotEmpty && pPriv->postRefresh)
|
|
(*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC);
|
|
}
|
|
|
|
|
|
GCOps ShadowGCOps = {
|
|
ShadowFillSpans, ShadowSetSpans,
|
|
ShadowPutImage, ShadowCopyArea,
|
|
ShadowCopyPlane, ShadowPolyPoint,
|
|
ShadowPolylines, ShadowPolySegment,
|
|
ShadowPolyRectangle, ShadowPolyArc,
|
|
ShadowFillPolygon, ShadowPolyFillRect,
|
|
ShadowPolyFillArc, ShadowPolyText8,
|
|
ShadowPolyText16, ShadowImageText8,
|
|
ShadowImageText16, ShadowImageGlyphBlt,
|
|
ShadowPolyGlyphBlt, ShadowPushPixels,
|
|
{NULL} /* devPrivate */
|
|
};
|
|
|