1540 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1540 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * $XFree86: xc/programs/Xserver/miext/shadow/shadow.c,v 1.14tsi Exp $
 | |
|  *
 | |
|  * Copyright © 2000 Keith Packard
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that
 | |
|  * copyright notice and this permission notice appear in supporting
 | |
|  * documentation, and that the name of Keith Packard not be used in
 | |
|  * advertising or publicity pertaining to distribution of the software without
 | |
|  * specific, written prior permission.  Keith Packard makes no
 | |
|  * representations about the suitability of this software for any purpose.  It
 | |
|  * is provided "as is" without express or implied warranty.
 | |
|  *
 | |
|  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | |
|  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | |
|  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | |
|  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | |
|  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | |
|  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | |
|  * PERFORMANCE OF THIS SOFTWARE.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include    "X.h"
 | |
| #include    "scrnintstr.h"
 | |
| #include    "windowstr.h"
 | |
| #include    "font.h"
 | |
| #include    "dixfontstr.h"
 | |
| #include    "fontstruct.h"
 | |
| #include    "mi.h"
 | |
| #include    "regionstr.h"
 | |
| #include    "globals.h"
 | |
| #include    "gcstruct.h"
 | |
| #include    "shadow.h"
 | |
| 
 | |
| typedef struct _shadowGCPriv {
 | |
|     GCOps   *ops;
 | |
|     GCFuncs *funcs;
 | |
| } shadowGCPrivRec, *shadowGCPrivPtr;
 | |
| 
 | |
| int shadowScrPrivateIndex;
 | |
| int shadowGCPrivateIndex;
 | |
| int shadowGeneration;
 | |
| 
 | |
| #define shadowGetGCPriv(pGC) \
 | |
|     ((shadowGCPrivPtr) (pGC)->devPrivates[shadowGCPrivateIndex].ptr)
 | |
| #define shadowGCPriv(pGC) \
 | |
|     shadowGCPrivPtr  pGCPriv = shadowGetGCPriv(pGC)
 | |
| 
 | |
| #define wrap(priv, real, mem, func) {\
 | |
|     priv->mem = real->mem; \
 | |
|     real->mem = func; \
 | |
| }
 | |
| 
 | |
| #define unwrap(priv, real, mem) {\
 | |
|     real->mem = priv->mem; \
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowRedisplay (ScreenPtr pScreen)
 | |
