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