1957 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			1957 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
| /*
 | |
|  * Copyright © 2003 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.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include    <X11/X.h>
 | |
| #include    "scrnintstr.h"
 | |
| #include    "windowstr.h"
 | |
| #include    <X11/fonts/font.h>
 | |
| #include    "dixfontstr.h"
 | |
| #include    <X11/fonts/fontstruct.h>
 | |
| #include    "mi.h"
 | |
| #include    "regionstr.h"
 | |
| #include    "globals.h"
 | |
| #include    "gcstruct.h"
 | |
| #include    "damage.h"
 | |
| #include    "damagestr.h"
 | |
| #ifdef COMPOSITE
 | |
| #include    "cw.h"
 | |
| #endif
 | |
| 
 | |
| #define wrap(priv, real, mem, func) {\
 | |
|     priv->mem = real->mem; \
 | |
|     real->mem = func; \
 | |
| }
 | |
| 
 | |
| #define unwrap(priv, real, mem) {\
 | |
|     real->mem = priv->mem; \
 | |
| }
 | |
| 
 | |
| #define BOX_SAME(a,b) \
 | |
|     ((a)->x1 == (b)->x1 && \
 | |
|      (a)->y1 == (b)->y1 && \
 | |
|      (a)->x2 == (b)->x2 && \
 | |
|      (a)->y2 == (b)->y2)
 | |
| 
 | |
| #define DAMAGE_VALIDATE_ENABLE 0
 | |
| #define DAMAGE_DEBUG_ENABLE 0
 | |
| #if DAMAGE_DEBUG_ENABLE
 | |
| #define DAMAGE_DEBUG(x)	ErrorF x
 | |
| #else
 | |
| #define DAMAGE_DEBUG(x)
 | |
| #endif
 | |
| 
 | |
| #define getPixmapDamageRef(pPixmap) ((DamagePtr *) \
 | |
|     dixLookupPrivateAddr(&(pPixmap)->devPrivates, damagePixPrivateKey))
 | |
| 
 | |
| #define pixmapDamage(pPixmap)		damagePixPriv(pPixmap)
 | |
| 
 | |
| static DevPrivateKey damageScrPrivateKey = &damageScrPrivateKey;
 | |
| static DevPrivateKey damagePixPrivateKey = &damagePixPrivateKey;
 | |
| static DevPrivateKey damageGCPrivateKey = &damageGCPrivateKey;
 | |
| static DevPrivateKey damageWinPrivateKey = &damageWinPrivateKey;
 | |
| 
 | |
| static DamagePtr *
 | |
| getDrawableDamageRef (DrawablePtr pDrawable)
 | |
| {
 | |
|     PixmapPtr   pPixmap;
 | |
|     
 | |
|     if (pDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	ScreenPtr   pScreen = pDrawable->pScreen;
 | |
| 
 | |
| 	pPixmap = 0;
 | |
| 	if (pScreen->GetWindowPixmap
 | |
| #ifdef ROOTLESS_WORKAROUND
 | |
| 	    && ((WindowPtr)pDrawable)->viewable
 | |
| #endif
 | |
| 	    )
 | |
| 	    pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable);
 | |
| 
 | |
| 	if (!pPixmap)
 | |
| 	{
 | |
| 	    damageScrPriv(pScreen);
 | |
| 
 | |
| 	    return &pScrPriv->pScreenDamage;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
| 	pPixmap = (PixmapPtr) pDrawable;
 | |
|     return getPixmapDamageRef (pPixmap);
 | |
| }
 | |
| 
 | |
| #define getDrawableDamage(pDrawable)	(*getDrawableDamageRef (pDrawable))
 | |
| #define getWindowDamage(pWin)		getDrawableDamage(&(pWin)->drawable)
 | |
| 
 | |
| #define drawableDamage(pDrawable)	\
 | |
|     DamagePtr	pDamage = getDrawableDamage(pDrawable)
 | |
| 
 | |
| #define windowDamage(pWin)		drawableDamage(&(pWin)->drawable)
 | |
| 
 | |
| #define winDamageRef(pWindow) \
 | |
|     DamagePtr	*pPrev = (DamagePtr *) \
 | |
| 	dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey)
 | |
| 
 | |
| static void
 | |
| DamageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion)
 | |
| {
 | |
|     BoxRec tmpBox;
 | |
|     RegionRec tmpRegion;
 | |
|     Bool was_empty;
 | |
| 
 | |
|     switch (pDamage->damageLevel) {
 | |
|     case DamageReportRawRegion:
 | |
| 	(*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure);
 | |
| 	break;
 | |
|     case DamageReportDeltaRegion:
 | |
| 	REGION_NULL (pScreen, &tmpRegion);
 | |
| 	REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage);
 | |
| 	if (REGION_NOTEMPTY (pScreen, &tmpRegion)) {
 | |
| 	    REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
 | |
| 			 pDamageRegion);
 | |
| 	    (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure);
 | |
| 	}
 | |
| 	REGION_UNINIT(pScreen, &tmpRegion);
 | |
| 	break;
 | |
|     case DamageReportBoundingBox:
 | |
| 	tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage);
 | |
| 	REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
 | |
| 		     pDamageRegion);
 | |
| 	if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) {
 | |
| 	    (*pDamage->damageReport) (pDamage, &pDamage->damage,
 | |
| 				      pDamage->closure);
 | |
| 	}
 | |
| 	break;
 | |
|     case DamageReportNonEmpty:
 | |
| 	was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage);
 | |
| 	REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
 | |
| 		     pDamageRegion);
 | |
| 	if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) {
 | |
| 	    (*pDamage->damageReport) (pDamage, &pDamage->damage,
 | |
| 				      pDamage->closure);
 | |
| 	}
 | |
| 	break;
 | |
|     case DamageReportNone:
 | |
| 	REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
 | |
| 		     pDamageRegion);
 | |
| 	break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #if DAMAGE_DEBUG_ENABLE
 | |
| static void
 | |
| _damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where)
 | |
| #define damageDamageRegion(d,r,c,m) _damageDamageRegion(d,r,c,m,__FUNCTION__)
 | |
| #else
 | |
| static void
 | |
| damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
 | |
| 			int subWindowMode)
 | |
| #endif
 | |
| {
 | |
|     ScreenPtr	    pScreen = pDrawable->pScreen;
 | |
|     damageScrPriv(pScreen);
 | |
|     drawableDamage(pDrawable);
 | |
|     DamagePtr	    pNext;
 | |
|     RegionRec	    clippedRec;
 | |
|     RegionPtr	    pDamageRegion;
 | |
|     RegionRec	    pixClip;
 | |
|     int		    draw_x, draw_y;
 | |
| #ifdef COMPOSITE
 | |
|     int		    screen_x = 0, screen_y = 0;
 | |
| #endif
 | |
| 
 | |
|     /* short circuit for empty regions */
 | |
|     if (!REGION_NOTEMPTY(pScreen, pRegion))
 | |
| 	return;
 | |
|     
 | |
| #ifdef COMPOSITE
 | |
|     /*
 | |
|      * When drawing to a pixmap which is storing window contents,
 | |
|      * the region presented is in pixmap relative coordinates which
 | |
|      * need to be converted to screen relative coordinates
 | |
|      */
 | |
|     if (pDrawable->type != DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x;
 | |
| 	screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y;
 | |
|     }
 | |
|     if (screen_x || screen_y)
 | |
|         REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y);
 | |
| #endif
 | |
| 	
 | |
|     if (pDrawable->type == DRAWABLE_WINDOW &&
 | |
| 	((WindowPtr)(pDrawable))->backingStore == NotUseful)
 | |
|     {
 | |
| 	if (subWindowMode == ClipByChildren)
 | |
| 	{
 | |
| 	    REGION_INTERSECT(pScreen, pRegion, pRegion,
 | |
| 			     &((WindowPtr)(pDrawable))->clipList);
 | |
| 	}
 | |
| 	else if (subWindowMode == IncludeInferiors)
 | |
| 	{
 | |
| 	    RegionPtr pTempRegion =
 | |
| 		NotClippedByChildren((WindowPtr)(pDrawable));
 | |
| 	    REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion);
 | |
| 	    REGION_DESTROY(pScreen, pTempRegion);
 | |
| 	}
 | |
| 	/* If subWindowMode is set to an invalid value, don't perform
 | |
| 	 * any drawable-based clipping. */
 | |
