xserver-multidpi/hw/xfree86/shadowfb/shadow.c

1749 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
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
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 */
};