diff options
Diffstat (limited to 'xorg-server/hw/xfree86/shadowfb/shadow.c')
-rw-r--r-- | xorg-server/hw/xfree86/shadowfb/shadow.c | 3322 |
1 files changed, 1641 insertions, 1681 deletions
diff --git a/xorg-server/hw/xfree86/shadowfb/shadow.c b/xorg-server/hw/xfree86/shadowfb/shadow.c index 26b92b5d6..714dd141a 100644 --- a/xorg-server/hw/xfree86/shadowfb/shadow.c +++ b/xorg-server/hw/xfree86/shadowfb/shadow.c @@ -1,1681 +1,1641 @@ -/*
- 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,
-};
-
+/* + 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, +}; |