|     }
 | |
|         
 | |
| 
 | |
|     REGION_NULL (pScreen, &clippedRec);
 | |
|     for (; pDamage; pDamage = pNext)
 | |
|     {
 | |
| 	pNext = pDamage->pNext;
 | |
| 	/*
 | |
| 	 * Check for internal damage and don't send events
 | |
| 	 */
 | |
| 	if (pScrPriv->internalLevel > 0 && !pDamage->isInternal)
 | |
| 	{
 | |
| 	    DAMAGE_DEBUG (("non internal damage, skipping at %d\n",
 | |
| 			   pScrPriv->internalLevel));
 | |
| 	    continue;
 | |
| 	}
 | |
| 	/*
 | |
| 	 * Check for unrealized windows
 | |
| 	 */
 | |
| 	if (pDamage->pDrawable->type == DRAWABLE_WINDOW &&
 | |
| 	    !((WindowPtr) (pDamage->pDrawable))->realized)
 | |
| 	{
 | |
| 	    continue;
 | |
| 	}
 | |
| 	
 | |
| 	draw_x = pDamage->pDrawable->x;
 | |
| 	draw_y = pDamage->pDrawable->y;
 | |
| #ifdef COMPOSITE
 | |
| 	/*
 | |
| 	 * Need to move everyone to screen coordinates
 | |
| 	 * XXX what about off-screen pixmaps with non-zero x/y?
 | |
| 	 */
 | |
| 	if (pDamage->pDrawable->type != DRAWABLE_WINDOW)
 | |
| 	{
 | |
| 	    draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x;
 | |
| 	    draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y;
 | |
| 	}
 | |
| #endif
 | |
| 	
 | |
| 	/*
 | |
| 	 * Clip against border or pixmap bounds
 | |
| 	 */
 | |
| 	
 | |
| 	pDamageRegion = pRegion;
 | |
| 	if (clip || pDamage->pDrawable != pDrawable)
 | |
| 	{
 | |
| 	    pDamageRegion = &clippedRec;
 | |
| 	    if (pDamage->pDrawable->type == DRAWABLE_WINDOW) {
 | |
| 		REGION_INTERSECT (pScreen, pDamageRegion, pRegion,
 | |
| 		    &((WindowPtr)(pDamage->pDrawable))->borderClip);
 | |
| 	    } else {
 | |
| 		BoxRec	box;
 | |
| 		box.x1 = draw_x;
 | |
| 		box.y1 = draw_y;
 | |
| 		box.x2 = draw_x + pDamage->pDrawable->width;
 | |
| 		box.y2 = draw_y + pDamage->pDrawable->height;
 | |
| 		REGION_INIT(pScreen, &pixClip, &box, 1);
 | |
| 		REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip);
 | |
| 		REGION_UNINIT(pScreen, &pixClip);
 | |
| 	    }
 | |
| 	    /*
 | |
| 	     * Short circuit empty results
 | |
| 	     */
 | |
| 	    if (!REGION_NOTEMPTY(pScreen, pDamageRegion))
 | |
| 		continue;
 | |
| 	}
 | |
| 	
 | |
| 	DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
 | |
| 		       where,
 | |
| 		       pDamageRegion->extents.x2 - pDamageRegion->extents.x1,
 | |
| 		       pDamageRegion->extents.y2 - pDamageRegion->extents.y1,
 | |
| 		       pDamageRegion->extents.x1, pDamageRegion->extents.y1,
 | |
| 		       pDrawable->id, pDamage->pDrawable->id));
 | |
| 	
 | |
| 	/*
 | |
| 	 * Move region to target coordinate space
 | |
| 	 */
 | |
| 	if (draw_x || draw_y)
 | |
| 	    REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y);
 | |
| 
 | |
| 	/* If the damage rec has been flagged to report damage after the op has
 | |
| 	 * completed, then union it into the delayed damage region, which will
 | |
| 	 * be used for reporting after calling down, and skip the reporting 
 | |
| 	 */
 | |
| 	if (!pDamage->reportAfter) {
 | |
| 	    DamageReportDamage (pDamage, pDamageRegion);
 | |
| 	} else {
 | |
| 	    REGION_UNION(pScreen, &pDamage->pendingDamage,
 | |
| 			 &pDamage->pendingDamage, pDamageRegion);
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * translate original region back
 | |
| 	 */
 | |
| 	if (pDamageRegion == pRegion && (draw_x || draw_y))
 | |
| 	    REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y);
 | |
|     }
 | |
| #ifdef COMPOSITE
 | |
|     if (screen_x || screen_y)
 | |
| 	REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y);
 | |
| #endif
 | |
|     
 | |
|     REGION_UNINIT (pScreen, &clippedRec);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageReportPostOp (DrawablePtr pDrawable)
 | |
| {
 | |
|     drawableDamage(pDrawable);
 | |
| 
 | |
|     for (; pDamage != NULL; pDamage = pDamage->pNext)
 | |
|     {
 | |
| 	if (pDamage->reportAfter) {
 | |
| 	    DamageReportDamage (pDamage, &pDamage->pendingDamage);
 | |
| 	    REGION_EMPTY (pScreen, &pDamage->pendingDamage);
 | |
| 	}
 | |
|     }
 | |
|     
 | |
| }
 | |
| 
 | |
| #if DAMAGE_DEBUG_ENABLE
 | |
| #define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
 | |
| static void
 | |
| _damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where)
 | |
| #else
 | |
| static void
 | |
| damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode)
 | |
| #endif
 | |
| {
 | |
|     RegionRec	region;
 | |
| 
 | |
|     REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1);
 | |
| #if DAMAGE_DEBUG_ENABLE
 | |
|     _damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode, where);
 | |
| #else
 | |
|     damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode);
 | |
| #endif
 | |
|     REGION_UNINIT (pDrawable->pScreen, ®ion);
 | |
| }
 | |
| 
 | |
| static void damageValidateGC(GCPtr, unsigned long, DrawablePtr);
 | |
| static void damageChangeGC(GCPtr, unsigned long);
 | |
| static void damageCopyGC(GCPtr, unsigned long, GCPtr);
 | |
| static void damageDestroyGC(GCPtr);
 | |
| static void damageChangeClip(GCPtr, int, pointer, int);
 | |
| static void damageDestroyClip(GCPtr);
 | |
| static void damageCopyClip(GCPtr, GCPtr);
 | |
| 
 | |
| static GCFuncs damageGCFuncs = {
 | |
|     damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC,
 | |
|     damageChangeClip, damageDestroyClip, damageCopyClip
 | |
| };
 | |
| 
 | |
| static GCOps damageGCOps;
 | |
| 
 | |
| static Bool
 | |
| damageCreateGC(GCPtr pGC)
 | |
