231 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
| 
 | |
| Copyright 1993, 1998  The Open Group
 | |
| 
 | |
| 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.
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included
 | |
| in all copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 | |
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 | |
| IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
 | |
| OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 | |
| ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | |
| OTHER DEALINGS IN THE SOFTWARE.
 | |
| 
 | |
| Except as contained in this notice, the name of The Open Group shall
 | |
| not be used in advertising or otherwise to promote the sale, use or
 | |
| other dealings in this Software without prior written authorization
 | |
| from The Open Group.
 | |
| 
 | |
| */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include "scrnintstr.h"
 | |
| #include "gcstruct.h"
 | |
| #include "pixmapstr.h"
 | |
| #include "windowstr.h"
 | |
| #include "migc.h"
 | |
| 
 | |
| /* ARGSUSED */
 | |
| void
 | |
| miChangeGC(GCPtr pGC, unsigned long mask)
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void
 | |
| miDestroyGC(GCPtr pGC)
 | |
| {
 | |
|     if (pGC->pRotatedPixmap)
 | |
|         (*pGC->pScreen->DestroyPixmap) (pGC->pRotatedPixmap);
 | |
|     if (pGC->freeCompClip)
 | |
|         RegionDestroy(pGC->pCompositeClip);
 | |
| }
 | |
| 
 | |
| void
 | |
| miDestroyClip(GCPtr pGC)
 | |
| {
 | |
|     if (pGC->clientClipType == CT_NONE)
 | |
|         return;
 | |
|     else if (pGC->clientClipType == CT_PIXMAP) {
 | |
|         (*pGC->pScreen->DestroyPixmap) ((PixmapPtr) (pGC->clientClip));
 | |
|     }
 | |
|     else {
 | |
|         /*
 | |
|          * we know we'll never have a list of rectangles, since ChangeClip
 | |
|          * immediately turns them into a region
 | |
|          */
 | |
|         RegionDestroy(pGC->clientClip);
 | |
|     }
 | |
|     pGC->clientClip = NULL;
 | |
|     pGC->clientClipType = CT_NONE;
 | |
| }
 | |
| 
 | |
| void
 | |
| miChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
 | |
| {
 | |
|     (*pGC->funcs->DestroyClip) (pGC);
 | |
|     if (type == CT_PIXMAP) {
 | |
|         /* convert the pixmap to a region */
 | |
|         pGC->clientClip = (pointer) BitmapToRegion(pGC->pScreen,
 | |
|                                                    (PixmapPtr) pvalue);
 | |
|         (*pGC->pScreen->DestroyPixmap) (pvalue);
 | |
|     }
 | |
|     else if (type == CT_REGION) {
 | |
|         /* stuff the region in the GC */
 | |
|         pGC->clientClip = pvalue;
 | |
|     }
 | |
|     else if (type != CT_NONE) {
 | |
|         pGC->clientClip = (pointer) RegionFromRects(nrects,
 | |
|                                                     (xRectangle *) pvalue,
 | |
|                                                     type);
 | |
|         free(pvalue);
 | |
|     }
 | |
|     pGC->clientClipType = (type != CT_NONE &&
 | |
|                            pGC->clientClip) ? CT_REGION : CT_NONE;
 | |
|     pGC->stateChanges |= GCClipMask;
 | |
| }
 | |
| 
 | |
| void
 | |
| miCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
 | |
