xserver-multidpi/hw/xfree86/shadowfb/shadow.c
Chris Wilson 5c6a2f93eb xfree86: Kill pixmapPrivate with a vengeance (v2)
ScrnInfo->pixmapPrivate only existed in order to catch invalid access to
the framebuffer by making the backing data NULL across the VT switch.
This was causing more confusion in the higher layers during mode setting
without any real benefit, so remove it.

v2: Kill ShadowModifyPixmapHeader() as well.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Julien Cristau <jcristau@debian.org>
Cc: Andrew Guertin <lists@dolphinling.net>
Reviewed-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2010-09-28 08:07:21 -07:00

1682 lines
39 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 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 DevPrivateKeyRec ShadowScreenKeyRec;
#define ShadowScreenKey (&ShadowScreenKeyRec)
static DevPrivateKeyRec ShadowGCKeyRec;
#define ShadowGCKey (&ShadowGCKeyRec)
#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 (!dixRegisterPrivateKey(&ShadowScreenKeyRec, PRIVATE_SCREEN, 0))
return FALSE;
if(!dixRegisterPrivateKey(&ShadowGCKeyRec, PRIVATE_GC, 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;
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];
Bool ret;
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen);
pScrn->EnterVT = pPriv->EnterVT;
ret = (*pPriv->EnterVT)(index, flags);
pPriv->EnterVT = pScrn->EnterVT;
pScrn->EnterVT = ShadowEnterVT;
if(ret) {
pPriv->vtSema = TRUE;
return TRUE;
}
return FALSE;
}
static void
ShadowLeaveVT(int index, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[index];
ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(xf86Screens[index]->pScreen);
pPriv->vtSema = FALSE;
pScrn->LeaveVT = pPriv->LeaveVT;
(*pPriv->LeaveVT)(index, flags);
pPriv->LeaveVT = pScrn->LeaveVT;
pScrn->LeaveVT = ShadowLeaveVT;
}
/**********************************************************/
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 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,
};