| {
 | |
|     ScreenPtr pScreen = pGC->pScreen;
 | |
|     damageScrPriv(pScreen);
 | |
|     damageGCPriv(pGC);
 | |
|     Bool ret;
 | |
| 
 | |
|     pGC->pCompositeClip = 0;
 | |
|     unwrap (pScrPriv, pScreen, CreateGC);
 | |
|     if((ret = (*pScreen->CreateGC) (pGC))) {
 | |
| 	pGCPriv->ops = NULL;
 | |
| 	pGCPriv->funcs = pGC->funcs;
 | |
| 	pGC->funcs = &damageGCFuncs;
 | |
|     }
 | |
|     wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| #ifdef NOTUSED
 | |
| static void
 | |
| damageWrapGC (GCPtr pGC)
 | |
| {
 | |
|     damageGCPriv(pGC);
 | |
| 
 | |
|     pGCPriv->ops = NULL;
 | |
|     pGCPriv->funcs = pGC->funcs;
 | |
|     pGC->funcs = &damageGCFuncs;
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageUnwrapGC (GCPtr pGC)
 | |
| {
 | |
|     damageGCPriv(pGC);
 | |
| 
 | |
|     pGC->funcs = pGCPriv->funcs;
 | |
|     if (pGCPriv->ops)
 | |
| 	pGC->ops = pGCPriv->ops;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
 | |
|     damageGCPriv(pGC);  \
 | |
|     GCFuncs *oldFuncs = pGC->funcs; \
 | |
|     unwrap(pGCPriv, pGC, funcs);  \
 | |
|     unwrap(pGCPriv, pGC, ops); \
 | |
| 
 | |
| #define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
 | |
|     wrap(pGCPriv, pGC, funcs, oldFuncs); \
 | |
|     wrap(pGCPriv, pGC, ops, &damageGCOps)
 | |
| 
 | |
| #define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
 | |
|     damageGCPriv(pGC); \
 | |
|     unwrap(pGCPriv, pGC, funcs); \
 | |
|     if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
 | |
| 
 | |
| #define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
 | |
|     wrap(pGCPriv, pGC, funcs, &damageGCFuncs);  \
 | |
|     if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
 | |
| 
 | |
| static void
 | |
| damageValidateGC(GCPtr         pGC,
 | |
| 		 unsigned long changes,
 | |
| 		 DrawablePtr   pDrawable)
 | |
| {
 | |
|     DAMAGE_GC_FUNC_PROLOGUE (pGC);
 | |
|     (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
 | |
|     pGCPriv->ops = pGC->ops;  /* just so it's not NULL */
 | |
|     DAMAGE_GC_FUNC_EPILOGUE (pGC);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageDestroyGC(GCPtr pGC)
 | |
| {
 | |
|     DAMAGE_GC_FUNC_PROLOGUE (pGC);
 | |
|     (*pGC->funcs->DestroyGC)(pGC);
 | |
|     DAMAGE_GC_FUNC_EPILOGUE (pGC);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageChangeGC (GCPtr		pGC,
 | |
| 		unsigned long   mask)
 | |
| {
 | |
|     DAMAGE_GC_FUNC_PROLOGUE (pGC);
 | |
|     (*pGC->funcs->ChangeGC) (pGC, mask);
 | |
|     DAMAGE_GC_FUNC_EPILOGUE (pGC);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageCopyGC (GCPtr	    pGCSrc,
 | |
| 	      unsigned long mask,
 | |
| 	      GCPtr	    pGCDst)
 | |
| {
 | |
|     DAMAGE_GC_FUNC_PROLOGUE (pGCDst);
 | |
|     (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
 | |
|     DAMAGE_GC_FUNC_EPILOGUE (pGCDst);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageChangeClip (GCPtr	    pGC,
 | |
| 		  int	    type,
 | |
| 		  pointer   pvalue,
 | |
| 		  int	    nrects)
 | |
| {
 | |
|     DAMAGE_GC_FUNC_PROLOGUE (pGC);
 | |
|     (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
 | |
|     DAMAGE_GC_FUNC_EPILOGUE (pGC);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
 | |
| {
 | |
|     DAMAGE_GC_FUNC_PROLOGUE (pgcDst);
 | |
|     (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
 | |
|     DAMAGE_GC_FUNC_EPILOGUE (pgcDst);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageDestroyClip(GCPtr pGC)
 | |
| {
 | |
|     DAMAGE_GC_FUNC_PROLOGUE (pGC);
 | |
|     (* pGC->funcs->DestroyClip)(pGC);
 | |
|     DAMAGE_GC_FUNC_EPILOGUE (pGC);
 | |
| }
 | |
| 
 | |
| #define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
 | |
|     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, pDrawable) { \
 | |
|     box.x1 += pDrawable->x; \
 | |
|     box.x2 += pDrawable->x; \
 | |
|     box.y1 += pDrawable->y; \
 | |
|     box.y2 += pDrawable->y; \
 | |
|     }
 | |
| 
 | |
| #define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
 | |
|     TRANSLATE_BOX(box, pDrawable); \
 | |
|     TRIM_BOX(box, pGC); \
 | |
|     }
 | |
| 
 | |
| #define BOX_NOT_EMPTY(box) \
 | |
|     (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
 | |
| 
 | |
| #define checkGCDamage(d,g)	(getDrawableDamage(d) && \
 | |
| 				 (!g->pCompositeClip ||\
 | |
| 				  REGION_NOTEMPTY(d->pScreen, \
 | |
| 						  g->pCompositeClip)))
 | |
| 
 | |
| #ifdef RENDER
 | |
| 
 | |
| #define TRIM_PICTURE_BOX(box, pDst) { \
 | |
|     BoxPtr 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; \
 | |
|     }
 | |
|     
 | |
| #define checkPictureDamage(p)	(getDrawableDamage(p->pDrawable) && \
 | |
| 				 REGION_NOTEMPTY(pScreen, p->pCompositeClip))
 | |
| 
 | |
| static void
 | |
| damageComposite (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);
 | |
|     damageScrPriv(pScreen);
 | |
| 
 | |
|     if (checkPictureDamage (pDst))
 | |
|     {
 | |
| 	BoxRec	box;
 | |
| 
 | |
| 	box.x1 = xDst + pDst->pDrawable->x;
 | |
| 	box.y1 = yDst + pDst->pDrawable->y;
 | |
| 	box.x2 = box.x1 + width;
 | |
| 	box.y2 = box.y1 + height;
 | |
| 	TRIM_PICTURE_BOX(box, pDst);
 | |
| 	if (BOX_NOT_EMPTY(box))
 | |
| 	    damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
 | |
|     }
 | |
|     unwrap (pScrPriv, ps, Composite);
 | |
|     (*ps->Composite) (op,
 | |
| 		       pSrc,
 | |
| 		       pMask,
 | |
| 		       pDst,
 | |
| 		       xSrc,
 | |
| 		       ySrc,
 | |
| 		       xMask,
 | |
| 		       yMask,
 | |
| 		       xDst,
 | |
| 		       yDst,
 | |
| 		       width,
 | |
| 		       height);
 | |
|     damageReportPostOp (pDst->pDrawable);
 | |
|     wrap (pScrPriv, ps, Composite, damageComposite);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageGlyphs (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);
 | |
|     damageScrPriv(pScreen);
 | |
| 
 | |
|     if (checkPictureDamage (pDst))
 | |
|     {
 | |
| 	int		nlistTmp = nlist;
 | |
| 	GlyphListPtr	listTmp = list;
 | |
| 	GlyphPtr	*glyphsTmp = glyphs;
 | |
| 	int		x, y;
 | |
| 	int		n;
 | |
| 	GlyphPtr	glyph;
 | |
| 	BoxRec		box;
 | |
| 	int		x1, y1, x2, y2;
 | |
| 
 | |
| 	box.x1 = 32767;
 | |
| 	box.y1 = 32767;
 | |
| 	box.x2 = -32767;
 | |
| 	box.y2 = -32767;
 | |
| 	x = pDst->pDrawable->x;
 | |
| 	y = pDst->pDrawable->y;
 | |
| 	while (nlistTmp--)
 | |
| 	{
 | |
| 	    x += listTmp->xOff;
 | |
| 	    y += listTmp->yOff;
 | |
| 	    n = listTmp->len;
 | |
| 	    while (n--)
 | |
| 	    {
 | |
| 		glyph = *glyphsTmp++;
 | |
| 		x1 = x - glyph->info.x;
 | |
| 		y1 = y - glyph->info.y;
 | |
| 		x2 = x1 + glyph->info.width;
 | |
| 		y2 = y1 + glyph->info.height;
 | |
| 		if (x1 < box.x1)
 | |
| 		    box.x1 = x1;
 | |
| 		if (y1 < box.y1)
 | |
| 		    box.y1 = y1;
 | |
| 		if (x2 > box.x2)
 | |
| 		    box.x2 = x2;
 | |
| 		if (y2 > box.y2)
 | |
| 		    box.y2 = y2;
 | |
| 		x += glyph->info.xOff;
 | |
| 		y += glyph->info.yOff;
 | |
| 	    }
 | |
| 	    listTmp++;
 | |
| 	}
 | |
| 	TRIM_PICTURE_BOX (box, pDst);
 | |
| 	if (BOX_NOT_EMPTY(box))
 | |
| 	    damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
 | |
|     }
 | |
|     unwrap (pScrPriv, ps, Glyphs);
 | |
|     (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
 | |
|     damageReportPostOp (pDst->pDrawable);
 | |
|     wrap (pScrPriv, ps, Glyphs, damageGlyphs);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /**********************************************************/
 | |
| 
 | |
| 
 | |
| static void
 | |
| damageFillSpans(DrawablePtr pDrawable,
 | |
| 		GC	    *pGC,
 | |
| 		int	    npt,
 | |
| 		DDXPointPtr ppt,
 | |
| 		int	    *pwidth,
 | |
| 		int	    fSorted)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (npt && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	int	    nptTmp = npt;
 | |
| 	DDXPointPtr pptTmp = ppt;
 | |
| 	int	    *pwidthTmp = pwidth;
 | |
| 	BoxRec	    box;
 | |
| 
 | |
| 	box.x1 = pptTmp->x;
 | |
| 	box.x2 = box.x1 + *pwidthTmp;
 | |
| 	box.y2 = box.y1 = pptTmp->y;
 | |
| 
 | |
| 	while(--nptTmp) 
 | |
| 	{
 | |
| 	   pptTmp++;
 | |
| 	   pwidthTmp++;
 | |
| 	   if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
 | |
| 	   if(box.x2 < (pptTmp->x + *pwidthTmp))
 | |
| 		box.x2 = pptTmp->x + *pwidthTmp;
 | |
| 	   if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
 | |
| 	   else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
 | |
| 	}
 | |
| 
 | |
| 	box.y2++;
 | |
| 
 | |
|         if(!pGC->miTranslate) {
 | |
|            TRANSLATE_BOX(box, pDrawable);
 | |
|         }
 | |
|         TRIM_BOX(box, pGC); 
 | |
| 
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     
 | |
|     (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted);
 | |
| 
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageSetSpans(DrawablePtr  pDrawable,
 | |
| 	       GCPtr	    pGC,
 | |
| 	       char	    *pcharsrc,
 | |
| 	       DDXPointPtr  ppt,
 | |
| 	       int	    *pwidth,
 | |
| 	       int	    npt,
 | |
| 	       int	    fSorted)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (npt && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	DDXPointPtr pptTmp = ppt;
 | |
| 	int	    *pwidthTmp = pwidth;
 | |
| 	int	    nptTmp = npt;
 | |
| 	BoxRec	    box;
 | |
| 
 | |
| 	box.x1 = pptTmp->x;
 | |
| 	box.x2 = box.x1 + *pwidthTmp;
 | |
| 	box.y2 = box.y1 = pptTmp->y;
 | |
| 
 | |
| 	while(--nptTmp) 
 | |
| 	{
 | |
| 	   pptTmp++;
 | |
| 	   pwidthTmp++;
 | |
| 	   if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
 | |
| 	   if(box.x2 < (pptTmp->x + *pwidthTmp))
 | |
| 		box.x2 = pptTmp->x + *pwidthTmp;
 | |
| 	   if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
 | |
| 	   else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
 | |
| 	}
 | |
| 
 | |
| 	box.y2++;
 | |
| 
 | |
|         if(!pGC->miTranslate) {
 | |
|            TRANSLATE_BOX(box, pDrawable);
 | |
|         }
 | |
|         TRIM_BOX(box, pGC); 
 | |
| 
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damagePutImage(DrawablePtr  pDrawable,
 | |
| 	       GCPtr	    pGC,
 | |
| 	       int	    depth,
 | |
| 	       int	    x,
 | |
| 	       int	    y,
 | |
| 	       int	    w,
 | |
| 	       int	    h,
 | |
| 	       int	    leftPad,
 | |
| 	       int	    format,
 | |
| 	       char	    *pImage)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
|     if (checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	box.x1 = x + pDrawable->x;
 | |
| 	box.x2 = box.x1 + w;
 | |
| 	box.y1 = y + pDrawable->y;
 | |
| 	box.y2 = box.y1 + h;
 | |
| 
 | |
| 	TRIM_BOX(box, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
 | |
| 		leftPad, format, pImage);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static RegionPtr
 | |
| damageCopyArea(DrawablePtr   pSrc,
 | |
| 	       DrawablePtr  pDst,
 | |
| 	       GC	    *pGC,
 | |
| 	       int	    srcx,
 | |
| 	       int	    srcy,
 | |
| 	       int	    width,
 | |
| 	       int	    height,
 | |
| 	       int	    dstx,
 | |
| 	       int	    dsty)
 | |
| {
 | |
|     RegionPtr ret;
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
 | |
|     
 | |
|     /* The driver will only call SourceValidate() when pSrc != pDst,
 | |
|      * but the software sprite (misprite.c) always need to know when a
 | |
|      * drawable is copied so it can remove the sprite. See #1030. */
 | |
|     if ((pSrc == pDst) && pSrc->pScreen->SourceValidate &&
 | |
| 	pSrc->type == DRAWABLE_WINDOW &&
 | |
| 	((WindowPtr)pSrc)->viewable)
 | |
|     {
 | |
| 	(*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
 | |
|     }
 | |
|     
 | |
|     if (checkGCDamage (pDst, pGC))
 | |
|     {
 | |
| 	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))
 | |
| 	   damageDamageBox (pDst, &box, pGC->subWindowMode);
 | |
|     }
 | |
| 
 | |
|     ret = (*pGC->ops->CopyArea)(pSrc, pDst,
 | |
|             pGC, srcx, srcy, width, height, dstx, dsty);
 | |
|     damageReportPostOp (pDst);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static RegionPtr
 | |
| damageCopyPlane(DrawablePtr	pSrc,
 | |
| 		DrawablePtr	pDst,
 | |
| 		GCPtr		pGC,
 | |
| 		int		srcx,
 | |
| 		int		srcy,
 | |
| 		int		width,
 | |
| 		int		height,
 | |
| 		int		dstx,
 | |
| 		int		dsty,
 | |
| 		unsigned long	bitPlane)
 | |
| {
 | |
|     RegionPtr ret;
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
 | |
| 
 | |
|     /* The driver will only call SourceValidate() when pSrc != pDst,
 | |
|      * but the software sprite (misprite.c) always need to know when a
 | |
|      * drawable is copied so it can remove the sprite. See #1030. */
 | |
|     if ((pSrc == pDst) && pSrc->pScreen->SourceValidate &&
 | |
| 	pSrc->type == DRAWABLE_WINDOW &&
 | |
| 	((WindowPtr)pSrc)->viewable)
 | |
|     {
 | |
|         (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
 | |
|     }
 | |
| 
 | |
|     if (checkGCDamage (pDst, pGC))
 | |
|     {
 | |
| 	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))
 | |
| 	   damageDamageBox (pDst, &box, pGC->subWindowMode);
 | |
|     }
 | |
| 
 | |
|     ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
 | |
| 	       pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
 | |
|     damageReportPostOp (pDst);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static void
 | |
| damagePolyPoint(DrawablePtr pDrawable,
 | |
| 		GCPtr	    pGC,
 | |
| 		int	    mode,
 | |
| 		int	    npt,
 | |
| 		xPoint	    *ppt)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (npt && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	BoxRec	box;
 | |
| 	int	nptTmp = npt;
 | |
| 	xPoint	*pptTmp = ppt;
 | |
| 
 | |
| 	box.x2 = box.x1 = pptTmp->x;
 | |
| 	box.y2 = box.y1 = pptTmp->y;
 | |
| 
 | |
| 	/* this could be slow if the points were spread out */
 | |
| 
 | |
| 	while(--nptTmp) 
 | |
| 	{
 | |
| 	   pptTmp++;
 | |
| 	   if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
 | |
| 	   else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
 | |
| 	   if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
 | |
| 	   else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
 | |
| 	}
 | |
| 
 | |
| 	box.x2++;
 | |
| 	box.y2++;
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damagePolylines(DrawablePtr pDrawable,
 | |
| 		GCPtr	    pGC,
 | |
| 		int	    mode,
 | |
| 		int	    npt,
 | |
| 		DDXPointPtr ppt)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (npt && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	int	    nptTmp = npt;
 | |
| 	DDXPointPtr pptTmp = ppt;
 | |
| 	BoxRec	    box;
 | |
| 	int	    extra = pGC->lineWidth >> 1;
 | |
| 
 | |
| 	box.x2 = box.x1 = pptTmp->x;
 | |
| 	box.y2 = box.y1 = pptTmp->y;
 | |
| 
 | |
| 	if(nptTmp > 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(--nptTmp) 
 | |
| 	   {
 | |
| 		pptTmp++;
 | |
| 		x += pptTmp->x;
 | |
| 		y += pptTmp->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(--nptTmp) 
 | |
| 	   {
 | |
| 		pptTmp++;
 | |
| 		if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
 | |
| 		else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
 | |
| 		if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
 | |
| 		else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	box.x2++;
 | |
| 	box.y2++;
 | |
| 
 | |
| 	if(extra) 
 | |
| 	{
 | |
| 	   box.x1 -= extra;
 | |
| 	   box.x2 += extra;
 | |
| 	   box.y1 -= extra;
 | |
| 	   box.y2 += extra;
 | |
|         }
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damagePolySegment(DrawablePtr	pDrawable,
 | |
| 		  GCPtr		pGC,
 | |
| 		  int		nSeg,
 | |
| 		  xSegment	*pSeg)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (nSeg && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	BoxRec	    box;
 | |
| 	int	    extra = pGC->lineWidth;
 | |
| 	int	    nsegTmp = nSeg;
 | |
| 	xSegment    *pSegTmp = pSeg;
 | |
| 
 | |
|         if(pGC->capStyle != CapProjecting)
 | |
| 	   extra >>= 1;
 | |
| 
 | |
| 	if(pSegTmp->x2 > pSegTmp->x1) {
 | |
| 	    box.x1 = pSegTmp->x1;
 | |
| 	    box.x2 = pSegTmp->x2;
 | |
| 	} else {
 | |
| 	    box.x2 = pSegTmp->x1;
 | |
| 	    box.x1 = pSegTmp->x2;
 | |
| 	}
 | |
| 
 | |
| 	if(pSegTmp->y2 > pSegTmp->y1) {
 | |
| 	    box.y1 = pSegTmp->y1;
 | |
| 	    box.y2 = pSegTmp->y2;
 | |
| 	} else {
 | |
| 	    box.y2 = pSegTmp->y1;
 | |
| 	    box.y1 = pSegTmp->y2;
 | |
| 	}
 | |
| 
 | |
| 	while(--nsegTmp) 
 | |
| 	{
 | |
| 	    pSegTmp++;
 | |
| 	    if(pSegTmp->x2 > pSegTmp->x1) 
 | |
| 	    {
 | |
| 		if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1;
 | |
| 		if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2;
 | |
| 	    }
 | |
| 	    else 
 | |
| 	    {
 | |
| 		if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2;
 | |
| 		if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1;
 | |
| 	    }
 | |
| 	    if(pSegTmp->y2 > pSegTmp->y1) 
 | |
| 	    {
 | |
| 		if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1;
 | |
| 		if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2;
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2;
 | |
| 		if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	box.x2++;
 | |
| 	box.y2++;
 | |
| 
 | |
| 	if(extra) 
 | |
| 	{
 | |
| 	   box.x1 -= extra;
 | |
| 	   box.x2 += extra;
 | |
| 	   box.y1 -= extra;
 | |
| 	   box.y2 += extra;
 | |
|         }
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damagePolyRectangle(DrawablePtr  pDrawable,
 | |
| 		    GCPtr        pGC,
 | |
| 		    int	         nRects,
 | |
| 		    xRectangle  *pRects)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (nRects && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	BoxRec	    box;
 | |
| 	int	    offset1, offset2, offset3;
 | |
| 	int	    nRectsTmp = nRects;
 | |
| 	xRectangle  *pRectsTmp = pRects;
 | |
| 
 | |
| 	offset2 = pGC->lineWidth;
 | |
| 	if(!offset2) offset2 = 1;
 | |
| 	offset1 = offset2 >> 1;
 | |
| 	offset3 = offset2 - offset1;
 | |
| 
 | |
| 	while(nRectsTmp--)
 | |
| 	{
 | |
| 	    box.x1 = pRectsTmp->x - offset1;
 | |
| 	    box.y1 = pRectsTmp->y - offset1;
 | |
| 	    box.x2 = box.x1 + pRectsTmp->width + offset2;
 | |
| 	    box.y2 = box.y1 + offset2;
 | |
| 	    TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	    if(BOX_NOT_EMPTY(box))
 | |
| 		damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
| 
 | |
| 	    box.x1 = pRectsTmp->x - offset1;
 | |
| 	    box.y1 = pRectsTmp->y + offset3;
 | |
| 	    box.x2 = box.x1 + offset2;
 | |
| 	    box.y2 = box.y1 + pRectsTmp->height - offset2;
 | |
| 	    TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	    if(BOX_NOT_EMPTY(box))
 | |
| 		damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
| 
 | |
| 	    box.x1 = pRectsTmp->x + pRectsTmp->width - offset1;
 | |
| 	    box.y1 = pRectsTmp->y + offset3;
 | |
| 	    box.x2 = box.x1 + offset2;
 | |
| 	    box.y2 = box.y1 + pRectsTmp->height - offset2;
 | |
| 	    TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	    if(BOX_NOT_EMPTY(box))
 | |
| 		damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
| 
 | |
| 	    box.x1 = pRectsTmp->x - offset1;
 | |
| 	    box.y1 = pRectsTmp->y + pRectsTmp->height - offset1;
 | |
| 	    box.x2 = box.x1 + pRectsTmp->width + offset2;
 | |
| 	    box.y2 = box.y1 + offset2;
 | |
| 	    TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	    if(BOX_NOT_EMPTY(box))
 | |
| 		damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
| 
 | |
| 	    pRectsTmp++;
 | |
| 	}
 | |
|     }
 | |
|     (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damagePolyArc(DrawablePtr   pDrawable,
 | |
| 	      GCPtr	    pGC,
 | |
| 	      int	    nArcs,
 | |
| 	      xArc	    *pArcs)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (nArcs && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	int	extra = pGC->lineWidth >> 1;
 | |
| 	BoxRec	box;
 | |
| 	int	nArcsTmp = nArcs;
 | |
| 	xArc	*pArcsTmp = pArcs;
 | |
| 
 | |
| 	box.x1 = pArcsTmp->x;
 | |
| 	box.x2 = box.x1 + pArcsTmp->width;
 | |
| 	box.y1 = pArcsTmp->y;
 | |
| 	box.y2 = box.y1 + pArcsTmp->height;
 | |
| 
 | |
| 	while(--nArcsTmp) 
 | |
| 	{
 | |
| 	    pArcsTmp++;
 | |
| 	    if(box.x1 > pArcsTmp->x)
 | |
| 		box.x1 = pArcsTmp->x;
 | |
| 	    if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
 | |
| 		box.x2 = pArcsTmp->x + pArcsTmp->width;
 | |
| 	    if(box.y1 > pArcsTmp->y) 
 | |
| 		box.y1 = pArcsTmp->y;
 | |
| 	    if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
 | |
| 		box.y2 = pArcsTmp->y + pArcsTmp->height;
 | |
|         }
 | |
| 
 | |
| 	if(extra) 
 | |
| 	{
 | |
| 	   box.x1 -= extra;
 | |
| 	   box.x2 += extra;
 | |
| 	   box.y1 -= extra;
 | |
| 	   box.y2 += extra;
 | |
|         }
 | |
| 
 | |
| 	box.x2++;
 | |
| 	box.y2++;
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageFillPolygon(DrawablePtr	pDrawable,
 | |
| 		  GCPtr		pGC,
 | |
| 		  int		shape,
 | |
| 		  int		mode,
 | |
| 		  int		npt,
 | |
| 		  DDXPointPtr	ppt)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (npt > 2 && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	DDXPointPtr pptTmp = ppt;
 | |
| 	int	    nptTmp = npt;
 | |
| 	BoxRec	    box;
 | |
| 
 | |
| 	box.x2 = box.x1 = pptTmp->x;
 | |
| 	box.y2 = box.y1 = pptTmp->y;
 | |
| 
 | |
| 	if(mode != CoordModeOrigin) 
 | |
| 	{
 | |
| 	   int x = box.x1;
 | |
| 	   int y = box.y1;
 | |
| 	   while(--nptTmp) 
 | |
| 	   {
 | |
| 		pptTmp++;
 | |
| 		x += pptTmp->x;
 | |
| 		y += pptTmp->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(--nptTmp) 
 | |
| 	   {
 | |
| 		pptTmp++;
 | |
| 		if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
 | |
| 		else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
 | |
| 		if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
 | |
| 		else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	box.x2++;
 | |
| 	box.y2++;
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     
 | |
|     (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| damagePolyFillRect(DrawablePtr	pDrawable,
 | |
| 		   GCPtr	pGC,
 | |
| 		   int		nRects,
 | |
| 		   xRectangle	*pRects)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
|     if (nRects && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	BoxRec	    box;
 | |
| 	xRectangle  *pRectsTmp = pRects;
 | |
| 	int	    nRectsTmp = nRects;
 | |
| 
 | |
| 	box.x1 = pRectsTmp->x;
 | |
| 	box.x2 = box.x1 + pRectsTmp->width;
 | |
| 	box.y1 = pRectsTmp->y;
 | |
| 	box.y2 = box.y1 + pRectsTmp->height;
 | |
| 
 | |
| 	while(--nRectsTmp) 
 | |
| 	{
 | |
| 	    pRectsTmp++;
 | |
| 	    if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x;
 | |
| 	    if(box.x2 < (pRectsTmp->x + pRectsTmp->width))
 | |
| 		box.x2 = pRectsTmp->x + pRectsTmp->width;
 | |
| 	    if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y;
 | |
| 	    if(box.y2 < (pRectsTmp->y + pRectsTmp->height))
 | |
| 		box.y2 = pRectsTmp->y + pRectsTmp->height;
 | |
| 	}
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	    damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| damagePolyFillArc(DrawablePtr	pDrawable,
 | |
| 		  GCPtr		pGC,
 | |
| 		  int		nArcs,
 | |
| 		  xArc		*pArcs)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (nArcs && checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	BoxRec	box;
 | |
| 	int	nArcsTmp = nArcs;
 | |
| 	xArc	*pArcsTmp = pArcs;
 | |
| 
 | |
| 	box.x1 = pArcsTmp->x;
 | |
| 	box.x2 = box.x1 + pArcsTmp->width;
 | |
| 	box.y1 = pArcsTmp->y;
 | |
| 	box.y2 = box.y1 + pArcsTmp->height;
 | |
| 
 | |
| 	while(--nArcsTmp) 
 | |
| 	{
 | |
| 	    pArcsTmp++;
 | |
| 	    if(box.x1 > pArcsTmp->x)
 | |
| 		box.x1 = pArcsTmp->x;
 | |
| 	    if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
 | |
| 		box.x2 = pArcsTmp->x + pArcsTmp->width;
 | |
| 	    if(box.y1 > pArcsTmp->y)
 | |
| 		box.y1 = pArcsTmp->y;
 | |
| 	    if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
 | |
| 		box.y2 = pArcsTmp->y + pArcsTmp->height;
 | |
|         }
 | |
| 
 | |
| 	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * general Poly/Image text function.  Extract glyph information,
 | |
|  * compute bounding box and remove cursor if it is overlapped.
 | |
|  */
 | |
| 
 | |
| static void
 | |
| damageDamageChars (DrawablePtr	pDrawable,
 | |
| 		   FontPtr	font,
 | |
| 		   int		x,
 | |
| 		   int		y,
 | |
| 		   unsigned int	n,
 | |
| 		   CharInfoPtr	*charinfo,
 | |
| 		   Bool		imageblt,
 | |
| 		   int		subWindowMode)
 | |
| {
 | |
|     ExtentInfoRec   extents;
 | |
|     BoxRec	    box;
 | |
| 
 | |
|     QueryGlyphExtents(font, charinfo, n, &extents);
 | |
|     if (imageblt)
 | |
|     {
 | |
| 	if (extents.overallWidth > extents.overallRight)
 | |
| 	    extents.overallRight = extents.overallWidth;
 | |
| 	if (extents.overallWidth < extents.overallLeft)
 | |
| 	    extents.overallLeft = extents.overallWidth;
 | |
| 	if (extents.overallLeft > 0)
 | |
| 	    extents.overallLeft = 0;
 | |
| 	if (extents.fontAscent > extents.overallAscent)
 | |
| 	    extents.overallAscent = extents.fontAscent;
 | |
| 	if (extents.fontDescent > extents.overallDescent)
 | |
| 	    extents.overallDescent = extents.fontDescent;
 | |
|     }
 | |
|     box.x1 = x + extents.overallLeft;
 | |
|     box.y1 = y - extents.overallAscent;
 | |
|     box.x2 = x + extents.overallRight;
 | |
|     box.y2 = y + extents.overallDescent;
 | |
|     damageDamageBox (pDrawable, &box, subWindowMode);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * values for textType:
 | |
|  */
 | |
| #define TT_POLY8   0
 | |
| #define TT_IMAGE8  1
 | |
| #define TT_POLY16  2
 | |
| #define TT_IMAGE16 3
 | |
| 
 | |
| static int 
 | |
| damageText (DrawablePtr	    pDrawable,
 | |
| 	    GCPtr	    pGC,
 | |
| 	    int		    x,
 | |
| 	    int		    y,
 | |
| 	    unsigned long   count,
 | |
| 	    char	    *chars,
 | |
| 	    FontEncoding    fontEncoding,
 | |
| 	    Bool	    textType)
 | |
| {
 | |
|     CharInfoPtr	    *charinfo;
 | |
|     CharInfoPtr	    *info;
 | |
|     unsigned long   i;
 | |
|     unsigned int    n;
 | |
|     int		    w;
 | |
|     Bool	    imageblt;
 | |
| 
 | |
|     imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
 | |
| 
 | |
|     charinfo = (CharInfoPtr *) xalloc(count * sizeof(CharInfoPtr));
 | |
|     if (!charinfo)
 | |
| 	return x;
 | |
| 
 | |
|     GetGlyphs(pGC->font, count, (unsigned char *)chars,
 | |
| 	      fontEncoding, &i, charinfo);
 | |
|     n = (unsigned int)i;
 | |
|     w = 0;
 | |
|     if (!imageblt)
 | |
| 	for (info = charinfo; i--; info++)
 | |
| 	    w += (*info)->metrics.characterWidth;
 | |
| 
 | |
|     if (n != 0) {
 | |
| 	damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n,
 | |
| 			   charinfo, imageblt, pGC->subWindowMode);
 | |
| 	if (imageblt)
 | |
| 	    (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
 | |
| 				       FONTGLYPHS(pGC->font));
 | |
| 	else
 | |
| 	    (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
 | |
| 				      FONTGLYPHS(pGC->font));
 | |
|     }
 | |
|     xfree(charinfo);
 | |
|     return x + w;
 | |
| }
 | |
| 
 | |
| static int
 | |
| damagePolyText8(DrawablePtr pDrawable,
 | |
| 		GCPtr	    pGC,
 | |
| 		int	    x,
 | |
| 		int	    y,
 | |
| 		int	    count,
 | |
| 		char	    *chars)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (checkGCDamage (pDrawable, pGC))
 | |
| 	x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
 | |
| 		    Linear8Bit, TT_POLY8);
 | |
|     else
 | |
| 	x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
|     return x;
 | |
| }
 | |
| 
 | |
| static int
 | |
| damagePolyText16(DrawablePtr	pDrawable,
 | |
| 		 GCPtr		pGC,
 | |
| 		 int		x,
 | |
| 		 int		y,
 | |
| 		 int		count,
 | |
| 		 unsigned short	*chars)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (checkGCDamage (pDrawable, pGC))
 | |
| 	x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
 | |
| 		    FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
 | |
| 		    TT_POLY16);
 | |
|     else
 | |
| 	x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
|     return x;
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageImageText8(DrawablePtr	pDrawable,
 | |
| 		 GCPtr		pGC,
 | |
| 		 int		x,
 | |
| 		 int		y,
 | |
| 		 int		count,
 | |
| 		 char		*chars)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (checkGCDamage (pDrawable, pGC))
 | |
| 	damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
 | |
| 		    Linear8Bit, TT_IMAGE8);
 | |
|     else
 | |
| 	(*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageImageText16(DrawablePtr	pDrawable,
 | |
| 		  GCPtr		pGC,
 | |
| 		  int		x,
 | |
| 		  int		y,
 | |
| 		  int		count,
 | |
| 		  unsigned short *chars)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
| 
 | |
|     if (checkGCDamage (pDrawable, pGC))
 | |
| 	damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
 | |
| 		    FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
 | |
| 		    TT_IMAGE16);
 | |
|     else
 | |
| 	(*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| damageImageGlyphBlt(DrawablePtr	    pDrawable,
 | |
| 		    GCPtr	    pGC,
 | |
| 		    int		    x,
 | |
| 		    int		    y,
 | |
| 		    unsigned int    nglyph,
 | |
| 		    CharInfoPtr	    *ppci,
 | |
| 		    pointer	    pglyphBase)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
|     damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
 | |
| 		       nglyph, ppci, TRUE, pGC->subWindowMode);
 | |
|     (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph,
 | |
| 					ppci, pglyphBase);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damagePolyGlyphBlt(DrawablePtr	pDrawable,
 | |
| 		   GCPtr	pGC,
 | |
| 		   int		x,
 | |
| 		   int		y,
 | |
| 		   unsigned int	nglyph,
 | |
| 		   CharInfoPtr	*ppci,
 | |
| 		   pointer	pglyphBase)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
|     damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
 | |
| 		       nglyph, ppci, FALSE, pGC->subWindowMode);
 | |
|     (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
 | |
| 				ppci, pglyphBase);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damagePushPixels(GCPtr		pGC,
 | |
| 		 PixmapPtr	pBitMap,
 | |
| 		 DrawablePtr	pDrawable,
 | |
| 		 int		dx,
 | |
| 		 int		dy,
 | |
| 		 int		xOrg,
 | |
| 		 int		yOrg)
 | |
| {
 | |
|     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | |
|     if(checkGCDamage (pDrawable, pGC))
 | |
|     {
 | |
| 	BoxRec box;
 | |
| 
 | |
|         box.x1 = xOrg;
 | |
|         box.y1 = yOrg;
 | |
| 
 | |
|         if(!pGC->miTranslate) {
 | |
|            box.x1 += pDrawable->x;          
 | |
|            box.y1 += pDrawable->y;          
 | |
|         }
 | |
| 
 | |
| 	box.x2 = box.x1 + dx;
 | |
| 	box.y2 = box.y1 + dy;
 | |
| 
 | |
| 	TRIM_BOX(box, pGC);
 | |
| 	if(BOX_NOT_EMPTY(box))
 | |
| 	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
 | |
|     }
 | |
|     (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
 | |
|     damageReportPostOp (pDrawable);
 | |
|     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage)
 | |
| {
 | |
|     while (*pPrev)
 | |
|     {
 | |
| 	if (*pPrev == pDamage)
 | |
| 	{
 | |
| 	    *pPrev = pDamage->pNext;
 | |
| 	    return;
 | |
| 	}
 | |
| 	pPrev = &(*pPrev)->pNext;
 | |
|     }
 | |
| #if DAMAGE_VALIDATE_ENABLE
 | |
|     ErrorF ("Damage not on list\n");
 | |
|     abort ();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage)
 | |
| {
 | |
| #if DAMAGE_VALIDATE_ENABLE
 | |
|     DamagePtr	pOld;
 | |
| 
 | |
|     for (pOld = *pPrev; pOld; pOld = pOld->pNext)
 | |
| 	if (pOld == pDamage) {
 | |
| 	    ErrorF ("Damage already on list\n");
 | |
| 	    abort ();
 | |
| 	}
 | |
| #endif
 | |
|     pDamage->pNext = *pPrev;
 | |
|     *pPrev = pDamage;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| damageDestroyPixmap (PixmapPtr pPixmap)
 | |
| {
 | |
|     ScreenPtr	pScreen = pPixmap->drawable.pScreen;
 | |
|     damageScrPriv(pScreen);
 | |
| 
 | |
|     if (pPixmap->refcnt == 1)
 | |
|     {
 | |
| 	DamagePtr	*pPrev = getPixmapDamageRef (pPixmap);
 | |
| 	DamagePtr	pDamage;
 | |
| 
 | |
| 	while ((pDamage = *pPrev))
 | |
| 	{
 | |
| 	    damageRemoveDamage (pPrev, pDamage);
 | |
| 	    if (!pDamage->isWindow)
 | |
| 		DamageDestroy (pDamage);
 | |
| 	}
 | |
|     }
 | |
|     unwrap (pScrPriv, pScreen, DestroyPixmap);
 | |
|     (*pScreen->DestroyPixmap) (pPixmap);
 | |
|     wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| damageCopyWindow(WindowPtr	pWindow,
 | |
| 		 DDXPointRec	ptOldOrg,
 | |
| 		 RegionPtr	prgnSrc)
 | |
| {
 | |
|     ScreenPtr pScreen = pWindow->drawable.pScreen;
 | |
|     damageScrPriv(pScreen);
 | |
| 
 | |
|     if (getWindowDamage (pWindow))
 | |
|     {
 | |
| 	int dx = pWindow->drawable.x - ptOldOrg.x;
 | |
| 	int dy = pWindow->drawable.y - ptOldOrg.y;
 | |
| 	
 | |
| 	/*
 | |
| 	 * The region comes in source relative, but the damage occurs
 | |
| 	 * at the destination location.  Translate back and forth.
 | |
| 	 */
 | |
| 	REGION_TRANSLATE (pScreen, prgnSrc, dx, dy);
 | |
| 	damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE, -1);
 | |
| 	REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
 | |
|     }
 | |
|     unwrap (pScrPriv, pScreen, CopyWindow);
 | |
|     (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
 | |
|     damageReportPostOp (&pWindow->drawable);
 | |
|     wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
 | |
| }
 | |
| 
 | |
| static GCOps damageGCOps = {
 | |
|     damageFillSpans, damageSetSpans,
 | |
|     damagePutImage, damageCopyArea,
 | |
|     damageCopyPlane, damagePolyPoint,
 | |
|     damagePolylines, damagePolySegment,
 | |
|     damagePolyRectangle, damagePolyArc,
 | |
|     damageFillPolygon, damagePolyFillRect,
 | |
|     damagePolyFillArc, damagePolyText8,
 | |
|     damagePolyText16, damageImageText8,
 | |
|     damageImageText16, damageImageGlyphBlt,
 | |
|     damagePolyGlyphBlt, damagePushPixels,
 | |
|     {NULL}		/* devPrivate */
 | |
| };
 | |
| 
 | |
| static void
 | |
| damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
 | |
| {
 | |
|     DamagePtr	pDamage;
 | |
|     ScreenPtr	pScreen = pWindow->drawable.pScreen;
 | |
|     damageScrPriv(pScreen);
 | |
| 
 | |
|     if ((pDamage = damageGetWinPriv(pWindow)))
 | |
|     {
 | |
| 	PixmapPtr   pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow);
 | |
| 	DamagePtr   *pPrev = getPixmapDamageRef(pOldPixmap);
 | |
| 	
 | |
| 	while (pDamage)
 | |
| 	{
 | |
| 	    damageRemoveDamage (pPrev, pDamage);
 | |
| 	    pDamage = pDamage->pNextWin;
 | |
| 	}
 | |
|     }
 | |
|     unwrap (pScrPriv, pScreen, SetWindowPixmap);
 | |
|     (*pScreen->SetWindowPixmap) (pWindow, pPixmap);
 | |
|     wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
 | |
|     if ((pDamage = damageGetWinPriv(pWindow)))
 | |
|     {
 | |
| 	DamagePtr   *pPrev = getPixmapDamageRef(pPixmap);
 | |
| 	
 | |
| 	while (pDamage)
 | |
| 	{
 | |
| 	    damageInsertDamage (pPrev, pDamage);
 | |
| 	    pDamage = pDamage->pNextWin;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| damageDestroyWindow (WindowPtr pWindow)
 | |
| {
 | |
|     DamagePtr	pDamage;
 | |
|     ScreenPtr	pScreen = pWindow->drawable.pScreen;
 | |
|     Bool	ret;
 | |
|     damageScrPriv(pScreen);
 | |
| 
 | |
|     while ((pDamage = damageGetWinPriv(pWindow)))
 | |
|     {
 | |
| 	DamageUnregister (&pWindow->drawable, pDamage);
 | |
| 	DamageDestroy (pDamage);
 | |
|     }
 | |
|     unwrap (pScrPriv, pScreen, DestroyWindow);
 | |
|     ret = (*pScreen->DestroyWindow) (pWindow);
 | |
|     wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| damageCloseScreen (int i, ScreenPtr pScreen)
 | |
| {
 | |
|     damageScrPriv(pScreen);
 | |
| 
 | |
|     unwrap (pScrPriv, pScreen, DestroyPixmap);
 | |
|     unwrap (pScrPriv, pScreen, CreateGC);
 | |
|     unwrap (pScrPriv, pScreen, CopyWindow);
 | |
|     unwrap (pScrPriv, pScreen, CloseScreen);
 | |
|     xfree (pScrPriv);
 | |
|     return (*pScreen->CloseScreen) (i, pScreen);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| DamageSetup (ScreenPtr pScreen)
 | |
| {
 | |
|     DamageScrPrivPtr	pScrPriv;
 | |
| #ifdef RENDER
 | |
|     PictureScreenPtr	ps = GetPictureScreenIfSet(pScreen);
 | |
| #endif
 | |
| 
 | |
|     if (dixLookupPrivate(&pScreen->devPrivates, damageScrPrivateKey))
 | |
| 	return TRUE;
 | |
| 
 | |
|     if (!dixRequestPrivate(damageGCPrivateKey, sizeof(DamageGCPrivRec)))
 | |
| 	return FALSE;
 | |
| 
 | |
|     pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec));
 | |
|     if (!pScrPriv)
 | |
| 	return FALSE;
 | |
| 
 | |
|     pScrPriv->internalLevel = 0;
 | |
|     pScrPriv->pScreenDamage = 0;
 | |
| 
 | |
|     wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
 | |
|     wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
 | |
|     wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
 | |
|     wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
 | |
|     wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
 | |
|     wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen);
 | |
| #ifdef RENDER
 | |
|     if (ps) {
 | |
| 	wrap (pScrPriv, ps, Glyphs, damageGlyphs);
 | |
| 	wrap (pScrPriv, ps, Composite, damageComposite);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     dixSetPrivate(&pScreen->devPrivates, damageScrPrivateKey, pScrPriv);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| DamagePtr
 | |
| DamageCreate (DamageReportFunc  damageReport,
 | |
| 	      DamageDestroyFunc	damageDestroy,
 | |
| 	      DamageReportLevel	damageLevel,
 | |
| 	      Bool		isInternal,
 | |
| 	      ScreenPtr		pScreen,
 | |
| 	      void		*closure)
 | |
| {
 | |
|     DamagePtr	pDamage;
 | |
| 
 | |
|     pDamage = xalloc (sizeof (DamageRec));
 | |
|     if (!pDamage)
 | |
| 	return 0;
 | |
|     pDamage->pNext = 0;
 | |
|     pDamage->pNextWin = 0;
 | |
|     REGION_NULL(pScreen, &pDamage->damage);
 | |
|     REGION_NULL(pScreen, &pDamage->pendingDamage);
 | |
|     
 | |
|     pDamage->damageLevel = damageLevel;
 | |
|     pDamage->isInternal = isInternal;
 | |
|     pDamage->closure = closure;
 | |
|     pDamage->isWindow = FALSE;
 | |
|     pDamage->pDrawable = 0;
 | |
|     pDamage->reportAfter = FALSE;
 | |
| 
 | |
|     pDamage->damageReport = damageReport;
 | |
|     pDamage->damageDestroy = damageDestroy;
 | |
|     return pDamage;
 | |
| }
 | |
| 
 | |
| void
 | |
| DamageRegister (DrawablePtr pDrawable,
 | |
| 		DamagePtr   pDamage)
 | |
| {
 | |
|     if (pDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	WindowPtr   pWindow = (WindowPtr) pDrawable;
 | |
| 	winDamageRef(pWindow);
 | |
| 
 | |
| #if DAMAGE_VALIDATE_ENABLE
 | |
| 	DamagePtr   pOld;
 | |
| 	
 | |
| 	for (pOld = *pPrev; pOld; pOld = pOld->pNextWin)
 | |
| 	    if (pOld == pDamage) {
 | |
| 		ErrorF ("Damage already on window list\n");
 | |
| 		abort ();
 | |
| 	    }
 | |
| #endif
 | |
| 	pDamage->pNextWin = *pPrev;
 | |
| 	*pPrev = pDamage;
 | |
| 	pDamage->isWindow = TRUE;
 | |
|     }
 | |
|     else
 | |
| 	pDamage->isWindow = FALSE;
 | |
|     pDamage->pDrawable = pDrawable;
 | |
|     damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage);
 | |
| }
 | |
| 
 | |
| void
 | |
| DamageDrawInternal (ScreenPtr pScreen, Bool enable)
 | |
| {
 | |
|     damageScrPriv (pScreen);
 | |
| 
 | |
|     pScrPriv->internalLevel += enable ? 1 : -1;
 | |
| }
 | |
| 
 | |
| void
 | |
| DamageUnregister (DrawablePtr	    pDrawable,
 | |
| 		  DamagePtr	    pDamage)
 | |
| {
 | |
|     if (pDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	WindowPtr   pWindow = (WindowPtr) pDrawable;
 | |
| 	winDamageRef (pWindow);
 | |
| #if DAMAGE_VALIDATE_ENABLE
 | |
| 	int	found = 0;
 | |
| #endif
 | |
| 
 | |
| 	while (*pPrev)
 | |
| 	{
 | |
| 	    if (*pPrev == pDamage)
 | |
| 	    {
 | |
| 		*pPrev = pDamage->pNextWin;
 | |
| #if DAMAGE_VALIDATE_ENABLE
 | |
| 		found = 1;
 | |
| #endif
 | |
| 		break;
 | |
| 	    }
 | |
| 	    pPrev = &(*pPrev)->pNextWin;
 | |
| 	}
 | |
| #if DAMAGE_VALIDATE_ENABLE
 | |
| 	if (!found) {
 | |
| 	    ErrorF ("Damage not on window list\n");
 | |
| 	    abort ();
 | |
| 	}
 | |
| #endif
 | |
|     }
 | |
|     pDamage->pDrawable = 0;
 | |
|     damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage);
 | |
| }
 | |
| 
 | |
| void
 | |
| DamageDestroy (DamagePtr    pDamage)
 | |
| {
 | |
|     if (pDamage->damageDestroy)
 | |
| 	(*pDamage->damageDestroy) (pDamage, pDamage->closure);
 | |
|     REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage);
 | |
|     REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->pendingDamage);
 | |
|     xfree (pDamage);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| DamageSubtract (DamagePtr	    pDamage,
 | |
| 		const RegionPtr	    pRegion)
 | |
| {
 | |
|     RegionPtr	pClip;
 | |
|     RegionRec	pixmapClip;
 | |
|     DrawablePtr	pDrawable = pDamage->pDrawable;
 | |
|     
 | |
|     REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion);
 | |
|     if (pDrawable)
 | |
|     {
 | |
| 	if (pDrawable->type == DRAWABLE_WINDOW)
 | |
| 	    pClip = &((WindowPtr) pDrawable)->borderClip;
 | |
| 	else
 | |
| 	{
 | |
| 	    BoxRec  box;
 | |
| 
 | |
| 	    box.x1 = pDrawable->x;
 | |
| 	    box.y1 = pDrawable->y;
 | |
| 	    box.x2 = pDrawable->x + pDrawable->width;
 | |
| 	    box.y2 = pDrawable->y + pDrawable->height;
 | |
| 	    REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1);
 | |
| 	    pClip = &pixmapClip;
 | |
| 	}
 | |
| 	REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y);
 | |
| 	REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip);
 | |
| 	REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y);
 | |
| 	if (pDrawable->type != DRAWABLE_WINDOW)
 | |
| 	    REGION_UNINIT(pDrawable->pScreen, &pixmapClip);
 | |
|     }
 | |
|     return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage);
 | |
| }
 | |
| 
 | |
| void
 | |
| DamageEmpty (DamagePtr	    pDamage)
 | |
| {
 | |
|     REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage);
 | |
| }
 | |
| 
 | |
| RegionPtr
 | |
| DamageRegion (DamagePtr		    pDamage)
 | |
| {
 | |
|     return &pDamage->damage;
 | |
| }
 | |
| 
 | |
| _X_EXPORT RegionPtr
 | |
| DamagePendingRegion (DamagePtr	    pDamage)
 | |
| {
 | |
|     return &pDamage->pendingDamage;
 | |
| }
 | |
| 
 | |
| _X_EXPORT void
 | |
| DamageDamageRegion (DrawablePtr	pDrawable,
 | |
| 		    RegionPtr	pRegion)
 | |
| {
 | |
|     damageDamageRegion (pDrawable, pRegion, FALSE, -1);
 | |
| 
 | |
|     /* Go back and report this damage for DamagePtrs with reportAfter set, since
 | |
|      * this call isn't part of an in-progress drawing op in the call chain and
 | |
|      * the DDX probably just wants to know about it right away.
 | |
|      */
 | |
|     damageReportPostOp (pDrawable);
 | |
| }
 | |
| 
 | |
| void
 | |
| DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter)
 | |
| {
 | |
|     pDamage->reportAfter = reportAfter;
 | |
| }
 |