| {
 | |
|     RegionPtr prgnNew;
 | |
| 
 | |
|     switch (pgcSrc->clientClipType) {
 | |
|     case CT_PIXMAP:
 | |
|         ((PixmapPtr) pgcSrc->clientClip)->refcnt++;
 | |
|         /* Fall through !! */
 | |
|     case CT_NONE:
 | |
|         (*pgcDst->funcs->ChangeClip) (pgcDst, (int) pgcSrc->clientClipType,
 | |
|                                       pgcSrc->clientClip, 0);
 | |
|         break;
 | |
|     case CT_REGION:
 | |
|         prgnNew = RegionCreate(NULL, 1);
 | |
|         RegionCopy(prgnNew, (RegionPtr) (pgcSrc->clientClip));
 | |
|         (*pgcDst->funcs->ChangeClip) (pgcDst, CT_REGION, (pointer) prgnNew, 0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* ARGSUSED */
 | |
| void
 | |
| miCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst)
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void
 | |
| miComputeCompositeClip(GCPtr pGC, DrawablePtr pDrawable)
 | |
| {
 | |
|     if (pDrawable->type == DRAWABLE_WINDOW) {
 | |
|         WindowPtr pWin = (WindowPtr) pDrawable;
 | |
|         RegionPtr pregWin;
 | |
|         Bool freeTmpClip, freeCompClip;
 | |
| 
 | |
|         if (pGC->subWindowMode == IncludeInferiors) {
 | |
|             pregWin = NotClippedByChildren(pWin);
 | |
|             freeTmpClip = TRUE;
 | |
|         }
 | |
|         else {
 | |
|             pregWin = &pWin->clipList;
 | |
|             freeTmpClip = FALSE;
 | |
|         }
 | |
|         freeCompClip = pGC->freeCompClip;
 | |
| 
 | |
|         /*
 | |
|          * if there is no client clip, we can get by with just keeping the
 | |
|          * pointer we got, and remembering whether or not should destroy (or
 | |
|          * maybe re-use) it later.  this way, we avoid unnecessary copying of
 | |
|          * regions.  (this wins especially if many clients clip by children
 | |
|          * and have no client clip.)
 | |
|          */
 | |
|         if (pGC->clientClipType == CT_NONE) {
 | |
|             if (freeCompClip)
 | |
|                 RegionDestroy(pGC->pCompositeClip);
 | |
|             pGC->pCompositeClip = pregWin;
 | |
|             pGC->freeCompClip = freeTmpClip;
 | |
|         }
 | |
|         else {
 | |
|             /*
 | |
|              * we need one 'real' region to put into the composite clip. if
 | |
|              * pregWin the current composite clip are real, we can get rid of
 | |
|              * one. if pregWin is real and the current composite clip isn't,
 | |
|              * use pregWin for the composite clip. if the current composite
 | |
|              * clip is real and pregWin isn't, use the current composite
 | |
|              * clip. if neither is real, create a new region.
 | |
|              */
 | |
| 
 | |
|             RegionTranslate(pGC->clientClip,
 | |
|                             pDrawable->x + pGC->clipOrg.x,
 | |
|                             pDrawable->y + pGC->clipOrg.y);
 | |
| 
 | |
|             if (freeCompClip) {
 | |
|                 RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip);
 | |
|                 if (freeTmpClip)
 | |
|                     RegionDestroy(pregWin);
 | |
|             }
 | |
|             else if (freeTmpClip) {
 | |
|                 RegionIntersect(pregWin, pregWin, pGC->clientClip);
 | |
|                 pGC->pCompositeClip = pregWin;
 | |
|             }
 | |
|             else {
 | |
|                 pGC->pCompositeClip = RegionCreate(NullBox, 0);
 | |
|                 RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip);
 | |
|             }
 | |
|             pGC->freeCompClip = TRUE;
 | |
|             RegionTranslate(pGC->clientClip,
 | |
|                             -(pDrawable->x + pGC->clipOrg.x),
 | |
|                             -(pDrawable->y + pGC->clipOrg.y));
 | |
|         }
 | |
|     }                           /* end of composite clip for a window */
 | |
|     else {
 | |
|         BoxRec pixbounds;
 | |
| 
 | |
|         /* XXX should we translate by drawable.x/y here ? */
 | |
|         /* If you want pixmaps in offscreen memory, yes */
 | |
|         pixbounds.x1 = pDrawable->x;
 | |
|         pixbounds.y1 = pDrawable->y;
 | |
|         pixbounds.x2 = pDrawable->x + pDrawable->width;
 | |
|         pixbounds.y2 = pDrawable->y + pDrawable->height;
 | |
| 
 | |
|         if (pGC->freeCompClip) {
 | |
|             RegionReset(pGC->pCompositeClip, &pixbounds);
 | |
|         }
 | |
|         else {
 | |
|             pGC->freeCompClip = TRUE;
 | |
|             pGC->pCompositeClip = RegionCreate(&pixbounds, 1);
 | |
|         }
 | |
| 
 | |
|         if (pGC->clientClipType == CT_REGION) {
 | |
|             if (pDrawable->x || pDrawable->y) {
 | |
|                 RegionTranslate(pGC->clientClip,
 | |
|                                 pDrawable->x + pGC->clipOrg.x,
 | |
|                                 pDrawable->y + pGC->clipOrg.y);
 | |
|                 RegionIntersect(pGC->pCompositeClip,
 | |
|                                 pGC->pCompositeClip, pGC->clientClip);
 | |
|                 RegionTranslate(pGC->clientClip,
 | |
|                                 -(pDrawable->x + pGC->clipOrg.x),
 | |
|                                 -(pDrawable->y + pGC->clipOrg.y));
 | |
|             }
 | |
|             else {
 | |
|                 RegionTranslate(pGC->pCompositeClip,
 | |
|                                 -pGC->clipOrg.x, -pGC->clipOrg.y);
 | |
|                 RegionIntersect(pGC->pCompositeClip,
 | |
|                                 pGC->pCompositeClip, pGC->clientClip);
 | |
|                 RegionTranslate(pGC->pCompositeClip,
 | |
|                                 pGC->clipOrg.x, pGC->clipOrg.y);
 | |
|             }
 | |
|         }
 | |
|     }                           /* end of composite clip for pixmap */
 | |
| }                               /* end miComputeCompositeClip */
 |