| {
 | |
|     shadowScrPriv(pScreen);
 | |
|     shadowBufPtr    pBuf;
 | |
| 
 | |
|     for (pBuf = pScrPriv->pBuf; pBuf; pBuf = pBuf->pNext)
 | |
|     {
 | |
| 	if (REGION_NOTEMPTY (pScreen, &pBuf->damage))
 | |
| 	{
 | |
| 	    REGION_INTERSECT (pScreen, &pBuf->damage, &pBuf->damage,
 | |
| 			      &WindowTable[pScreen->myNum]->borderClip);
 | |
| 	    (*pBuf->update) (pScreen, pBuf);
 | |
| 	    REGION_EMPTY (pScreen, &pBuf->damage);
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowBlockHandler (pointer	data,
 | |
| 		      OSTimePtr pTimeout,
 | |
| 		      pointer pRead)
 | |
| {
 | |
|     ScreenPtr	pScreen = (ScreenPtr) data;
 | |
| 
 | |
|     shadowRedisplay (pScreen);
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowWakeupHandler (pointer data, int i, pointer LastSelectMask)
 | |
| {
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowDamageRegion (WindowPtr pWindow, RegionPtr pRegion)
 | |
| {
 | |
|     shadowBufPtr    pBuf = shadowFindBuf (pWindow);
 | |
| 
 | |
|     if (!pBuf)
 | |
| 	abort ();
 | |
| 
 | |
|     REGION_INTERSECT(pWindow->drawable.pScreen, pRegion, pRegion,
 | |
| 		     &pWindow->borderClip);
 | |
|     REGION_UNION(pWindow->drawable.pScreen, &pBuf->damage, &pBuf->damage,
 | |
| 		 pRegion);
 | |
| #ifdef ALWAYS_DISPLAY
 | |
|     shadowRedisplay (pWindow->drawable.pScreen);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowDamageBox (WindowPtr pWindow, BoxPtr pBox)
 | |
| {
 | |
|     RegionRec	region;
 | |
| 
 | |
|     REGION_INIT (pWindow->drawable.pScreen, ®ion, pBox, 1);
 | |
|     shadowDamageRegion (pWindow, ®ion);
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowDamageRect (WindowPtr pWindow, int x, int y, int w, int h)
 | |
| {
 | |
|     BoxRec	box;
 | |
| 
 | |
|     x += pWindow->drawable.x;
 | |
|     y += pWindow->drawable.y;
 | |
|     box.x1 = x;
 | |
|     box.x2 = x + w;
 | |
|     box.y1 = y;
 | |
|     box.y2 = y + h;
 | |
|     shadowDamageBox (pWindow, &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;
 | |
|     shadowScrPriv(pScreen);
 | |
|     shadowGCPriv(pGC);
 | |
|     Bool ret;
 | |
| 
 | |
|     unwrap (pScrPriv, pScreen, CreateGC);
 | |
|     if((ret = (*pScreen->CreateGC) (pGC))) {
 | |
| 	pGCPriv->ops = NULL;
 | |
| 	pGCPriv->funcs = pGC->funcs;
 | |
| 	pGC->funcs = &shadowGCFuncs;
 | |
|     }
 | |
|     wrap (pScrPriv, pScreen, CreateGC, shadowCreateGC);
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| void
 | |
| shadowWrapGC (GCPtr pGC)
 | |
| {
 | |
|     shadowGCPriv(pGC);
 | |
| 
 | |
|     pGCPriv->ops = NULL;
 | |
|     pGCPriv->funcs = pGC->funcs;
 | |
|     pGC->funcs = &shadowGCFuncs;
 | |
| }
 | |
| 
 | |
| void
 | |
| shadowUnwrapGC (GCPtr pGC)
 | |
| {
 | |
|     shadowGCPriv(pGC);
 | |
| 
 | |
|     pGC->funcs = pGCPriv->funcs;
 | |
|     if (pGCPriv->ops)
 | |
| 	pGC->ops = pGCPriv->ops;
 | |
| }
 | |
| 
 | |
| #define SHADOW_GC_OP_PROLOGUE(pGC, pDraw) \
 | |
|     shadowGCPriv(pGC);  \
 | |
|     GCFuncs *oldFuncs = pGC->funcs; \
 | |
|     unwrap(pGCPriv, pGC, funcs);  \
 | |
|     unwrap(pGCPriv, pGC, ops); \
 | |
| 
 | |
| #define SHADOW_GC_OP_EPILOGUE(pGC, pDraw) \
 | |
|     wrap(pGCPriv, pGC, funcs, oldFuncs); \
 | |
|     wrap(pGCPriv, pGC, ops, &shadowGCOps)
 | |
| 
 | |
| #define SHADOW_GC_FUNC_PROLOGUE(pGC) \
 | |
|     shadowGCPriv(pGC); \
 | |
|     unwrap(pGCPriv, pGC, funcs); \
 | |
|     if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
 | |
| 
 | |
| #define SHADOW_GC_FUNC_EPILOGUE(pGC) \
 | |
|     wrap(pGCPriv, pGC, funcs, &shadowGCFuncs);  \
 | |
|     if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &shadowGCOps)
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| #define IS_VISIBLE(pWin) 1
 | |
| 
 | |
| 
 | |
| #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))
 | |
| 
 | |
| #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;
 | |
|     PictureScreenPtr	ps = GetPictureScreen(pScreen);
 | |
|     shadowScrPriv(pScreen);
 | |
| 
 | |
|     unwrap (pScrPriv, ps, Composite);
 | |
|     (*ps->Composite) (op,
 | |
| 		       pSrc,
 | |
| 		       pMask,
 | |
| 		       pDst,
 | |
| 		       xSrc,
 | |
| 		       ySrc,
 | |
| 		       xMask,
 | |
| 		       yMask,
 | |
| 		       xDst,
 | |
| 		       yDst,
 | |
| 		       width,
 | |
| 		       height);
 | |
|     wrap (pScrPriv, ps, Composite, shadowComposite);
 | |
|     if (pDst->pDrawable->type == DRAWABLE_WINDOW)
 | |
| 	shadowDamageRect ((WindowPtr) pDst->pDrawable, xDst, yDst,
 | |
| 			    width, height);
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowGlyphs (CARD8		op,
 | |
| 		PicturePtr	pSrc,
 | |
| 		PicturePtr	pDst,
 | |
| 		PictFormatPtr	maskFormat,
 | |
| 		INT16		xSrc,
 | |
| 		INT16		ySrc,
 | |
| 		int		nlist,
 | |
| 		GlyphListPtr	list,
 | |
| 		GlyphPtr	*glyphs)
 | |
| {
 | |
|     ScreenPtr		pScreen = pDst->pDrawable->pScreen;
 | |
|     PictureScreenPtr	ps = GetPictureScreen(pScreen);
 | |
|     shadowScrPriv(pScreen);
 | |
|     int			x, y;
 | |
|     int			n;
 | |
|     GlyphPtr		glyph;
 | |
| 
 | |
|     unwrap (pScrPriv, ps, Glyphs);
 | |
|     (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
 | |
|     wrap (pScrPriv, ps, Glyphs, shadowGlyphs);
 | |
|     if (pDst->pDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	x = xSrc;
 | |
| 	y = ySrc;
 | |
| 	while (nlist--)
 | |
| 	{
 | |
| 	    x += list->xOff;
 | |
| 	    y += list->yOff;
 | |
| 	    n = list->len;
 | |
| 	    while (n--)
 | |
| 	    {
 | |
| 		glyph = *glyphs++;
 | |
| 		shadowDamageRect ((WindowPtr) pDst->pDrawable,
 | |
| 				    x - glyph->info.x,
 | |
| 				    y - glyph->info.y,
 | |
| 				    glyph->info.width,
 | |
| 				    glyph->info.height);
 | |
| 		x += glyph->info.xOff;
 | |
| 		y += glyph->info.yOff;
 | |
| 	    }
 | |
| 	    list++;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /**********************************************************/
 | |
| 
 | |
| 
 | |
| static void
 | |
| shadowFillSpans(
 | |
|     DrawablePtr pDraw,
 | |
|     GC		*pGC,
 | |
|     int		nInit,
 | |
|     DDXPointPtr pptInit,
 | |
|     int 	*pwidthInit,
 | |
|     int 	fSorted
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && nInit) {
 | |
| 	DDXPointPtr ppt = pptInit;
 | |
| 	int *pwidth = pwidthInit;
 | |
| 	int i = nInit;
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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++;
 | |
| 
 | |
| 	(*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
 | |
| 
 | |
|         if(!pGC->miTranslate) {
 | |
|            TRANSLATE_BOX(box, pDraw);
 | |
|         }
 | |
|         TRIM_BOX(box, pGC); 
 | |
| 
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     } else
 | |
| 	(*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
 | |
| 
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowSetSpans(
 | |
|     DrawablePtr		pDraw,
 | |
|     GCPtr		pGC,
 | |
|     char		*pcharsrc,
 | |
|     DDXPointPtr 	pptInit,
 | |
|     int			*pwidthInit,
 | |
|     int			nspans,
 | |
|     int			fSorted
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && nspans) {
 | |
| 	DDXPointPtr ppt = pptInit;
 | |
| 	int *pwidth = pwidthInit;
 | |
| 	int i = nspans;
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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++;
 | |
| 
 | |
| 	(*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
 | |
| 				pwidthInit, nspans, fSorted);
 | |
| 
 | |
|         if(!pGC->miTranslate) {
 | |
|            TRANSLATE_BOX(box, pDraw);
 | |
|         }
 | |
|         TRIM_BOX(box, pGC); 
 | |
| 
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     } else
 | |
| 	(*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
 | |
| 				pwidthInit, nspans, fSorted);
 | |
| 
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowPutImage(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		depth,
 | |
|     int x, int y, int w, int h,
 | |
|     int		leftPad,
 | |
|     int		format,
 | |
|     char 	*pImage
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h,
 | |
| 		leftPad, format, pImage);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw)) {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static RegionPtr
 | |
| shadowCopyArea(
 | |
|     DrawablePtr pSrc,
 | |
|     DrawablePtr pDst,
 | |
|     GC *pGC,
 | |
|     int srcx, int srcy,
 | |
|     int width, int height,
 | |
|     int dstx, int dsty
 | |
| ){
 | |
|     RegionPtr ret;
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDst);
 | |
|     ret = (*pGC->ops->CopyArea)(pSrc, pDst,
 | |
|             pGC, srcx, srcy, width, height, dstx, dsty);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDst);
 | |
| 
 | |
|     if(IS_VISIBLE(pDst)) {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDst, &box);
 | |
|     }
 | |
| 
 | |
|     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;
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDst);
 | |
|     ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
 | |
| 	       pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDst);
 | |
| 
 | |
|     if(IS_VISIBLE(pDst)) {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDst, &box);
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowPolyPoint(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr pGC,
 | |
|     int mode,
 | |
|     int npt,
 | |
|     xPoint *pptInit
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && npt) {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	box.x2 = box.x1 = pptInit->x;
 | |
| 	box.y2 = box.y1 = pptInit->y;
 | |
| 
 | |
| 	/* this could be slow if the points were spread out */
 | |
| 
 | |
| 	while(--npt) {
 | |
| 	   pptInit++;
 | |
| 	   if(box.x1 > pptInit->x) box.x1 = pptInit->x;
 | |
| 	   else if(box.x2 < pptInit->x) box.x2 = pptInit->x;
 | |
| 	   if(box.y1 > pptInit->y) box.y1 = pptInit->y;
 | |
| 	   else if(box.y2 < pptInit->y) box.y2 = pptInit->y;
 | |
| 	}
 | |
| 
 | |
| 	box.x2++;
 | |
| 	box.y2++;
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowPolylines(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		mode,
 | |
|     int		npt,
 | |
|     DDXPointPtr pptInit
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && npt) {
 | |
| 	BoxRec box;
 | |
| 	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) {
 | |
| 		pptInit++;
 | |
| 		x += pptInit->x;
 | |
| 		y += pptInit->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) {
 | |
| 		pptInit++;
 | |
| 		if(box.x1 > pptInit->x) box.x1 = pptInit->x;
 | |
| 		else if(box.x2 < pptInit->x) box.x2 = pptInit->x;
 | |
| 		if(box.y1 > pptInit->y) box.y1 = pptInit->y;
 | |
| 		else if(box.y2 < pptInit->y) box.y2 = pptInit->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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowPolySegment(
 | |
|     DrawablePtr	pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		nseg,
 | |
|     xSegment	*pSeg
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && nseg) {
 | |
| 	BoxRec box;
 | |
| 	int extra = pGC->lineWidth;
 | |
| 
 | |
|         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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowPolyRectangle(
 | |
|     DrawablePtr  pDraw,
 | |
|     GCPtr        pGC,
 | |
|     int	         nRects,
 | |
|     xRectangle  *pRects
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->PolyRectangle)(pDraw, pGC, nRects, pRects);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && nRects)
 | |
|     {
 | |
| 	BoxRec box;
 | |
| 	int offset1, offset2, offset3;
 | |
| 
 | |
| 	offset2 = pGC->lineWidth;
 | |
| 	if(!offset2) offset2 = 1;
 | |
| 	offset1 = offset2 >> 1;
 | |
| 	offset3 = offset2 - offset1;
 | |
| 
 | |
| 	while(nRects--)
 | |
| 	{
 | |
| 	    box.x1 = pRects->x - offset1;
 | |
| 	    box.y1 = pRects->y - offset1;
 | |
| 	    box.x2 = box.x1 + pRects->width + offset2;
 | |
| 	    box.y2 = box.y1 + offset2;
 | |
| 	    TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 | |
| 	    if(BOX_NOT_EMPTY(box))
 | |
| 		shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
| 
 | |
| 	    box.x1 = pRects->x - offset1;
 | |
| 	    box.y1 = pRects->y + offset3;
 | |
| 	    box.x2 = box.x1 + offset2;
 | |
| 	    box.y2 = box.y1 + pRects->height - offset2;
 | |
| 	    TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 | |
| 	    if(BOX_NOT_EMPTY(box))
 | |
| 		shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
| 
 | |
| 	    box.x1 = pRects->x + pRects->width - offset1;
 | |
| 	    box.y1 = pRects->y + offset3;
 | |
| 	    box.x2 = box.x1 + offset2;
 | |
| 	    box.y2 = box.y1 + pRects->height - offset2;
 | |
| 	    TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 | |
| 	    if(BOX_NOT_EMPTY(box))
 | |
| 		shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
| 
 | |
| 	    box.x1 = pRects->x - offset1;
 | |
| 	    box.y1 = pRects->y + pRects->height - offset1;
 | |
| 	    box.x2 = box.x1 + pRects->width + offset2;
 | |
| 	    box.y2 = box.y1 + offset2;
 | |
| 	    TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 | |
| 	    if(BOX_NOT_EMPTY(box))
 | |
| 		shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
| 
 | |
| 	    pRects++;
 | |
| 	}
 | |
|     }
 | |
|  }
 | |
| 
 | |
| static void
 | |
| shadowPolyArc(
 | |
|     DrawablePtr	pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		narcs,
 | |
|     xArc	*parcs
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && narcs) {
 | |
| 	int extra = pGC->lineWidth >> 1;
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowFillPolygon(
 | |
|     DrawablePtr	pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		shape,
 | |
|     int		mode,
 | |
|     int		count,
 | |
|     DDXPointPtr	pptInit
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && (count > 2)) {
 | |
| 	DDXPointPtr ppt = pptInit;
 | |
| 	int i = count;
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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++;
 | |
| 
 | |
| 	(*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     } else
 | |
| 	(*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
 | |
| 
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| shadowPolyFillRect(
 | |
|     DrawablePtr	pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		nRectsInit,
 | |
|     xRectangle	*pRectsInit
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && nRectsInit) {
 | |
| 	BoxRec box;
 | |
| 	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 */
 | |
| 
 | |
| 	(*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	    shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     } else
 | |
| 	(*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
 | |
| 
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| shadowPolyFillArc(
 | |
|     DrawablePtr	pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		narcs,
 | |
|     xArc	*parcs
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && narcs) {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| static int
 | |
| shadowPolyText8(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		x,
 | |
|     int 	y,
 | |
|     int 	count,
 | |
|     char	*chars
 | |
| ){
 | |
|     int width;
 | |
| 
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     width -= x;
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && (width > 0)) {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	/* ugh */
 | |
| 	box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
 | |
| 	box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
 | |
| 
 | |
| 	if(count > 1) {
 | |
| 	   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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| 
 | |
|     return (width + x);
 | |
| }
 | |
| 
 | |
| static int
 | |
| shadowPolyText16(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		x,
 | |
|     int		y,
 | |
|     int 	count,
 | |
|     unsigned short *chars
 | |
| ){
 | |
|     int width;
 | |
| 
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     width -= x;
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && (width > 0)) {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	/* ugh */
 | |
| 	box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
 | |
| 	box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
 | |
| 
 | |
| 	if(count > 1) {
 | |
| 	   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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| 
 | |
|     return (width + x);
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowImageText8(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		x,
 | |
|     int		y,
 | |
|     int 	count,
 | |
|     char	*chars
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && count) {
 | |
| 	int top, bot, Min, Max;
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| static void
 | |
| shadowImageText16(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		x,
 | |
|     int		y,
 | |
|     int 	count,
 | |
|     unsigned short *chars
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && count) {
 | |
| 	int top, bot, Min, Max;
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| shadowImageGlyphBlt(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr pGC,
 | |
|     int x, int y,
 | |
|     unsigned int nglyph,
 | |
|     CharInfoPtr *ppci,
 | |
|     pointer pglyphBase
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyph,
 | |
| 					ppci, pglyphBase);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && nglyph) {
 | |
| 	int top, bot, width = 0;
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowPolyGlyphBlt(
 | |
|     DrawablePtr pDraw,
 | |
|     GCPtr pGC,
 | |
|     int x, int y,
 | |
|     unsigned int nglyph,
 | |
|     CharInfoPtr *ppci,
 | |
|     pointer pglyphBase
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyph,
 | |
| 				ppci, pglyphBase);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw) && nglyph) {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	/* 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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowPushPixels(
 | |
|     GCPtr	pGC,
 | |
|     PixmapPtr	pBitMap,
 | |
|     DrawablePtr pDraw,
 | |
|     int	dx, int dy, int xOrg, int yOrg
 | |
| ){
 | |
|     SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
 | |
|     (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
 | |
|     SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
 | |
| 
 | |
|     if(IS_VISIBLE(pDraw)) {
 | |
| 	BoxRec box;
 | |
| 
 | |
|         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))
 | |
| 	   shadowDamageBox ((WindowPtr) pDraw, &box);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| shadowPaintWindow(
 | |
|   WindowPtr pWindow,
 | |
|   RegionPtr prgn,
 | |
|   int what
 | |
| ){
 | |
|     ScreenPtr pScreen = pWindow->drawable.pScreen;
 | |
|     shadowScrPriv(pScreen);
 | |
| 
 | |
|     if(what == PW_BACKGROUND) {
 | |
| 	unwrap (pScrPriv, pScreen, PaintWindowBackground);
 | |
| 	(*pScreen->PaintWindowBackground) (pWindow, prgn, what);
 | |
| 	wrap (pScrPriv, pScreen, PaintWindowBackground, shadowPaintWindow);
 | |
|     } else {
 | |
| 	unwrap (pScrPriv, pScreen, PaintWindowBorder);
 | |
| 	(*pScreen->PaintWindowBorder) (pWindow, prgn, what);
 | |
| 	wrap (pScrPriv, pScreen, PaintWindowBorder, shadowPaintWindow);
 | |
|     }
 | |
|     shadowDamageRegion (pWindow, prgn);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| shadowCopyWindow(
 | |
|    WindowPtr pWindow,
 | |
|    DDXPointRec ptOldOrg,
 | |
|    RegionPtr prgn
 | |
| ){
 | |
|     ScreenPtr pScreen = pWindow->drawable.pScreen;
 | |
|     shadowScrPriv(pScreen);
 | |
| 
 | |
|     unwrap (pScrPriv, pScreen, CopyWindow);
 | |
|     (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgn);
 | |
|     wrap (pScrPriv, pScreen, CopyWindow, shadowCopyWindow);
 | |
|     shadowDamageRegion (pWindow, prgn);
 | |
| }
 | |
| 
 | |
| 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 */
 | |
| };
 | |
| 
 | |
| static void
 | |
| shadowGetImage (DrawablePtr pDrawable,
 | |
| 		int sx,
 | |
| 		int sy,
 | |
| 		int w,
 | |
| 		int h,
 | |
| 		unsigned int format,
 | |
| 		unsigned long planeMask,
 | |
| 		char * pdstLine)
 | |
| {
 | |
|     ScreenPtr pScreen = pDrawable->pScreen;
 | |
|     shadowScrPriv(pScreen);
 | |
| 
 | |
|     /* Many apps use GetImage to sync with the visable frame buffer */
 | |
|     if (pDrawable->type == DRAWABLE_WINDOW)
 | |
| 	shadowRedisplay (pScreen);
 | |
|     unwrap (pScrPriv, pScreen, GetImage);
 | |
|     (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
 | |
|     wrap (pScrPriv, pScreen, GetImage, shadowGetImage);
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowRestoreAreas (PixmapPtr pPixmap,
 | |
| 		    RegionPtr prgn,
 | |
| 		    int xorg,
 | |
| 		    int yorg,
 | |
| 		    WindowPtr pWin)
 | |
| {
 | |
|     ScreenPtr pScreen = pWin->drawable.pScreen;
 | |
|     shadowScrPriv(pScreen);
 | |
| 
 | |
|     unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
 | |
|     (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn,
 | |
| 						xorg, yorg, pWin);
 | |
|     wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
 | |
| 			     shadowRestoreAreas);
 | |
|     shadowDamageRegion (pWin, prgn);
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| shadowCloseScreen (int i, ScreenPtr pScreen)
 | |
| {
 | |
|     shadowScrPriv(pScreen);
 | |
| 
 | |
|     unwrap (pScrPriv, pScreen, CreateGC);
 | |
|     unwrap (pScrPriv, pScreen, PaintWindowBackground);
 | |
|     unwrap (pScrPriv, pScreen, PaintWindowBorder);
 | |
|     unwrap (pScrPriv, pScreen, CopyWindow);
 | |
|     unwrap (pScrPriv, pScreen, CloseScreen);
 | |
|     unwrap (pScrPriv, pScreen, GetImage);
 | |
|     unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
 | |
|     xfree (pScrPriv);
 | |
|     return (*pScreen->CloseScreen) (i, pScreen);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| shadowSetup (ScreenPtr pScreen)
 | |
| {
 | |
|     shadowScrPrivPtr	pScrPriv;
 | |
| #ifdef RENDER
 | |
|     PictureScreenPtr	ps = GetPictureScreenIfSet(pScreen);
 | |
| #endif
 | |
| 
 | |
|     if (shadowGeneration != serverGeneration)
 | |
|     {
 | |
| 	shadowScrPrivateIndex = AllocateScreenPrivateIndex ();
 | |
| 	if (shadowScrPrivateIndex == -1)
 | |
| 	    return FALSE;
 | |
| 	shadowGCPrivateIndex = AllocateGCPrivateIndex ();
 | |
| 	if (shadowGCPrivateIndex == -1)
 | |
| 	    return FALSE;
 | |
| 	shadowGeneration = serverGeneration;
 | |
|     }
 | |
|     if (!AllocateGCPrivate (pScreen, shadowGCPrivateIndex, sizeof (shadowGCPrivRec)))
 | |
| 	return FALSE;
 | |
|     pScrPriv = (shadowScrPrivPtr) xalloc (sizeof (shadowScrPrivRec));
 | |
|     if (!pScrPriv)
 | |
| 	return FALSE;
 | |
| 
 | |
|     if (!RegisterBlockAndWakeupHandlers (shadowBlockHandler,
 | |
| 					 shadowWakeupHandler,
 | |
| 					 (pointer) pScreen))
 | |
| 	return FALSE;
 | |
| 
 | |
|     wrap (pScrPriv, pScreen, CreateGC, shadowCreateGC);
 | |
|     wrap (pScrPriv, pScreen, PaintWindowBackground, shadowPaintWindow);
 | |
|     wrap (pScrPriv, pScreen, PaintWindowBorder, shadowPaintWindow);
 | |
|     wrap (pScrPriv, pScreen, CopyWindow, shadowCopyWindow);
 | |
|     wrap (pScrPriv, pScreen, CloseScreen, shadowCloseScreen);
 | |
|     wrap (pScrPriv, pScreen, GetImage, shadowGetImage);
 | |
|     wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
 | |
| 			     shadowRestoreAreas);
 | |
| #ifdef RENDER
 | |
|     if (ps) {
 | |
| 	wrap (pScrPriv, ps, Glyphs, shadowGlyphs);
 | |
| 	wrap (pScrPriv, ps, Composite, shadowComposite);
 | |
|     }
 | |
| #endif
 | |
|     pScrPriv->pBuf = 0;
 | |
| 
 | |
|     pScreen->devPrivates[shadowScrPrivateIndex].ptr = (pointer) pScrPriv;
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| shadowAdd (ScreenPtr	    pScreen,
 | |
| 	   PixmapPtr	    pPixmap,
 | |
| 	   ShadowUpdateProc update,
 | |
| 	   ShadowWindowProc window,
 | |
| 	   int		    randr,
 | |
| 	   void		    *closure)
 | |
| {
 | |
|     shadowScrPriv(pScreen);
 | |
|     shadowBufPtr    pBuf;
 | |
| 
 | |
|     pBuf = (shadowBufPtr) xalloc (sizeof (shadowBufRec));
 | |
|     if (!pBuf)
 | |
| 	return FALSE;
 | |
|     /*
 | |
|      * Map simple rotation values to bitmasks; fortunately,
 | |
|      * these are all unique
 | |
|      */
 | |
|     switch (randr) {
 | |
|     case 0:
 | |
| 	randr = SHADOW_ROTATE_0;
 | |
| 	break;
 | |
|     case 90:
 | |
| 	randr = SHADOW_ROTATE_90;
 | |
| 	break;
 | |
|     case 180:
 | |
| 	randr = SHADOW_ROTATE_180;
 | |
| 	break;
 | |
|     case 270:
 | |
| 	randr = SHADOW_ROTATE_270;
 | |
| 	break;
 | |
|     }
 | |
|     pBuf->pPixmap = pPixmap;
 | |
|     pBuf->update = update;
 | |
|     pBuf->window = window;
 | |
|     REGION_NULL(pScreen, &pBuf->damage);
 | |
|     pBuf->pNext = pScrPriv->pBuf;
 | |
|     pBuf->randr = randr;
 | |
|     pBuf->closure = 0;
 | |
|     pScrPriv->pBuf = pBuf;
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| void
 | |
| shadowRemove (ScreenPtr pScreen, PixmapPtr pPixmap)
 | |
| {
 | |
|     shadowScrPriv(pScreen);
 | |
|     shadowBufPtr    pBuf, *pPrev;
 | |
| 
 | |
|     for (pPrev = &pScrPriv->pBuf; (pBuf = *pPrev); pPrev = &pBuf->pNext)
 | |
| 	if (pBuf->pPixmap == pPixmap)
 | |
| 	{
 | |
| 	    REGION_UNINIT (pScreen, &pBuf->damage);
 | |
| 	    *pPrev = pBuf->pNext;
 | |
| 	    xfree (pBuf);
 | |
| 	    break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| shadowBufPtr
 | |
| shadowFindBuf (WindowPtr pWindow)
 | |
| {
 | |
|     ScreenPtr	    pScreen = pWindow->drawable.pScreen;
 | |
|     shadowScrPriv(pScreen);
 | |
|     shadowBufPtr    pBuf, *pPrev;
 | |
|     PixmapPtr	    pPixmap = (*pScreen->GetWindowPixmap) (pWindow);
 | |
| 
 | |
|     for (pPrev = &pScrPriv->pBuf; (pBuf = *pPrev); pPrev = &pBuf->pNext)
 | |
|     {
 | |
| 	if (!pBuf->pPixmap)
 | |
| 	    pBuf->pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
 | |
| 	if (pBuf->pPixmap == pPixmap)
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * Reorder so this one is first next time
 | |
| 	     */
 | |
| 	    if (pPrev != &pScrPriv->pBuf)
 | |
| 	    {
 | |
| 		*pPrev = pBuf->pNext;
 | |
| 		pBuf->pNext = pScrPriv->pBuf;
 | |
| 		pScrPriv->pBuf = pBuf;
 | |
| 	    }
 | |
| 	    return pBuf;
 | |
| 	}
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| shadowInit (ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window)
 | |
| {
 | |
|     if (!shadowSetup (pScreen))
 | |
| 	return FALSE;
 | |
| 
 | |
|     if (!shadowAdd (pScreen, 0, update, window, SHADOW_ROTATE_0, 0))
 | |
| 	return FALSE;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 |