xserver-multidpi/hw/xfree86/shadowfb/shadow.c
Keith Packard 2dc138922b Rename region macros to eliminate screen argument
This is a combination of a huge mechanical patch and a few small
fixups required to finish the job. They were reviewed separately, but
because the server does not build without both pieces, I've merged
them together at this time.

The mechanical changes were performed by running the included
'fix-region' script over the whole tree:

$ git ls-files | grep -v '^fix-' | xargs ./fix-region

And then, the white space errors in the resulting patch were fixed
using the provided fix-patch-whitespace script.

$ sh ./fix-patch-whitespace

Thanks to Jamey Sharp for the mighty fine sed-generating sed script.

The hand-done changes involve removing functions from dix/region.c
that duplicate inline functions in include/regionstr.h, along with
their declarations in regionstr.h, mi.h and mispans.h.

Reviewed-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Keith Packard <keithp@keithp.com>
2010-06-05 18:59:00 -07:00

1730 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"
# include "picturestr.h"
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);
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
);
typedef struct {
ScrnInfoPtr pScrn;
RefreshAreaFuncPtr preRefresh;
RefreshAreaFuncPtr postRefresh;
CloseScreenProcPtr CloseScreen;
CopyWindowProcPtr CopyWindow;
CreateGCProcPtr CreateGC;
ModifyPixmapHeaderProcPtr ModifyPixmapHeader;
CompositeProcPtr Composite;
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;
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
if(!preRefreshArea && !postRefreshArea) return FALSE;
if(!dixRequestPrivate(ShadowGCKey, sizeof(ShadowGCRec)))
return FALSE;
if(!(pPriv = (ShadowScreenPtr)malloc(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;
if(ps) {
pPriv->Composite = ps->Composite;
ps->Composite = ShadowComposite;
}
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);
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
pScreen->CloseScreen = pPriv->CloseScreen;
pScreen->CopyWindow = pPriv->CopyWindow;
pScreen->CreateGC = pPriv->CreateGC;
pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader;
pScrn->EnterVT = pPriv->EnterVT;
pScrn->LeaveVT = pPriv->LeaveVT;
if(ps) {
ps->Composite = pPriv->Composite;
}
free((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) {
RegionNull(&rgnDst);
RegionCopy(&rgnDst, prgn);
RegionTranslate(&rgnDst,
pWin->drawable.x - ptOldOrg.x,
pWin->drawable.y - ptOldOrg.y);
RegionIntersect(&rgnDst, &pWin->borderClip, &rgnDst);
if ((num = RegionNumRects(&rgnDst))) {
if(pPriv->preRefresh)
(*pPriv->preRefresh)(pPriv->pScrn, num, RegionRects(&rgnDst));
} else {
RegionUninit(&rgnDst);
}
}
pScreen->CopyWindow = pPriv->CopyWindow;
(*pScreen->CopyWindow) (pWin, ptOldOrg, prgn);
pScreen->CopyWindow = ShadowCopyWindow;
if (num) {
if (pPriv->postRefresh)
(*pPriv->postRefresh)(pPriv->pScrn, num, RegionRects(&rgnDst));
RegionUninit(&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;
}
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);
}
}
/**********************************************************/
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)malloc(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 {
free(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);
free(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, (RegionExtents(
&((WindowPtr) pDrawable)->winSize))->x1);
BB->y1 =
max(pDrawable->y + y - ascent,
(RegionExtents(
&((WindowPtr) pDrawable)->winSize))->y1);
BB->x2 =
min(pDrawable->x + x + right,
(RegionExtents(
&((WindowPtr) pDrawable)->winSize))->x2);
BB->y2 =
min(pDrawable->y + y + descent,
(RegionExtents(
&((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, (RegionExtents(
&((WindowPtr) pDrawable)->winSize))->x1);
BB->y1 =
max(pDrawable->y + y + BB->y1,
(RegionExtents(
&((WindowPtr) pDrawable)->winSize))->y1);
BB->x2 =
min(pDrawable->x + x + BB->x2,
(RegionExtents(
&((WindowPtr) pDrawable)->winSize))->x2);
BB->y2 =
min(pDrawable->y + y + BB->y2,
(RegionExtents(
&((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 */
};