diff options
author | marha <marha@users.sourceforge.net> | 2010-05-15 16:28:11 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2010-05-15 16:28:11 +0000 |
commit | c38dead3ea7e177728d90cd815cf4eead0c9f534 (patch) | |
tree | b809dba1dc9013bb1e67a5ee388f2dd217dc0f88 /xorg-server/mi | |
parent | 6083a94d68878c9ad5f59b28bd07e4738e9fb7b4 (diff) | |
download | vcxsrv-c38dead3ea7e177728d90cd815cf4eead0c9f534.tar.gz vcxsrv-c38dead3ea7e177728d90cd815cf4eead0c9f534.tar.bz2 vcxsrv-c38dead3ea7e177728d90cd815cf4eead0c9f534.zip |
xserver git update 15/5/2010
Diffstat (limited to 'xorg-server/mi')
29 files changed, 17360 insertions, 17434 deletions
diff --git a/xorg-server/mi/miarc.c b/xorg-server/mi/miarc.c index d182d2592..3b4a628e4 100644 --- a/xorg-server/mi/miarc.c +++ b/xorg-server/mi/miarc.c @@ -213,16 +213,6 @@ typedef struct _miPolyArc { miArcJoinPtr joins;
} miPolyArcRec, *miPolyArcPtr;
-#define GCValsFunction 0
-#define GCValsForeground 1
-#define GCValsBackground 2
-#define GCValsLineWidth 3
-#define GCValsCapStyle 4
-#define GCValsJoinStyle 5
-#define GCValsMask (GCFunction | GCForeground | GCBackground | \
- GCLineWidth | GCCapStyle | GCJoinStyle)
-static CARD32 gcvals[6];
-
static void fillSpans(DrawablePtr pDrawable, GCPtr pGC);
static void newFinalSpan(int y, int xmin, int xmax);
static void drawArc(xArc *tarc, int l, int a0, int a1, miArcFacePtr right,
@@ -800,7 +790,7 @@ miComputeWideEllipse(int lw, xArc *parc) if (!lw)
lw = 1;
k = (parc->height >> 1) + ((lw - 1) >> 1);
- spdata = xalloc(sizeof(miArcSpanData) + sizeof(miArcSpan) * (k + 2));
+ spdata = malloc(sizeof(miArcSpanData) + sizeof(miArcSpan) * (k + 2));
if (!spdata)
return NULL;
spdata->spans = (miArcSpan *)(spdata + 1);
@@ -831,14 +821,14 @@ miFillWideEllipse( yorgu = parc->height + pGC->lineWidth;
n = (sizeof(int) * 2) * yorgu;
- widths = xalloc(n + (sizeof(DDXPointRec) * 2) * yorgu);
+ widths = malloc(n + (sizeof(DDXPointRec) * 2) * yorgu);
if (!widths)
return;
points = (DDXPointPtr)((char *)widths + n);
spdata = miComputeWideEllipse((int)pGC->lineWidth, parc);
if (!spdata)
{
- xfree(widths);
+ free(widths);
return;
}
pts = points;
@@ -927,10 +917,10 @@ miFillWideEllipse( wids += 2;
}
}
- xfree(spdata);
+ free(spdata);
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
- xfree(widths);
+ free(widths);
}
/*
@@ -1045,13 +1035,18 @@ miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) pGCTo = GetScratchGC(1, pDraw->pScreen);
if (!pGCTo)
return;
- gcvals[GCValsFunction] = GXcopy;
- gcvals[GCValsForeground] = 1;
- gcvals[GCValsBackground] = 0;
- gcvals[GCValsLineWidth] = pGC->lineWidth;
- gcvals[GCValsCapStyle] = pGC->capStyle;
- gcvals[GCValsJoinStyle] = pGC->joinStyle;
- dixChangeGC(NullClient, pGCTo, GCValsMask, gcvals, NULL);
+ {
+ ChangeGCVal gcvals[6];
+ gcvals[0].val = GXcopy;
+ gcvals[1].val = 1;
+ gcvals[2].val = 0;
+ gcvals[3].val = pGC->lineWidth;
+ gcvals[4].val = pGC->capStyle;
+ gcvals[5].val = pGC->joinStyle;
+ ChangeGC(NullClient, pGCTo, GCFunction |
+ GCForeground | GCBackground | GCLineWidth |
+ GCCapStyle | GCJoinStyle, gcvals);
+ }
/* allocate a 1 bit deep pixmap of the appropriate size, and
* validate it */
@@ -1090,11 +1085,14 @@ miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) iphase >= 0;
iphase--)
{
+ ChangeGCVal gcval;
if (iphase == 1) {
- dixChangeGC (NullClient, pGC, GCForeground, &bg, NULL);
+ gcval.val = bg;
+ ChangeGC (NullClient, pGC, GCForeground, &gcval);
ValidateGC (pDraw, pGC);
} else if (pGC->lineStyle == LineDoubleDash) {
- dixChangeGC (NullClient, pGC, GCForeground, &fg, NULL);
+ gcval.val = fg;
+ ChangeGC (NullClient, pGC, GCForeground, &gcval);
ValidateGC (pDraw, pGC);
}
for (i = 0; i < polyArcs[iphase].narcs; i++) {
@@ -1266,7 +1264,7 @@ miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft, arc.height = width;
arc.angle1 = -miDatan2 (corner.y - center.y, corner.x - center.x);
arc.angle2 = a;
- pArcPts = xalloc (3 * sizeof (SppPointRec));
+ pArcPts = malloc(3 * sizeof (SppPointRec));
if (!pArcPts)
return;
pArcPts[0].x = otherCorner.x;
@@ -1282,7 +1280,7 @@ miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft, * rest of the line */
miFillSppPoly(pDraw, pGC, cpt, pArcPts, xOrg, yOrg, xFtrans, yFtrans);
}
- xfree(pArcPts);
+ free(pArcPts);
return;
case JoinMiter:
/*
@@ -1413,7 +1411,7 @@ miRoundCap( * rest of the line */
miFillSppPoly(pDraw, pGC, cpt, pArcPts, -xOrg, -yOrg, xFtrans, yFtrans);
}
- xfree(pArcPts);
+ free(pArcPts);
}
/*
@@ -1511,10 +1509,10 @@ miDatan2 (double dy, double dx) * This procedure allocates the space necessary to fit the arc points.
* Sometimes it's convenient for those points to be at the end of an existing
* array. (For example, if we want to leave a spare point to make sectors
- * instead of segments.) So we pass in the xalloc()ed chunk that contains the
+ * instead of segments.) So we pass in the malloc()ed chunk that contains the
* array and an index saying where we should start stashing the points.
* If there isn't an array already, we just pass in a null pointer and
- * count on xrealloc() to handle the null pointer correctly.
+ * count on realloc() to handle the null pointer correctly.
*/
static int
miGetArcPts(
@@ -1561,7 +1559,7 @@ miGetArcPts( count++;
cdt = 2 * miDcos(dt);
- if (!(poly = (SppPointPtr) xrealloc((pointer)*ppPts,
+ if (!(poly = (SppPointPtr) realloc((pointer)*ppPts,
(cpt + count) * sizeof(SppPointRec))))
return(0);
*ppPts = poly;
@@ -1624,7 +1622,7 @@ addCap ( if (*ncapsp == *sizep)
{
newsize = *sizep + ADD_REALLOC_STEP;
- cap = (miArcCapPtr) xrealloc (*capsp,
+ cap = (miArcCapPtr) realloc(*capsp,
newsize * sizeof (**capsp));
if (!cap)
return;
@@ -1655,7 +1653,7 @@ addJoin ( if (*njoinsp == *sizep)
{
newsize = *sizep + ADD_REALLOC_STEP;
- join = (miArcJoinPtr) xrealloc (*joinsp,
+ join = (miArcJoinPtr) realloc(*joinsp,
newsize * sizeof (**joinsp));
if (!join)
return;
@@ -1685,7 +1683,7 @@ addArc ( if (*narcsp == *sizep)
{
newsize = *sizep + ADD_REALLOC_STEP;
- arc = (miArcDataPtr) xrealloc (*arcsp,
+ arc = (miArcDataPtr) realloc(*arcsp,
newsize * sizeof (**arcsp));
if (!arc)
return NULL;
@@ -1710,13 +1708,13 @@ miFreeArcs( iphase--)
{
if (arcs[iphase].narcs > 0)
- xfree(arcs[iphase].arcs);
+ free(arcs[iphase].arcs);
if (arcs[iphase].njoins > 0)
- xfree(arcs[iphase].joins);
+ free(arcs[iphase].joins);
if (arcs[iphase].ncaps > 0)
- xfree(arcs[iphase].caps);
+ free(arcs[iphase].caps);
}
- xfree(arcs);
+ free(arcs);
}
/*
@@ -1800,13 +1798,13 @@ miComputeArcs ( isDoubleDash = (pGC->lineStyle == LineDoubleDash);
dashOffset = pGC->dashOffset;
- data = xalloc (narcs * sizeof (struct arcData));
+ data = malloc(narcs * sizeof (struct arcData));
if (!data)
return NULL;
- arcs = xalloc (sizeof (*arcs) * (isDoubleDash ? 2 : 1));
+ arcs = malloc(sizeof (*arcs) * (isDoubleDash ? 2 : 1));
if (!arcs)
{
- xfree(data);
+ free(data);
return NULL;
}
for (i = 0; i < narcs; i++) {
@@ -2155,11 +2153,11 @@ miComputeArcs ( arcs[iphase].arcs[arcs[iphase].narcs-1].cap =
arcs[iphase].ncaps;
}
- xfree(data);
+ free(data);
return arcs;
arcfail:
miFreeArcs(arcs, pGC);
- xfree(data);
+ free(data);
return NULL;
}
@@ -3016,7 +3014,7 @@ realAllocSpan (void) struct finalSpan *span;
int i;
- newChunk = xalloc (sizeof (struct finalSpanChunk));
+ newChunk = malloc(sizeof (struct finalSpanChunk));
if (!newChunk)
return (struct finalSpan *) NULL;
newChunk->next = chunks;
@@ -3039,11 +3037,11 @@ disposeFinalSpans (void) for (chunk = chunks; chunk; chunk = next) {
next = chunk->next;
- xfree (chunk);
+ free(chunk);
}
chunks = 0;
freeFinalSpans = 0;
- xfree(finalSpans);
+ free(finalSpans);
finalSpans = 0;
}
@@ -3063,8 +3061,8 @@ fillSpans ( if (nspans == 0)
return;
- xSpan = xSpans = xalloc (nspans * sizeof (DDXPointRec));
- xWidth = xWidths = xalloc (nspans * sizeof (int));
+ xSpan = xSpans = malloc(nspans * sizeof (DDXPointRec));
+ xWidth = xWidths = malloc(nspans * sizeof (int));
if (xSpans && xWidths)
{
i = 0;
@@ -3084,9 +3082,9 @@ fillSpans ( }
disposeFinalSpans ();
if (xSpans)
- xfree (xSpans);
+ free(xSpans);
if (xWidths)
- xfree (xWidths);
+ free(xWidths);
finalMiny = 0;
finalMaxy = -1;
finalSize = 0;
@@ -3121,7 +3119,7 @@ realFindSpan (int y) else
change = SPAN_REALLOC;
newSize = finalSize + change;
- newSpans = xalloc(newSize * sizeof (struct finalSpan *));
+ newSpans = malloc(newSize * sizeof (struct finalSpan *));
if (!newSpans)
return NULL;
newMiny = finalMiny;
@@ -3134,7 +3132,7 @@ realFindSpan (int y) memmove(((char *) newSpans) + (finalMiny-newMiny) * sizeof (struct finalSpan *),
(char *) finalSpans,
finalSize * sizeof (struct finalSpan *));
- xfree (finalSpans);
+ free(finalSpans);
}
if ((i = finalMiny - newMiny) > 0)
bzero ((char *)newSpans, i * sizeof (struct finalSpan *));
@@ -3477,7 +3475,7 @@ drawArc ( left->counterClock = temp;
}
}
- xfree(spdata);
+ free(spdata);
}
static void
diff --git a/xorg-server/mi/mibitblt.c b/xorg-server/mi/mibitblt.c index cc8b11d9c..b1e188d5a 100644 --- a/xorg-server/mi/mibitblt.c +++ b/xorg-server/mi/mibitblt.c @@ -1,831 +1,830 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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. - -******************************************************************/ -/* Author: Todd Newman (aided and abetted by Mr. Drewry) */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xprotostr.h> - -#include "misc.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "scrnintstr.h" -#include "mi.h" -#include "regionstr.h" -#include <X11/Xmd.h> -#include "servermd.h" - -#ifndef HAS_FFS -extern int ffs(int); -#endif - -/* MICOPYAREA -- public entry for the CopyArea request - * For each rectangle in the source region - * get the pixels with GetSpans - * set them in the destination with SetSpans - * We let SetSpans worry about clipping to the destination. - */ -RegionPtr -miCopyArea(DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GCPtr pGC, - int xIn, - int yIn, - int widthSrc, - int heightSrc, - int xOut, - int yOut) -{ - DDXPointPtr ppt, pptFirst; - unsigned int *pwidthFirst, *pwidth, *pbits; - BoxRec srcBox, *prect; - /* may be a new region, or just a copy */ - RegionPtr prgnSrcClip; - /* non-0 if we've created a src clip */ - RegionPtr prgnExposed; - int realSrcClip = 0; - int srcx, srcy, dstx, dsty, i, j, y, width, height, - xMin, xMax, yMin, yMax; - unsigned int *ordering; - int numRects; - BoxPtr boxes; - - srcx = xIn + pSrcDrawable->x; - srcy = yIn + pSrcDrawable->y; - - /* If the destination isn't realized, this is easy */ - if (pDstDrawable->type == DRAWABLE_WINDOW && - !((WindowPtr)pDstDrawable)->realized) - return NULL; - - /* clip the source */ - if (pSrcDrawable->type == DRAWABLE_PIXMAP) - { - BoxRec box; - - box.x1 = pSrcDrawable->x; - box.y1 = pSrcDrawable->y; - box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; - box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; - - prgnSrcClip = REGION_CREATE(pGC->pScreen, &box, 1); - realSrcClip = 1; - } - else - { - if (pGC->subWindowMode == IncludeInferiors) { - prgnSrcClip = NotClippedByChildren ((WindowPtr) pSrcDrawable); - realSrcClip = 1; - } else - prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; - } - - /* If the src drawable is a window, we need to translate the srcBox so - * that we can compare it with the window's clip region later on. */ - srcBox.x1 = srcx; - srcBox.y1 = srcy; - srcBox.x2 = srcx + widthSrc; - srcBox.y2 = srcy + heightSrc; - - dstx = xOut; - dsty = yOut; - if (pGC->miTranslate) - { - dstx += pDstDrawable->x; - dsty += pDstDrawable->y; - } - - pptFirst = ppt = xalloc(heightSrc * sizeof(DDXPointRec)); - pwidthFirst = pwidth = xalloc(heightSrc * sizeof(unsigned int)); - numRects = REGION_NUM_RECTS(prgnSrcClip); - boxes = REGION_RECTS(prgnSrcClip); - ordering = xalloc(numRects * sizeof(unsigned int)); - if(!pptFirst || !pwidthFirst || !ordering) - { - if (ordering) - xfree(ordering); - if (pwidthFirst) - xfree(pwidthFirst); - if (pptFirst) - xfree(pptFirst); - return NULL; - } - - /* If not the same drawable then order of move doesn't matter. - Following assumes that boxes are sorted from top - to bottom and left to right. - */ - if ((pSrcDrawable != pDstDrawable) && - ((pGC->subWindowMode != IncludeInferiors) || - (pSrcDrawable->type == DRAWABLE_PIXMAP) || - (pDstDrawable->type == DRAWABLE_PIXMAP))) - for (i=0; i < numRects; i++) - ordering[i] = i; - else { /* within same drawable, must sequence moves carefully! */ - if (dsty <= srcBox.y1) { /* Scroll up or stationary vertical. - Vertical order OK */ - if (dstx <= srcBox.x1) /* Scroll left or stationary horizontal. - Horizontal order OK as well */ - for (i=0; i < numRects; i++) - ordering[i] = i; - else { /* scroll right. must reverse horizontal banding of rects. */ - for (i=0, j=1, xMax=0; i < numRects; j=i+1, xMax=i) { - /* find extent of current horizontal band */ - y=boxes[i].y1; /* band has this y coordinate */ - while ((j < numRects) && (boxes[j].y1 == y)) - j++; - /* reverse the horizontal band in the output ordering */ - for (j-- ; j >= xMax; j--, i++) - ordering[i] = j; - } - } - } - else { /* Scroll down. Must reverse vertical banding. */ - if (dstx < srcBox.x1) { /* Scroll left. Horizontal order OK. */ - for (i=numRects-1, j=i-1, yMin=i, yMax=0; - i >= 0; - j=i-1, yMin=i) { - /* find extent of current horizontal band */ - y=boxes[i].y1; /* band has this y coordinate */ - while ((j >= 0) && (boxes[j].y1 == y)) - j--; - /* reverse the horizontal band in the output ordering */ - for (j++ ; j <= yMin; j++, i--, yMax++) - ordering[yMax] = j; - } - } - else /* Scroll right or horizontal stationary. - Reverse horizontal order as well (if stationary, horizontal - order can be swapped without penalty and this is faster - to compute). */ - for (i=0, j=numRects-1; i < numRects; i++, j--) - ordering[i] = j; - } - } - - for(i = 0; i < numRects; i++) - { - prect = &boxes[ordering[i]]; - xMin = max(prect->x1, srcBox.x1); - xMax = min(prect->x2, srcBox.x2); - yMin = max(prect->y1, srcBox.y1); - yMax = min(prect->y2, srcBox.y2); - /* is there anything visible here? */ - if(xMax <= xMin || yMax <= yMin) - continue; - - ppt = pptFirst; - pwidth = pwidthFirst; - y = yMin; - height = yMax - yMin; - width = xMax - xMin; - - for(j = 0; j < height; j++) - { - /* We must untranslate before calling GetSpans */ - ppt->x = xMin; - ppt++->y = y++; - *pwidth++ = width; - } - pbits = xalloc(height * PixmapBytePad(width, pSrcDrawable->depth)); - if (pbits) - { - (*pSrcDrawable->pScreen->GetSpans)(pSrcDrawable, width, pptFirst, - (int *)pwidthFirst, height, (char *)pbits); - ppt = pptFirst; - pwidth = pwidthFirst; - xMin -= (srcx - dstx); - y = yMin - (srcy - dsty); - for(j = 0; j < height; j++) - { - ppt->x = xMin; - ppt++->y = y++; - *pwidth++ = width; - } - - (*pGC->ops->SetSpans)(pDstDrawable, pGC, (char *)pbits, pptFirst, - (int *)pwidthFirst, height, TRUE); - xfree(pbits); - } - } - prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn, - widthSrc, heightSrc, xOut, yOut, (unsigned long)0); - if(realSrcClip) - REGION_DESTROY(pGC->pScreen, prgnSrcClip); - - xfree(ordering); - xfree(pwidthFirst); - xfree(pptFirst); - return prgnExposed; -} - -/* MIGETPLANE -- gets a bitmap representing one plane of pDraw - * A helper used for CopyPlane and XY format GetImage - * No clever strategy here, we grab a scanline at a time, pull out the - * bits and then stuff them in a 1 bit deep map. - */ -/* - * This should be replaced with something more general. mi shouldn't have to - * care about such things as scanline padding et alia. - */ -static -MiBits * -miGetPlane( - DrawablePtr pDraw, - int planeNum, /* number of the bitPlane */ - int sx, - int sy, - int w, - int h, - MiBits *result) -{ - int i, j, k, width, bitsPerPixel, widthInBytes; - DDXPointRec pt = {0, 0}; - MiBits pixel; - MiBits bit; - unsigned char *pCharsOut = NULL; - -#if BITMAP_SCANLINE_UNIT == 8 -#define OUT_TYPE unsigned char -#endif -#if BITMAP_SCANLINE_UNIT == 16 -#define OUT_TYPE CARD16 -#endif -#if BITMAP_SCANLINE_UNIT == 32 -#define OUT_TYPE CARD32 -#endif -#if BITMAP_SCANLINE_UNIT == 64 -#define OUT_TYPE CARD64 -#endif - - OUT_TYPE *pOut; - int delta = 0; - - sx += pDraw->x; - sy += pDraw->y; - widthInBytes = BitmapBytePad(w); - if(!result) - result = xcalloc(h, widthInBytes); - if (!result) - return NULL; - bitsPerPixel = pDraw->bitsPerPixel; - pOut = (OUT_TYPE *) result; - if(bitsPerPixel == 1) - { - pCharsOut = (unsigned char *) result; - width = w; - } - else - { - delta = (widthInBytes / (BITMAP_SCANLINE_UNIT / 8)) - - (w / BITMAP_SCANLINE_UNIT); - width = 1; -#if IMAGE_BYTE_ORDER == MSBFirst - planeNum += (32 - bitsPerPixel); -#endif - } - pt.y = sy; - for (i = h; --i >= 0; pt.y++) - { - pt.x = sx; - if(bitsPerPixel == 1) - { - (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1, - (char *)pCharsOut); - pCharsOut += widthInBytes; - } - else - { - k = 0; - for(j = w; --j >= 0; pt.x++) - { - /* Fetch the next pixel */ - (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1, - (char *)&pixel); - /* - * Now get the bit and insert into a bitmap in XY format. - */ - bit = (pixel >> planeNum) & 1; -#if 0 - /* XXX assuming bit order == byte order */ -#if BITMAP_BIT_ORDER == LSBFirst - bit <<= k; -#else - bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k); -#endif -#else - /* XXX assuming byte order == LSBFirst */ - if (screenInfo.bitmapBitOrder == LSBFirst) - bit <<= k; - else - bit <<= ((screenInfo.bitmapScanlineUnit - 1) - - (k % screenInfo.bitmapScanlineUnit)) + - ((k / screenInfo.bitmapScanlineUnit) * - screenInfo.bitmapScanlineUnit); -#endif - *pOut |= (OUT_TYPE) bit; - k++; - if (k == BITMAP_SCANLINE_UNIT) - { - pOut++; - k = 0; - } - } - pOut += delta; - } - } - return(result); - -} - -/* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw. - * Drawing through the clip mask we SetSpans() the bits into a - * bitmap and stipple those bits onto the destination drawable by doing a - * PolyFillRect over the whole drawable, - * then we invert the bitmap by copying it onto itself with an alu of - * GXinvert, invert the foreground/background colors of the gc, and draw - * the background bits. - * Note how the clipped out bits of the bitmap are always the background - * color so that the stipple never causes FillRect to draw them. - */ -static void -miOpqStipDrawable(DrawablePtr pDraw, GCPtr pGC, RegionPtr prgnSrc, - MiBits *pbits, int srcx, int w, int h, int dstx, int dsty) -{ - int oldfill, i; - unsigned long oldfg; - int *pwidth, *pwidthFirst; - ChangeGCVal gcv[6]; - PixmapPtr pStipple, pPixmap; - DDXPointRec oldOrg; - GCPtr pGCT; - DDXPointPtr ppt, pptFirst; - xRectangle rect; - RegionPtr prgnSrcClip; - - pPixmap = (*pDraw->pScreen->CreatePixmap) - (pDraw->pScreen, w + srcx, h, 1, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pPixmap) - return; - - /* Put the image into a 1 bit deep pixmap */ - pGCT = GetScratchGC(1, pDraw->pScreen); - if (!pGCT) - { - (*pDraw->pScreen->DestroyPixmap)(pPixmap); - return; - } - /* First set the whole pixmap to 0 */ - gcv[0].val = 0; - dixChangeGC(NullClient, pGCT, GCBackground, NULL, gcv); - ValidateGC((DrawablePtr)pPixmap, pGCT); - miClearDrawable((DrawablePtr)pPixmap, pGCT); - ppt = pptFirst = xalloc(h * sizeof(DDXPointRec)); - pwidth = pwidthFirst = xalloc(h * sizeof(int)); - if(!pptFirst || !pwidthFirst) - { - if (pwidthFirst) xfree(pwidthFirst); - if (pptFirst) xfree(pptFirst); - FreeScratchGC(pGCT); - return; - } - - /* we need a temporary region because ChangeClip must be assumed - to destroy what it's sent. note that this means we don't - have to free prgnSrcClip ourselves. - */ - prgnSrcClip = REGION_CREATE(pGCT->pScreen, NULL, 0); - REGION_COPY(pGCT->pScreen, prgnSrcClip, prgnSrc); - REGION_TRANSLATE(pGCT->pScreen, prgnSrcClip, srcx, 0); - (*pGCT->funcs->ChangeClip)(pGCT, CT_REGION, prgnSrcClip, 0); - ValidateGC((DrawablePtr)pPixmap, pGCT); - - /* Since we know pDraw is always a pixmap, we never need to think - * about translation here */ - for(i = 0; i < h; i++) - { - ppt->x = 0; - ppt++->y = i; - *pwidth++ = w + srcx; - } - - (*pGCT->ops->SetSpans)((DrawablePtr)pPixmap, pGCT, (char *)pbits, - pptFirst, pwidthFirst, h, TRUE); - xfree(pwidthFirst); - xfree(pptFirst); - - - /* Save current values from the client GC */ - oldfill = pGC->fillStyle; - pStipple = pGC->stipple; - if(pStipple) - pStipple->refcnt++; - oldOrg = pGC->patOrg; - - /* Set a new stipple in the drawable */ - gcv[0].val = FillStippled; - gcv[1].ptr = pPixmap; - gcv[2].val = dstx - srcx; - gcv[3].val = dsty; - - dixChangeGC(NullClient, pGC, - GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin, - NULL, gcv); - ValidateGC(pDraw, pGC); - - /* Fill the drawable with the stipple. This will draw the - * foreground color whereever 1 bits are set, leaving everything - * with 0 bits untouched. Note that the part outside the clip - * region is all 0s. */ - rect.x = dstx; - rect.y = dsty; - rect.width = w; - rect.height = h; - (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); - - /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only - * within the clipping region, the part outside is still all 0s */ - gcv[0].val = GXinvert; - dixChangeGC(NullClient, pGCT, GCFunction, NULL, gcv); - ValidateGC((DrawablePtr)pPixmap, pGCT); - (*pGCT->ops->CopyArea)((DrawablePtr)pPixmap, (DrawablePtr)pPixmap, - pGCT, 0, 0, w + srcx, h, 0, 0); - - /* Swap foreground and background colors on the GC for the drawable. - * Now when we fill the drawable, we will fill in the "Background" - * values */ - oldfg = pGC->fgPixel; - gcv[0].val = pGC->bgPixel; - gcv[1].val = oldfg; - gcv[2].ptr = pPixmap; - dixChangeGC(NullClient, pGC, GCForeground | GCBackground | GCStipple, - NULL, gcv); - ValidateGC(pDraw, pGC); - /* PolyFillRect might have bashed the rectangle */ - rect.x = dstx; - rect.y = dsty; - rect.width = w; - rect.height = h; - (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); - - /* Now put things back */ - if(pStipple) - pStipple->refcnt--; - gcv[0].val = oldfg; - gcv[1].val = pGC->fgPixel; - gcv[2].val = oldfill; - gcv[3].ptr = pStipple; - gcv[4].val = oldOrg.x; - gcv[5].val = oldOrg.y; - dixChangeGC(NullClient, pGC, - GCForeground | GCBackground | GCFillStyle | GCStipple | - GCTileStipXOrigin | GCTileStipYOrigin, NULL, gcv); - - ValidateGC(pDraw, pGC); - /* put what we hope is a smaller clip region back in the scratch gc */ - (*pGCT->funcs->ChangeClip)(pGCT, CT_NONE, NULL, 0); - FreeScratchGC(pGCT); - (*pDraw->pScreen->DestroyPixmap)(pPixmap); - -} - -/* MICOPYPLANE -- public entry for the CopyPlane request. - * strategy: - * First build up a bitmap out of the bits requested - * build a source clip - * Use the bitmap we've built up as a Stipple for the destination - */ -RegionPtr -miCopyPlane( DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GCPtr pGC, - int srcx, - int srcy, - int width, - int height, - int dstx, - int dsty, - unsigned long bitPlane) -{ - MiBits *ptile; - BoxRec box; - RegionPtr prgnSrc, prgnExposed; - - /* incorporate the source clip */ - - box.x1 = srcx + pSrcDrawable->x; - box.y1 = srcy + pSrcDrawable->y; - box.x2 = box.x1 + width; - box.y2 = box.y1 + height; - /* clip to visible drawable */ - if (box.x1 < pSrcDrawable->x) - box.x1 = pSrcDrawable->x; - if (box.y1 < pSrcDrawable->y) - box.y1 = pSrcDrawable->y; - if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) - box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; - if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) - box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; - if (box.x1 > box.x2) - box.x2 = box.x1; - if (box.y1 > box.y2) - box.y2 = box.y1; - prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1); - - if (pSrcDrawable->type != DRAWABLE_PIXMAP) { - /* clip to visible drawable */ - - if (pGC->subWindowMode == IncludeInferiors) - { - RegionPtr clipList = NotClippedByChildren ((WindowPtr) pSrcDrawable); - REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc, clipList); - REGION_DESTROY(pGC->pScreen, clipList); - } else - REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc, - &((WindowPtr)pSrcDrawable)->clipList); - } - - box = *REGION_EXTENTS(pGC->pScreen, prgnSrc); - REGION_TRANSLATE(pGC->pScreen, prgnSrc, -box.x1, -box.y1); - - if ((box.x2 > box.x1) && (box.y2 > box.y1)) - { - /* minimize the size of the data extracted */ - /* note that we convert the plane mask bitPlane into a plane number */ - box.x1 -= pSrcDrawable->x; - box.x2 -= pSrcDrawable->x; - box.y1 -= pSrcDrawable->y; - box.y2 -= pSrcDrawable->y; - ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1, - box.x1, box.y1, - box.x2 - box.x1, box.y2 - box.y1, - (MiBits *) NULL); - if (ptile) - { - miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0, - box.x2 - box.x1, box.y2 - box.y1, - dstx + box.x1 - srcx, dsty + box.y1 - srcy); - xfree(ptile); - } - } - prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, - width, height, dstx, dsty, bitPlane); - REGION_DESTROY(pGC->pScreen, prgnSrc); - return prgnExposed; -} - -/* MIGETIMAGE -- public entry for the GetImage Request - * We're getting the image into a memory buffer. While we have to use GetSpans - * to read a line from the device (since we don't know what that looks like), - * we can just write into the destination buffer - * - * two different strategies are used, depending on whether we're getting the - * image in Z format or XY format - * Z format: - * Line at a time, GetSpans a line into the destination buffer, then if the - * planemask is not all ones, we do a SetSpans into a temporary buffer (to get - * bits turned off) and then another GetSpans to get stuff back (because - * pixmaps are opaque, and we are passed in the memory to write into). This is - * pretty ugly and slow but works. Life is hard. - * XY format: - * get the single plane specified in planemask - */ -void -miGetImage( DrawablePtr pDraw, int sx, int sy, int w, int h, - unsigned int format, unsigned long planeMask, char *pDst) -{ - unsigned char depth; - int i, linelength, width, srcx, srcy; - DDXPointRec pt = {0, 0}; - XID gcv[2]; - PixmapPtr pPixmap = NULL; - GCPtr pGC = NULL; - - depth = pDraw->depth; - if(format == ZPixmap) - { - if ( (((1<<depth)-1)&planeMask) != (1<<depth)-1 ) - { - xPoint pt; - - pGC = GetScratchGC(depth, pDraw->pScreen); - if (!pGC) - return; - pPixmap = (*pDraw->pScreen->CreatePixmap) - (pDraw->pScreen, w, 1, depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pPixmap) - { - FreeScratchGC(pGC); - return; - } - /* - * Clear the pixmap before doing anything else - */ - ValidateGC((DrawablePtr)pPixmap, pGC); - pt.x = pt.y = 0; - width = w; - (*pGC->ops->FillSpans)((DrawablePtr)pPixmap, pGC, 1, &pt, &width, - TRUE); - - /* alu is already GXCopy */ - gcv[0] = (XID)planeMask; - DoChangeGC(pGC, GCPlaneMask, gcv, 0); - ValidateGC((DrawablePtr)pPixmap, pGC); - } - - linelength = PixmapBytePad(w, depth); - srcx = sx + pDraw->x; - srcy = sy + pDraw->y; - for(i = 0; i < h; i++) - { - pt.x = srcx; - pt.y = srcy + i; - width = w; - (*pDraw->pScreen->GetSpans)(pDraw, w, &pt, &width, 1, pDst); - if (pPixmap) - { - pt.x = 0; - pt.y = 0; - width = w; - (*pGC->ops->SetSpans)((DrawablePtr)pPixmap, pGC, pDst, - &pt, &width, 1, TRUE); - (*pDraw->pScreen->GetSpans)((DrawablePtr)pPixmap, w, &pt, - &width, 1, pDst); - } - pDst += linelength; - } - if (pPixmap) - { - (*pGC->pScreen->DestroyPixmap)(pPixmap); - FreeScratchGC(pGC); - } - } - else - { - (void) miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h, - (MiBits *)pDst); - } -} - -/* MIPUTIMAGE -- public entry for the PutImage request - * Here we benefit from knowing the format of the bits pointed to by pImage, - * even if we don't know how pDraw represents them. - * Three different strategies are used depending on the format - * XYBitmap Format: - * we just use the Opaque Stipple helper function to cover the destination - * Note that this covers all the planes of the drawable with the - * foreground color (masked with the GC planemask) where there are 1 bits - * and the background color (masked with the GC planemask) where there are - * 0 bits - * XYPixmap format: - * what we're called with is a series of XYBitmaps, but we only want - * each XYPixmap to update 1 plane, instead of updating all of them. - * we set the foreground color to be all 1s and the background to all 0s - * then for each plane, we set the plane mask to only effect that one - * plane and recursive call ourself with the format set to XYBitmap - * (This clever idea courtesy of RGD.) - * ZPixmap format: - * This part is simple, just call SetSpans - */ -void -miPutImage( DrawablePtr pDraw, GCPtr pGC, int depth, - int x, int y, int w, int h, - int leftPad, int format, char *pImage) -{ - DDXPointPtr pptFirst, ppt; - int *pwidthFirst, *pwidth; - RegionPtr prgnSrc; - BoxRec box; - unsigned long oldFg, oldBg; - XID gcv[3]; - unsigned long oldPlanemask; - unsigned long i; - long bytesPer; - - if (!w || !h) - return; - switch(format) - { - case XYBitmap: - - box.x1 = 0; - box.y1 = 0; - box.x2 = w; - box.y2 = h; - prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1); - - miOpqStipDrawable(pDraw, pGC, prgnSrc, (MiBits *) pImage, - leftPad, w, h, x, y); - REGION_DESTROY(pGC->pScreen, prgnSrc); - break; - - case XYPixmap: - depth = pGC->depth; - oldPlanemask = pGC->planemask; - oldFg = pGC->fgPixel; - oldBg = pGC->bgPixel; - gcv[0] = (XID)~0; - gcv[1] = (XID)0; - DoChangeGC(pGC, GCForeground | GCBackground, gcv, 0); - bytesPer = (long)h * BitmapBytePad(w + leftPad); - - for (i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer) - { - if (i & oldPlanemask) - { - gcv[0] = (XID)i; - DoChangeGC(pGC, GCPlaneMask, gcv, 0); - ValidateGC(pDraw, pGC); - (*pGC->ops->PutImage)(pDraw, pGC, 1, x, y, w, h, leftPad, - XYBitmap, (char *)pImage); - } - } - gcv[0] = (XID)oldPlanemask; - gcv[1] = (XID)oldFg; - gcv[2] = (XID)oldBg; - DoChangeGC(pGC, GCPlaneMask | GCForeground | GCBackground, gcv, 0); - ValidateGC(pDraw, pGC); - break; - - case ZPixmap: - ppt = pptFirst = xalloc(h * sizeof(DDXPointRec)); - pwidth = pwidthFirst = xalloc(h * sizeof(int)); - if(!pptFirst || !pwidthFirst) - { - if (pwidthFirst) - xfree(pwidthFirst); - if (pptFirst) - xfree(pptFirst); - return; - } - if (pGC->miTranslate) - { - x += pDraw->x; - y += pDraw->y; - } - - for(i = 0; i < h; i++) - { - ppt->x = x; - ppt->y = y + i; - ppt++; - *pwidth++ = w; - } - - (*pGC->ops->SetSpans)(pDraw, pGC, (char *)pImage, pptFirst, - pwidthFirst, h, TRUE); - xfree(pwidthFirst); - xfree(pptFirst); - break; - } -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+******************************************************************/
+/* Author: Todd Newman (aided and abetted by Mr. Drewry) */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xprotostr.h>
+
+#include "misc.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "mi.h"
+#include "regionstr.h"
+#include <X11/Xmd.h>
+#include "servermd.h"
+
+#ifndef HAS_FFS
+extern int ffs(int);
+#endif
+
+/* MICOPYAREA -- public entry for the CopyArea request
+ * For each rectangle in the source region
+ * get the pixels with GetSpans
+ * set them in the destination with SetSpans
+ * We let SetSpans worry about clipping to the destination.
+ */
+RegionPtr
+miCopyArea(DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ int xIn,
+ int yIn,
+ int widthSrc,
+ int heightSrc,
+ int xOut,
+ int yOut)
+{
+ DDXPointPtr ppt, pptFirst;
+ unsigned int *pwidthFirst, *pwidth, *pbits;
+ BoxRec srcBox, *prect;
+ /* may be a new region, or just a copy */
+ RegionPtr prgnSrcClip;
+ /* non-0 if we've created a src clip */
+ RegionPtr prgnExposed;
+ int realSrcClip = 0;
+ int srcx, srcy, dstx, dsty, i, j, y, width, height,
+ xMin, xMax, yMin, yMax;
+ unsigned int *ordering;
+ int numRects;
+ BoxPtr boxes;
+
+ srcx = xIn + pSrcDrawable->x;
+ srcy = yIn + pSrcDrawable->y;
+
+ /* If the destination isn't realized, this is easy */
+ if (pDstDrawable->type == DRAWABLE_WINDOW &&
+ !((WindowPtr)pDstDrawable)->realized)
+ return NULL;
+
+ /* clip the source */
+ if (pSrcDrawable->type == DRAWABLE_PIXMAP)
+ {
+ BoxRec box;
+
+ box.x1 = pSrcDrawable->x;
+ box.y1 = pSrcDrawable->y;
+ box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
+ box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
+
+ prgnSrcClip = REGION_CREATE(pGC->pScreen, &box, 1);
+ realSrcClip = 1;
+ }
+ else
+ {
+ if (pGC->subWindowMode == IncludeInferiors) {
+ prgnSrcClip = NotClippedByChildren ((WindowPtr) pSrcDrawable);
+ realSrcClip = 1;
+ } else
+ prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
+ }
+
+ /* If the src drawable is a window, we need to translate the srcBox so
+ * that we can compare it with the window's clip region later on. */
+ srcBox.x1 = srcx;
+ srcBox.y1 = srcy;
+ srcBox.x2 = srcx + widthSrc;
+ srcBox.y2 = srcy + heightSrc;
+
+ dstx = xOut;
+ dsty = yOut;
+ if (pGC->miTranslate)
+ {
+ dstx += pDstDrawable->x;
+ dsty += pDstDrawable->y;
+ }
+
+ pptFirst = ppt = malloc(heightSrc * sizeof(DDXPointRec));
+ pwidthFirst = pwidth = malloc(heightSrc * sizeof(unsigned int));
+ numRects = REGION_NUM_RECTS(prgnSrcClip);
+ boxes = REGION_RECTS(prgnSrcClip);
+ ordering = malloc(numRects * sizeof(unsigned int));
+ if(!pptFirst || !pwidthFirst || !ordering)
+ {
+ if (ordering)
+ free(ordering);
+ if (pwidthFirst)
+ free(pwidthFirst);
+ if (pptFirst)
+ free(pptFirst);
+ return NULL;
+ }
+
+ /* If not the same drawable then order of move doesn't matter.
+ Following assumes that boxes are sorted from top
+ to bottom and left to right.
+ */
+ if ((pSrcDrawable != pDstDrawable) &&
+ ((pGC->subWindowMode != IncludeInferiors) ||
+ (pSrcDrawable->type == DRAWABLE_PIXMAP) ||
+ (pDstDrawable->type == DRAWABLE_PIXMAP)))
+ for (i=0; i < numRects; i++)
+ ordering[i] = i;
+ else { /* within same drawable, must sequence moves carefully! */
+ if (dsty <= srcBox.y1) { /* Scroll up or stationary vertical.
+ Vertical order OK */
+ if (dstx <= srcBox.x1) /* Scroll left or stationary horizontal.
+ Horizontal order OK as well */
+ for (i=0; i < numRects; i++)
+ ordering[i] = i;
+ else { /* scroll right. must reverse horizontal banding of rects. */
+ for (i=0, j=1, xMax=0; i < numRects; j=i+1, xMax=i) {
+ /* find extent of current horizontal band */
+ y=boxes[i].y1; /* band has this y coordinate */
+ while ((j < numRects) && (boxes[j].y1 == y))
+ j++;
+ /* reverse the horizontal band in the output ordering */
+ for (j-- ; j >= xMax; j--, i++)
+ ordering[i] = j;
+ }
+ }
+ }
+ else { /* Scroll down. Must reverse vertical banding. */
+ if (dstx < srcBox.x1) { /* Scroll left. Horizontal order OK. */
+ for (i=numRects-1, j=i-1, yMin=i, yMax=0;
+ i >= 0;
+ j=i-1, yMin=i) {
+ /* find extent of current horizontal band */
+ y=boxes[i].y1; /* band has this y coordinate */
+ while ((j >= 0) && (boxes[j].y1 == y))
+ j--;
+ /* reverse the horizontal band in the output ordering */
+ for (j++ ; j <= yMin; j++, i--, yMax++)
+ ordering[yMax] = j;
+ }
+ }
+ else /* Scroll right or horizontal stationary.
+ Reverse horizontal order as well (if stationary, horizontal
+ order can be swapped without penalty and this is faster
+ to compute). */
+ for (i=0, j=numRects-1; i < numRects; i++, j--)
+ ordering[i] = j;
+ }
+ }
+
+ for(i = 0; i < numRects; i++)
+ {
+ prect = &boxes[ordering[i]];
+ xMin = max(prect->x1, srcBox.x1);
+ xMax = min(prect->x2, srcBox.x2);
+ yMin = max(prect->y1, srcBox.y1);
+ yMax = min(prect->y2, srcBox.y2);
+ /* is there anything visible here? */
+ if(xMax <= xMin || yMax <= yMin)
+ continue;
+
+ ppt = pptFirst;
+ pwidth = pwidthFirst;
+ y = yMin;
+ height = yMax - yMin;
+ width = xMax - xMin;
+
+ for(j = 0; j < height; j++)
+ {
+ /* We must untranslate before calling GetSpans */
+ ppt->x = xMin;
+ ppt++->y = y++;
+ *pwidth++ = width;
+ }
+ pbits = malloc(height * PixmapBytePad(width, pSrcDrawable->depth));
+ if (pbits)
+ {
+ (*pSrcDrawable->pScreen->GetSpans)(pSrcDrawable, width, pptFirst,
+ (int *)pwidthFirst, height, (char *)pbits);
+ ppt = pptFirst;
+ pwidth = pwidthFirst;
+ xMin -= (srcx - dstx);
+ y = yMin - (srcy - dsty);
+ for(j = 0; j < height; j++)
+ {
+ ppt->x = xMin;
+ ppt++->y = y++;
+ *pwidth++ = width;
+ }
+
+ (*pGC->ops->SetSpans)(pDstDrawable, pGC, (char *)pbits, pptFirst,
+ (int *)pwidthFirst, height, TRUE);
+ free(pbits);
+ }
+ }
+ prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
+ widthSrc, heightSrc, xOut, yOut, (unsigned long)0);
+ if(realSrcClip)
+ REGION_DESTROY(pGC->pScreen, prgnSrcClip);
+
+ free(ordering);
+ free(pwidthFirst);
+ free(pptFirst);
+ return prgnExposed;
+}
+
+/* MIGETPLANE -- gets a bitmap representing one plane of pDraw
+ * A helper used for CopyPlane and XY format GetImage
+ * No clever strategy here, we grab a scanline at a time, pull out the
+ * bits and then stuff them in a 1 bit deep map.
+ */
+/*
+ * This should be replaced with something more general. mi shouldn't have to
+ * care about such things as scanline padding et alia.
+ */
+static
+MiBits *
+miGetPlane(
+ DrawablePtr pDraw,
+ int planeNum, /* number of the bitPlane */
+ int sx,
+ int sy,
+ int w,
+ int h,
+ MiBits *result)
+{
+ int i, j, k, width, bitsPerPixel, widthInBytes;
+ DDXPointRec pt = {0, 0};
+ MiBits pixel;
+ MiBits bit;
+ unsigned char *pCharsOut = NULL;
+
+#if BITMAP_SCANLINE_UNIT == 8
+#define OUT_TYPE unsigned char
+#endif
+#if BITMAP_SCANLINE_UNIT == 16
+#define OUT_TYPE CARD16
+#endif
+#if BITMAP_SCANLINE_UNIT == 32
+#define OUT_TYPE CARD32
+#endif
+#if BITMAP_SCANLINE_UNIT == 64
+#define OUT_TYPE CARD64
+#endif
+
+ OUT_TYPE *pOut;
+ int delta = 0;
+
+ sx += pDraw->x;
+ sy += pDraw->y;
+ widthInBytes = BitmapBytePad(w);
+ if(!result)
+ result = calloc(h, widthInBytes);
+ if (!result)
+ return NULL;
+ bitsPerPixel = pDraw->bitsPerPixel;
+ pOut = (OUT_TYPE *) result;
+ if(bitsPerPixel == 1)
+ {
+ pCharsOut = (unsigned char *) result;
+ width = w;
+ }
+ else
+ {
+ delta = (widthInBytes / (BITMAP_SCANLINE_UNIT / 8)) -
+ (w / BITMAP_SCANLINE_UNIT);
+ width = 1;
+#if IMAGE_BYTE_ORDER == MSBFirst
+ planeNum += (32 - bitsPerPixel);
+#endif
+ }
+ pt.y = sy;
+ for (i = h; --i >= 0; pt.y++)
+ {
+ pt.x = sx;
+ if(bitsPerPixel == 1)
+ {
+ (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1,
+ (char *)pCharsOut);
+ pCharsOut += widthInBytes;
+ }
+ else
+ {
+ k = 0;
+ for(j = w; --j >= 0; pt.x++)
+ {
+ /* Fetch the next pixel */
+ (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1,
+ (char *)&pixel);
+ /*
+ * Now get the bit and insert into a bitmap in XY format.
+ */
+ bit = (pixel >> planeNum) & 1;
+#if 0
+ /* XXX assuming bit order == byte order */
+#if BITMAP_BIT_ORDER == LSBFirst
+ bit <<= k;
+#else
+ bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k);
+#endif
+#else
+ /* XXX assuming byte order == LSBFirst */
+ if (screenInfo.bitmapBitOrder == LSBFirst)
+ bit <<= k;
+ else
+ bit <<= ((screenInfo.bitmapScanlineUnit - 1) -
+ (k % screenInfo.bitmapScanlineUnit)) +
+ ((k / screenInfo.bitmapScanlineUnit) *
+ screenInfo.bitmapScanlineUnit);
+#endif
+ *pOut |= (OUT_TYPE) bit;
+ k++;
+ if (k == BITMAP_SCANLINE_UNIT)
+ {
+ pOut++;
+ k = 0;
+ }
+ }
+ pOut += delta;
+ }
+ }
+ return(result);
+
+}
+
+/* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw.
+ * Drawing through the clip mask we SetSpans() the bits into a
+ * bitmap and stipple those bits onto the destination drawable by doing a
+ * PolyFillRect over the whole drawable,
+ * then we invert the bitmap by copying it onto itself with an alu of
+ * GXinvert, invert the foreground/background colors of the gc, and draw
+ * the background bits.
+ * Note how the clipped out bits of the bitmap are always the background
+ * color so that the stipple never causes FillRect to draw them.
+ */
+static void
+miOpqStipDrawable(DrawablePtr pDraw, GCPtr pGC, RegionPtr prgnSrc,
+ MiBits *pbits, int srcx, int w, int h, int dstx, int dsty)
+{
+ int oldfill, i;
+ unsigned long oldfg;
+ int *pwidth, *pwidthFirst;
+ ChangeGCVal gcv[6];
+ PixmapPtr pStipple, pPixmap;
+ DDXPointRec oldOrg;
+ GCPtr pGCT;
+ DDXPointPtr ppt, pptFirst;
+ xRectangle rect;
+ RegionPtr prgnSrcClip;
+
+ pPixmap = (*pDraw->pScreen->CreatePixmap)
+ (pDraw->pScreen, w + srcx, h, 1,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap)
+ return;
+
+ /* Put the image into a 1 bit deep pixmap */
+ pGCT = GetScratchGC(1, pDraw->pScreen);
+ if (!pGCT)
+ {
+ (*pDraw->pScreen->DestroyPixmap)(pPixmap);
+ return;
+ }
+ /* First set the whole pixmap to 0 */
+ gcv[0].val = 0;
+ ChangeGC(NullClient, pGCT, GCBackground, gcv);
+ ValidateGC((DrawablePtr)pPixmap, pGCT);
+ miClearDrawable((DrawablePtr)pPixmap, pGCT);
+ ppt = pptFirst = malloc(h * sizeof(DDXPointRec));
+ pwidth = pwidthFirst = malloc(h * sizeof(int));
+ if(!pptFirst || !pwidthFirst)
+ {
+ if (pwidthFirst) free(pwidthFirst);
+ if (pptFirst) free(pptFirst);
+ FreeScratchGC(pGCT);
+ return;
+ }
+
+ /* we need a temporary region because ChangeClip must be assumed
+ to destroy what it's sent. note that this means we don't
+ have to free prgnSrcClip ourselves.
+ */
+ prgnSrcClip = REGION_CREATE(pGCT->pScreen, NULL, 0);
+ REGION_COPY(pGCT->pScreen, prgnSrcClip, prgnSrc);
+ REGION_TRANSLATE(pGCT->pScreen, prgnSrcClip, srcx, 0);
+ (*pGCT->funcs->ChangeClip)(pGCT, CT_REGION, prgnSrcClip, 0);
+ ValidateGC((DrawablePtr)pPixmap, pGCT);
+
+ /* Since we know pDraw is always a pixmap, we never need to think
+ * about translation here */
+ for(i = 0; i < h; i++)
+ {
+ ppt->x = 0;
+ ppt++->y = i;
+ *pwidth++ = w + srcx;
+ }
+
+ (*pGCT->ops->SetSpans)((DrawablePtr)pPixmap, pGCT, (char *)pbits,
+ pptFirst, pwidthFirst, h, TRUE);
+ free(pwidthFirst);
+ free(pptFirst);
+
+
+ /* Save current values from the client GC */
+ oldfill = pGC->fillStyle;
+ pStipple = pGC->stipple;
+ if(pStipple)
+ pStipple->refcnt++;
+ oldOrg = pGC->patOrg;
+
+ /* Set a new stipple in the drawable */
+ gcv[0].val = FillStippled;
+ gcv[1].ptr = pPixmap;
+ gcv[2].val = dstx - srcx;
+ gcv[3].val = dsty;
+
+ ChangeGC(NullClient, pGC,
+ GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
+ gcv);
+ ValidateGC(pDraw, pGC);
+
+ /* Fill the drawable with the stipple. This will draw the
+ * foreground color whereever 1 bits are set, leaving everything
+ * with 0 bits untouched. Note that the part outside the clip
+ * region is all 0s. */
+ rect.x = dstx;
+ rect.y = dsty;
+ rect.width = w;
+ rect.height = h;
+ (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
+
+ /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only
+ * within the clipping region, the part outside is still all 0s */
+ gcv[0].val = GXinvert;
+ ChangeGC(NullClient, pGCT, GCFunction, gcv);
+ ValidateGC((DrawablePtr)pPixmap, pGCT);
+ (*pGCT->ops->CopyArea)((DrawablePtr)pPixmap, (DrawablePtr)pPixmap,
+ pGCT, 0, 0, w + srcx, h, 0, 0);
+
+ /* Swap foreground and background colors on the GC for the drawable.
+ * Now when we fill the drawable, we will fill in the "Background"
+ * values */
+ oldfg = pGC->fgPixel;
+ gcv[0].val = pGC->bgPixel;
+ gcv[1].val = oldfg;
+ gcv[2].ptr = pPixmap;
+ ChangeGC(NullClient, pGC, GCForeground | GCBackground | GCStipple, gcv);
+ ValidateGC(pDraw, pGC);
+ /* PolyFillRect might have bashed the rectangle */
+ rect.x = dstx;
+ rect.y = dsty;
+ rect.width = w;
+ rect.height = h;
+ (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
+
+ /* Now put things back */
+ if(pStipple)
+ pStipple->refcnt--;
+ gcv[0].val = oldfg;
+ gcv[1].val = pGC->fgPixel;
+ gcv[2].val = oldfill;
+ gcv[3].ptr = pStipple;
+ gcv[4].val = oldOrg.x;
+ gcv[5].val = oldOrg.y;
+ ChangeGC(NullClient, pGC,
+ GCForeground | GCBackground | GCFillStyle | GCStipple |
+ GCTileStipXOrigin | GCTileStipYOrigin, gcv);
+
+ ValidateGC(pDraw, pGC);
+ /* put what we hope is a smaller clip region back in the scratch gc */
+ (*pGCT->funcs->ChangeClip)(pGCT, CT_NONE, NULL, 0);
+ FreeScratchGC(pGCT);
+ (*pDraw->pScreen->DestroyPixmap)(pPixmap);
+
+}
+
+/* MICOPYPLANE -- public entry for the CopyPlane request.
+ * strategy:
+ * First build up a bitmap out of the bits requested
+ * build a source clip
+ * Use the bitmap we've built up as a Stipple for the destination
+ */
+RegionPtr
+miCopyPlane( DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ int srcx,
+ int srcy,
+ int width,
+ int height,
+ int dstx,
+ int dsty,
+ unsigned long bitPlane)
+{
+ MiBits *ptile;
+ BoxRec box;
+ RegionPtr prgnSrc, prgnExposed;
+
+ /* incorporate the source clip */
+
+ box.x1 = srcx + pSrcDrawable->x;
+ box.y1 = srcy + pSrcDrawable->y;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+ /* clip to visible drawable */
+ if (box.x1 < pSrcDrawable->x)
+ box.x1 = pSrcDrawable->x;
+ if (box.y1 < pSrcDrawable->y)
+ box.y1 = pSrcDrawable->y;
+ if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
+ box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
+ if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
+ box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
+ if (box.x1 > box.x2)
+ box.x2 = box.x1;
+ if (box.y1 > box.y2)
+ box.y2 = box.y1;
+ prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1);
+
+ if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
+ /* clip to visible drawable */
+
+ if (pGC->subWindowMode == IncludeInferiors)
+ {
+ RegionPtr clipList = NotClippedByChildren ((WindowPtr) pSrcDrawable);
+ REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc, clipList);
+ REGION_DESTROY(pGC->pScreen, clipList);
+ } else
+ REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc,
+ &((WindowPtr)pSrcDrawable)->clipList);
+ }
+
+ box = *REGION_EXTENTS(pGC->pScreen, prgnSrc);
+ REGION_TRANSLATE(pGC->pScreen, prgnSrc, -box.x1, -box.y1);
+
+ if ((box.x2 > box.x1) && (box.y2 > box.y1))
+ {
+ /* minimize the size of the data extracted */
+ /* note that we convert the plane mask bitPlane into a plane number */
+ box.x1 -= pSrcDrawable->x;
+ box.x2 -= pSrcDrawable->x;
+ box.y1 -= pSrcDrawable->y;
+ box.y2 -= pSrcDrawable->y;
+ ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1,
+ box.x1, box.y1,
+ box.x2 - box.x1, box.y2 - box.y1,
+ (MiBits *) NULL);
+ if (ptile)
+ {
+ miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0,
+ box.x2 - box.x1, box.y2 - box.y1,
+ dstx + box.x1 - srcx, dsty + box.y1 - srcy);
+ free(ptile);
+ }
+ }
+ prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
+ width, height, dstx, dsty, bitPlane);
+ REGION_DESTROY(pGC->pScreen, prgnSrc);
+ return prgnExposed;
+}
+
+/* MIGETIMAGE -- public entry for the GetImage Request
+ * We're getting the image into a memory buffer. While we have to use GetSpans
+ * to read a line from the device (since we don't know what that looks like),
+ * we can just write into the destination buffer
+ *
+ * two different strategies are used, depending on whether we're getting the
+ * image in Z format or XY format
+ * Z format:
+ * Line at a time, GetSpans a line into the destination buffer, then if the
+ * planemask is not all ones, we do a SetSpans into a temporary buffer (to get
+ * bits turned off) and then another GetSpans to get stuff back (because
+ * pixmaps are opaque, and we are passed in the memory to write into). This is
+ * pretty ugly and slow but works. Life is hard.
+ * XY format:
+ * get the single plane specified in planemask
+ */
+void
+miGetImage( DrawablePtr pDraw, int sx, int sy, int w, int h,
+ unsigned int format, unsigned long planeMask, char *pDst)
+{
+ unsigned char depth;
+ int i, linelength, width, srcx, srcy;
+ DDXPointRec pt = {0, 0};
+ PixmapPtr pPixmap = NULL;
+ GCPtr pGC = NULL;
+
+ depth = pDraw->depth;
+ if(format == ZPixmap)
+ {
+ if ( (((1<<depth)-1)&planeMask) != (1<<depth)-1 )
+ {
+ ChangeGCVal gcv;
+ xPoint pt;
+
+ pGC = GetScratchGC(depth, pDraw->pScreen);
+ if (!pGC)
+ return;
+ pPixmap = (*pDraw->pScreen->CreatePixmap)
+ (pDraw->pScreen, w, 1, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap)
+ {
+ FreeScratchGC(pGC);
+ return;
+ }
+ /*
+ * Clear the pixmap before doing anything else
+ */
+ ValidateGC((DrawablePtr)pPixmap, pGC);
+ pt.x = pt.y = 0;
+ width = w;
+ (*pGC->ops->FillSpans)((DrawablePtr)pPixmap, pGC, 1, &pt, &width,
+ TRUE);
+
+ /* alu is already GXCopy */
+ gcv.val = (XID)planeMask;
+ ChangeGC(NullClient, pGC, GCPlaneMask, &gcv);
+ ValidateGC((DrawablePtr)pPixmap, pGC);
+ }
+
+ linelength = PixmapBytePad(w, depth);
+ srcx = sx + pDraw->x;
+ srcy = sy + pDraw->y;
+ for(i = 0; i < h; i++)
+ {
+ pt.x = srcx;
+ pt.y = srcy + i;
+ width = w;
+ (*pDraw->pScreen->GetSpans)(pDraw, w, &pt, &width, 1, pDst);
+ if (pPixmap)
+ {
+ pt.x = 0;
+ pt.y = 0;
+ width = w;
+ (*pGC->ops->SetSpans)((DrawablePtr)pPixmap, pGC, pDst,
+ &pt, &width, 1, TRUE);
+ (*pDraw->pScreen->GetSpans)((DrawablePtr)pPixmap, w, &pt,
+ &width, 1, pDst);
+ }
+ pDst += linelength;
+ }
+ if (pPixmap)
+ {
+ (*pGC->pScreen->DestroyPixmap)(pPixmap);
+ FreeScratchGC(pGC);
+ }
+ }
+ else
+ {
+ (void) miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h,
+ (MiBits *)pDst);
+ }
+}
+
+/* MIPUTIMAGE -- public entry for the PutImage request
+ * Here we benefit from knowing the format of the bits pointed to by pImage,
+ * even if we don't know how pDraw represents them.
+ * Three different strategies are used depending on the format
+ * XYBitmap Format:
+ * we just use the Opaque Stipple helper function to cover the destination
+ * Note that this covers all the planes of the drawable with the
+ * foreground color (masked with the GC planemask) where there are 1 bits
+ * and the background color (masked with the GC planemask) where there are
+ * 0 bits
+ * XYPixmap format:
+ * what we're called with is a series of XYBitmaps, but we only want
+ * each XYPixmap to update 1 plane, instead of updating all of them.
+ * we set the foreground color to be all 1s and the background to all 0s
+ * then for each plane, we set the plane mask to only effect that one
+ * plane and recursive call ourself with the format set to XYBitmap
+ * (This clever idea courtesy of RGD.)
+ * ZPixmap format:
+ * This part is simple, just call SetSpans
+ */
+void
+miPutImage( DrawablePtr pDraw, GCPtr pGC, int depth,
+ int x, int y, int w, int h,
+ int leftPad, int format, char *pImage)
+{
+ DDXPointPtr pptFirst, ppt;
+ int *pwidthFirst, *pwidth;
+ RegionPtr prgnSrc;
+ BoxRec box;
+ unsigned long oldFg, oldBg;
+ ChangeGCVal gcv[3];
+ unsigned long oldPlanemask;
+ unsigned long i;
+ long bytesPer;
+
+ if (!w || !h)
+ return;
+ switch(format)
+ {
+ case XYBitmap:
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = w;
+ box.y2 = h;
+ prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1);
+
+ miOpqStipDrawable(pDraw, pGC, prgnSrc, (MiBits *) pImage,
+ leftPad, w, h, x, y);
+ REGION_DESTROY(pGC->pScreen, prgnSrc);
+ break;
+
+ case XYPixmap:
+ depth = pGC->depth;
+ oldPlanemask = pGC->planemask;
+ oldFg = pGC->fgPixel;
+ oldBg = pGC->bgPixel;
+ gcv[0].val = (XID)~0;
+ gcv[1].val = (XID)0;
+ ChangeGC(NullClient, pGC, GCForeground | GCBackground, gcv);
+ bytesPer = (long)h * BitmapBytePad(w + leftPad);
+
+ for (i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer)
+ {
+ if (i & oldPlanemask)
+ {
+ gcv[0].val = (XID)i;
+ ChangeGC(NullClient, pGC, GCPlaneMask, gcv);
+ ValidateGC(pDraw, pGC);
+ (*pGC->ops->PutImage)(pDraw, pGC, 1, x, y, w, h, leftPad,
+ XYBitmap, (char *)pImage);
+ }
+ }
+ gcv[0].val = (XID)oldPlanemask;
+ gcv[1].val = (XID)oldFg;
+ gcv[2].val = (XID)oldBg;
+ ChangeGC(NullClient, pGC, GCPlaneMask | GCForeground | GCBackground, gcv);
+ ValidateGC(pDraw, pGC);
+ break;
+
+ case ZPixmap:
+ ppt = pptFirst = malloc(h * sizeof(DDXPointRec));
+ pwidth = pwidthFirst = malloc(h * sizeof(int));
+ if(!pptFirst || !pwidthFirst)
+ {
+ if (pwidthFirst)
+ free(pwidthFirst);
+ if (pptFirst)
+ free(pptFirst);
+ return;
+ }
+ if (pGC->miTranslate)
+ {
+ x += pDraw->x;
+ y += pDraw->y;
+ }
+
+ for(i = 0; i < h; i++)
+ {
+ ppt->x = x;
+ ppt->y = y + i;
+ ppt++;
+ *pwidth++ = w;
+ }
+
+ (*pGC->ops->SetSpans)(pDraw, pGC, (char *)pImage, pptFirst,
+ pwidthFirst, h, TRUE);
+ free(pwidthFirst);
+ free(pptFirst);
+ break;
+ }
+}
diff --git a/xorg-server/mi/micmap.c b/xorg-server/mi/micmap.c index cc829fc10..ed8641c9e 100644 --- a/xorg-server/mi/micmap.c +++ b/xorg-server/mi/micmap.c @@ -1,666 +1,666 @@ -/* - * Copyright © 1987 Sun Microsystems, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -/* - * This is based on cfbcmap.c. The functions here are useful independently - * of cfb, which is the reason for including them here. How "mi" these - * are may be debatable. - */ - - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "scrnintstr.h" -#include "colormapst.h" -#include "resource.h" -#include "globals.h" -#include "micmap.h" - -static int micmapScrPrivateKeyIndex; -DevPrivateKey micmapScrPrivateKey = &micmapScrPrivateKeyIndex; - -int -miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) -{ - if (GetInstalledmiColormap(pScreen)) { - *pmaps = GetInstalledmiColormap(pScreen)->mid; - return (1); - } - return 0; -} - -void -miInstallColormap(ColormapPtr pmap) -{ - ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen); - - if(pmap != oldpmap) - { - /* Uninstall pInstalledMap. No hardware changes required, just - * notify all interested parties. */ - if(oldpmap != (ColormapPtr)None) - WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); - /* Install pmap */ - SetInstalledmiColormap(pmap->pScreen, pmap); - WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); - - } -} - -void -miUninstallColormap(ColormapPtr pmap) -{ - ColormapPtr curpmap = GetInstalledmiColormap(pmap->pScreen); - - if(pmap == curpmap) - { - if (pmap->mid != pmap->pScreen->defColormap) - { - dixLookupResourceByType((pointer *)&curpmap, - pmap->pScreen->defColormap, - RT_COLORMAP, serverClient, - DixUseAccess); - (*pmap->pScreen->InstallColormap)(curpmap); - } - } -} - -void -miResolveColor(unsigned short *pred, unsigned short *pgreen, - unsigned short *pblue, VisualPtr pVisual) -{ - int shift = 16 - pVisual->bitsPerRGBValue; - unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1; - - if ((pVisual->class | DynamicClass) == GrayScale) - { - /* rescale to gray then rgb bits */ - *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100; - *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim; - } - else - { - /* rescale to rgb bits */ - *pred = ((*pred >> shift) * 65535) / lim; - *pgreen = ((*pgreen >> shift) * 65535) / lim; - *pblue = ((*pblue >> shift) * 65535) / lim; - } -} - -Bool -miInitializeColormap(ColormapPtr pmap) -{ - unsigned i; - VisualPtr pVisual; - unsigned lim, maxent, shift; - - pVisual = pmap->pVisual; - lim = (1 << pVisual->bitsPerRGBValue) - 1; - shift = 16 - pVisual->bitsPerRGBValue; - maxent = pVisual->ColormapEntries - 1; - if (pVisual->class == TrueColor) - { - unsigned limr, limg, limb; - - limr = pVisual->redMask >> pVisual->offsetRed; - limg = pVisual->greenMask >> pVisual->offsetGreen; - limb = pVisual->blueMask >> pVisual->offsetBlue; - for(i = 0; i <= maxent; i++) - { - /* rescale to [0..65535] then rgb bits */ - pmap->red[i].co.local.red = - ((((i * 65535) / limr) >> shift) * 65535) / lim; - pmap->green[i].co.local.green = - ((((i * 65535) / limg) >> shift) * 65535) / lim; - pmap->blue[i].co.local.blue = - ((((i * 65535) / limb) >> shift) * 65535) / lim; - } - } - else if (pVisual->class == StaticColor) - { - unsigned limr, limg, limb; - - limr = pVisual->redMask >> pVisual->offsetRed; - limg = pVisual->greenMask >> pVisual->offsetGreen; - limb = pVisual->blueMask >> pVisual->offsetBlue; - for(i = 0; i <= maxent; i++) - { - /* rescale to [0..65535] then rgb bits */ - pmap->red[i].co.local.red = - ((((((i & pVisual->redMask) >> pVisual->offsetRed) - * 65535) / limr) >> shift) * 65535) / lim; - pmap->red[i].co.local.green = - ((((((i & pVisual->greenMask) >> pVisual->offsetGreen) - * 65535) / limg) >> shift) * 65535) / lim; - pmap->red[i].co.local.blue = - ((((((i & pVisual->blueMask) >> pVisual->offsetBlue) - * 65535) / limb) >> shift) * 65535) / lim; - } - } - else if (pVisual->class == StaticGray) - { - for(i = 0; i <= maxent; i++) - { - /* rescale to [0..65535] then rgb bits */ - pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift) - * 65535) / lim; - pmap->red[i].co.local.green = pmap->red[i].co.local.red; - pmap->red[i].co.local.blue = pmap->red[i].co.local.red; - } - } - return TRUE; -} - -/* When simulating DirectColor on PseudoColor hardware, multiple - entries of the colormap must be updated - */ - -#define AddElement(mask) { \ - pixel = red | green | blue; \ - for (i = 0; i < nresult; i++) \ - if (outdefs[i].pixel == pixel) \ - break; \ - if (i == nresult) \ - { \ - nresult++; \ - outdefs[i].pixel = pixel; \ - outdefs[i].flags = 0; \ - } \ - outdefs[i].flags |= (mask); \ - outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \ - outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \ - outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \ -} - -int -miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs, - xColorItem *outdefs) -{ - int red, green, blue; - int maxred, maxgreen, maxblue; - int stepred, stepgreen, stepblue; - VisualPtr pVisual; - int pixel; - int nresult; - int i; - - pVisual = pmap->pVisual; - - stepred = 1 << pVisual->offsetRed; - stepgreen = 1 << pVisual->offsetGreen; - stepblue = 1 << pVisual->offsetBlue; - maxred = pVisual->redMask; - maxgreen = pVisual->greenMask; - maxblue = pVisual->blueMask; - nresult = 0; - for (;ndef--; indefs++) - { - if (indefs->flags & DoRed) - { - red = indefs->pixel & pVisual->redMask; - for (green = 0; green <= maxgreen; green += stepgreen) - { - for (blue = 0; blue <= maxblue; blue += stepblue) - { - AddElement (DoRed) - } - } - } - if (indefs->flags & DoGreen) - { - green = indefs->pixel & pVisual->greenMask; - for (red = 0; red <= maxred; red += stepred) - { - for (blue = 0; blue <= maxblue; blue += stepblue) - { - AddElement (DoGreen) - } - } - } - if (indefs->flags & DoBlue) - { - blue = indefs->pixel & pVisual->blueMask; - for (red = 0; red <= maxred; red += stepred) - { - for (green = 0; green <= maxgreen; green += stepgreen) - { - AddElement (DoBlue) - } - } - } - } - return nresult; -} - -Bool -miCreateDefColormap(ScreenPtr pScreen) -{ -/* - * In the following sources PC X server vendors may want to delete - * "_not_tog" from "#ifdef WIN32_not_tog" - */ -#ifdef WIN32_not_tog - /* - * these are the MS-Windows desktop colors, adjusted for X's 16-bit - * color specifications. - */ - static xColorItem citems[] = { - { 0, 0, 0, 0, 0, 0 }, - { 1, 0x8000, 0, 0, 0, 0 }, - { 2, 0, 0x8000, 0, 0, 0 }, - { 3, 0x8000, 0x8000, 0, 0, 0 }, - { 4, 0, 0, 0x8000, 0, 0 }, - { 5, 0x8000, 0, 0x8000, 0, 0 }, - { 6, 0, 0x8000, 0x8000, 0, 0 }, - { 7, 0xc000, 0xc000, 0xc000, 0, 0 }, - { 8, 0xc000, 0xdc00, 0xc000, 0, 0 }, - { 9, 0xa600, 0xca00, 0xf000, 0, 0 }, - { 246, 0xff00, 0xfb00, 0xf000, 0, 0 }, - { 247, 0xa000, 0xa000, 0xa400, 0, 0 }, - { 248, 0x8000, 0x8000, 0x8000, 0, 0 }, - { 249, 0xff00, 0, 0, 0, 0 }, - { 250, 0, 0xff00, 0, 0, 0 }, - { 251, 0xff00, 0xff00, 0, 0, 0 }, - { 252, 0, 0, 0xff00, 0, 0 }, - { 253, 0xff00, 0, 0xff00, 0, 0 }, - { 254, 0, 0xff00, 0xff00, 0, 0 }, - { 255, 0xff00, 0xff00, 0xff00, 0, 0 } - }; -#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0] - int i; -#else - unsigned short zero = 0, ones = 0xFFFF; -#endif - Pixel wp, bp; - VisualPtr pVisual; - ColormapPtr cmap; - int alloctype; - - for (pVisual = pScreen->visuals; - pVisual->vid != pScreen->rootVisual; - pVisual++) - ; - - if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass)) - alloctype = AllocNone; - else - alloctype = AllocAll; - - if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap, - alloctype, 0) != Success) - return FALSE; - - if (pScreen->rootDepth > 1) { - wp = pScreen->whitePixel; - bp = pScreen->blackPixel; -#ifdef WIN32_not_tog - for (i = 0; i < NUM_DESKTOP_COLORS; i++) { - if (AllocColor (cmap, - &citems[i].red, &citems[i].green, &citems[i].blue, - &citems[i].pixel, 0) != Success) - return FALSE; - } -#else - if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) != - Success) || - (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != - Success)) - return FALSE; - pScreen->whitePixel = wp; - pScreen->blackPixel = bp; -#endif - } - - (*pScreen->InstallColormap)(cmap); - return TRUE; -} - -/* - * Default true color bitmasks, should be overridden by - * driver - */ - -#define _RZ(d) ((d + 2) / 3) -#define _RS(d) 0 -#define _RM(d) ((1 << _RZ(d)) - 1) -#define _GZ(d) ((d - _RZ(d) + 1) / 2) -#define _GS(d) _RZ(d) -#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d)) -#define _BZ(d) (d - _RZ(d) - _GZ(d)) -#define _BS(d) (_RZ(d) + _GZ(d)) -#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d)) -#define _CE(d) (1 << _RZ(d)) - -typedef struct _miVisuals { - struct _miVisuals *next; - int depth; - int bitsPerRGB; - int visuals; - int count; - int preferredCVC; - Pixel redMask, greenMask, blueMask; -} miVisualsRec, *miVisualsPtr; - -static int miVisualPriority[] = { - PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray -}; - -#define NUM_PRIORITY 6 - -static miVisualsPtr miVisuals; - -void -miClearVisualTypes(void) -{ - miVisualsPtr v; - - while ((v = miVisuals)) { - miVisuals = v->next; - xfree(v); - } -} - - -Bool -miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB, - int preferredCVC, - Pixel redMask, Pixel greenMask, Pixel blueMask) -{ - miVisualsPtr new, *prev, v; - int count; - - new = xalloc (sizeof *new); - if (!new) - return FALSE; - if (!redMask || !greenMask || !blueMask) - { - redMask = _RM(depth); - greenMask = _GM(depth); - blueMask = _BM(depth); - } - new->next = 0; - new->depth = depth; - new->visuals = visuals; - new->bitsPerRGB = bitsPerRGB; - new->preferredCVC = preferredCVC; - new->redMask = redMask; - new->greenMask = greenMask; - new->blueMask = blueMask; - count = (visuals >> 1) & 033333333333; - count = visuals - count - ((count >> 1) & 033333333333); - count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */ - new->count = count; - for (prev = &miVisuals; (v = *prev); prev = &v->next); - *prev = new; - return TRUE; -} - -Bool -miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC) -{ - return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB, - preferredCVC, 0, 0, 0); -} - -int -miGetDefaultVisualMask(int depth) -{ - if (depth > MAX_PSEUDO_DEPTH) - return LARGE_VISUALS; - else if (depth >= MIN_TRUE_DEPTH) - return ALL_VISUALS; - else if (depth == 1) - return StaticGrayMask; - else - return SMALL_VISUALS; -} - -static Bool -miVisualTypesSet (int depth) -{ - miVisualsPtr visuals; - - for (visuals = miVisuals; visuals; visuals = visuals->next) - if (visuals->depth == depth) - return TRUE; - return FALSE; -} - -Bool -miSetPixmapDepths (void) -{ - int d, f; - - /* Add any unlisted depths from the pixmap formats */ - for (f = 0; f < screenInfo.numPixmapFormats; f++) - { - d = screenInfo.formats[f].depth; - if (!miVisualTypesSet (d)) - { - if (!miSetVisualTypes (d, 0, 0, -1)) - return FALSE; - } - } - return TRUE; -} - -/* - * Distance to least significant one bit - */ -static int -maskShift (Pixel p) -{ - int s; - - if (!p) return 0; - s = 0; - while (!(p & 1)) - { - s++; - p >>= 1; - } - return s; -} - -/* - * Given a list of formats for a screen, create a list - * of visuals and depths for the screen which corespond to - * the set which can be used with this version of cfb. - */ - -Bool -miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp, - int *ndepthp, int *rootDepthp, VisualID *defaultVisp, - unsigned long sizes, int bitsPerRGB, int preferredVis) - -{ - int i, j = 0, k; - VisualPtr visual; - DepthPtr depth; - VisualID *vid; - int d, b; - int f; - int ndepth, nvisual; - int nvtype; - int vtype; - miVisualsPtr visuals, nextVisuals; - int *preferredCVCs, *prefp; - int first_depth; - - /* none specified, we'll guess from pixmap formats */ - if (!miVisuals) - { - for (f = 0; f < screenInfo.numPixmapFormats; f++) - { - d = screenInfo.formats[f].depth; - b = screenInfo.formats[f].bitsPerPixel; - if (sizes & (1 << (b - 1))) - vtype = miGetDefaultVisualMask(d); - else - vtype = 0; - if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1)) - return FALSE; - } - } - nvisual = 0; - ndepth = 0; - for (visuals = miVisuals; visuals; visuals = nextVisuals) - { - nextVisuals = visuals->next; - ndepth++; - nvisual += visuals->count; - } - depth = xalloc (ndepth * sizeof (DepthRec)); - visual = xalloc (nvisual * sizeof (VisualRec)); - preferredCVCs = xalloc(ndepth * sizeof(int)); - if (!depth || !visual || !preferredCVCs) - { - xfree (depth); - xfree (visual); - xfree (preferredCVCs); - return FALSE; - } - *depthp = depth; - *visualp = visual; - *ndepthp = ndepth; - *nvisualp = nvisual; - prefp = preferredCVCs; - for (visuals = miVisuals; visuals; visuals = nextVisuals) - { - nextVisuals = visuals->next; - d = visuals->depth; - vtype = visuals->visuals; - nvtype = visuals->count; - *prefp = visuals->preferredCVC; - prefp++; - vid = NULL; - if (nvtype) - { - vid = xalloc (nvtype * sizeof (VisualID)); - if (!vid) { - xfree(preferredCVCs); - return FALSE; - } - } - depth->depth = d; - depth->numVids = nvtype; - depth->vids = vid; - depth++; - for (i = 0; i < NUM_PRIORITY; i++) { - if (! (vtype & (1 << miVisualPriority[i]))) - continue; - visual->class = miVisualPriority[i]; - visual->bitsPerRGBValue = visuals->bitsPerRGB; - visual->ColormapEntries = 1 << d; - visual->nplanes = d; - visual->vid = *vid = FakeClientID (0); - switch (visual->class) { - case PseudoColor: - case GrayScale: - case StaticGray: - visual->redMask = 0; - visual->greenMask = 0; - visual->blueMask = 0; - visual->offsetRed = 0; - visual->offsetGreen = 0; - visual->offsetBlue = 0; - break; - case DirectColor: - case TrueColor: - visual->ColormapEntries = _CE(d); - /* fall through */ - case StaticColor: - visual->redMask = visuals->redMask; - visual->greenMask = visuals->greenMask; - visual->blueMask = visuals->blueMask; - visual->offsetRed = maskShift (visuals->redMask); - visual->offsetGreen = maskShift (visuals->greenMask); - visual->offsetBlue = maskShift (visuals->blueMask); - } - vid++; - visual++; - } - xfree (visuals); - } - miVisuals = NULL; - visual = *visualp; - depth = *depthp; - - /* - * if we did not supplyied by a preferred visual class - * check if there is a preferred class in one of the depth - * structures - if there is, we want to start looking for the - * default visual/depth from that depth. - */ - first_depth = 0; - if (preferredVis < 0 && defaultColorVisualClass < 0 ) { - for (i = 0; i < ndepth; i++) { - if (preferredCVCs[i] >= 0) { - first_depth = i; - break; - } - } - } - - for (i = first_depth; i < ndepth; i++) - { - int prefColorVisualClass = -1; - - if (defaultColorVisualClass >= 0) - prefColorVisualClass = defaultColorVisualClass; - else if (preferredVis >= 0) - prefColorVisualClass = preferredVis; - else if (preferredCVCs[i] >= 0) - prefColorVisualClass = preferredCVCs[i]; - - if (*rootDepthp && *rootDepthp != depth[i].depth) - continue; - - for (j = 0; j < depth[i].numVids; j++) - { - for (k = 0; k < nvisual; k++) - if (visual[k].vid == depth[i].vids[j]) - break; - if (k == nvisual) - continue; - if (prefColorVisualClass < 0 || - visual[k].class == prefColorVisualClass) - break; - } - if (j != depth[i].numVids) - break; - } - if (i == ndepth) { - i = 0; - j = 0; - } - *rootDepthp = depth[i].depth; - *defaultVisp = depth[i].vids[j]; - xfree(preferredCVCs); - - return TRUE; -} +/*
+ * Copyright © 1987 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+/*
+ * This is based on cfbcmap.c. The functions here are useful independently
+ * of cfb, which is the reason for including them here. How "mi" these
+ * are may be debatable.
+ */
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "scrnintstr.h"
+#include "colormapst.h"
+#include "resource.h"
+#include "globals.h"
+#include "micmap.h"
+
+static int micmapScrPrivateKeyIndex;
+DevPrivateKey micmapScrPrivateKey = &micmapScrPrivateKeyIndex;
+
+int
+miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
+{
+ if (GetInstalledmiColormap(pScreen)) {
+ *pmaps = GetInstalledmiColormap(pScreen)->mid;
+ return (1);
+ }
+ return 0;
+}
+
+void
+miInstallColormap(ColormapPtr pmap)
+{
+ ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen);
+
+ if(pmap != oldpmap)
+ {
+ /* Uninstall pInstalledMap. No hardware changes required, just
+ * notify all interested parties. */
+ if(oldpmap != (ColormapPtr)None)
+ WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
+ /* Install pmap */
+ SetInstalledmiColormap(pmap->pScreen, pmap);
+ WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
+
+ }
+}
+
+void
+miUninstallColormap(ColormapPtr pmap)
+{
+ ColormapPtr curpmap = GetInstalledmiColormap(pmap->pScreen);
+
+ if(pmap == curpmap)
+ {
+ if (pmap->mid != pmap->pScreen->defColormap)
+ {
+ dixLookupResourceByType((pointer *)&curpmap,
+ pmap->pScreen->defColormap,
+ RT_COLORMAP, serverClient,
+ DixUseAccess);
+ (*pmap->pScreen->InstallColormap)(curpmap);
+ }
+ }
+}
+
+void
+miResolveColor(unsigned short *pred, unsigned short *pgreen,
+ unsigned short *pblue, VisualPtr pVisual)
+{
+ int shift = 16 - pVisual->bitsPerRGBValue;
+ unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1;
+
+ if ((pVisual->class | DynamicClass) == GrayScale)
+ {
+ /* rescale to gray then rgb bits */
+ *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100;
+ *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim;
+ }
+ else
+ {
+ /* rescale to rgb bits */
+ *pred = ((*pred >> shift) * 65535) / lim;
+ *pgreen = ((*pgreen >> shift) * 65535) / lim;
+ *pblue = ((*pblue >> shift) * 65535) / lim;
+ }
+}
+
+Bool
+miInitializeColormap(ColormapPtr pmap)
+{
+ unsigned i;
+ VisualPtr pVisual;
+ unsigned lim, maxent, shift;
+
+ pVisual = pmap->pVisual;
+ lim = (1 << pVisual->bitsPerRGBValue) - 1;
+ shift = 16 - pVisual->bitsPerRGBValue;
+ maxent = pVisual->ColormapEntries - 1;
+ if (pVisual->class == TrueColor)
+ {
+ unsigned limr, limg, limb;
+
+ limr = pVisual->redMask >> pVisual->offsetRed;
+ limg = pVisual->greenMask >> pVisual->offsetGreen;
+ limb = pVisual->blueMask >> pVisual->offsetBlue;
+ for(i = 0; i <= maxent; i++)
+ {
+ /* rescale to [0..65535] then rgb bits */
+ pmap->red[i].co.local.red =
+ ((((i * 65535) / limr) >> shift) * 65535) / lim;
+ pmap->green[i].co.local.green =
+ ((((i * 65535) / limg) >> shift) * 65535) / lim;
+ pmap->blue[i].co.local.blue =
+ ((((i * 65535) / limb) >> shift) * 65535) / lim;
+ }
+ }
+ else if (pVisual->class == StaticColor)
+ {
+ unsigned limr, limg, limb;
+
+ limr = pVisual->redMask >> pVisual->offsetRed;
+ limg = pVisual->greenMask >> pVisual->offsetGreen;
+ limb = pVisual->blueMask >> pVisual->offsetBlue;
+ for(i = 0; i <= maxent; i++)
+ {
+ /* rescale to [0..65535] then rgb bits */
+ pmap->red[i].co.local.red =
+ ((((((i & pVisual->redMask) >> pVisual->offsetRed)
+ * 65535) / limr) >> shift) * 65535) / lim;
+ pmap->red[i].co.local.green =
+ ((((((i & pVisual->greenMask) >> pVisual->offsetGreen)
+ * 65535) / limg) >> shift) * 65535) / lim;
+ pmap->red[i].co.local.blue =
+ ((((((i & pVisual->blueMask) >> pVisual->offsetBlue)
+ * 65535) / limb) >> shift) * 65535) / lim;
+ }
+ }
+ else if (pVisual->class == StaticGray)
+ {
+ for(i = 0; i <= maxent; i++)
+ {
+ /* rescale to [0..65535] then rgb bits */
+ pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift)
+ * 65535) / lim;
+ pmap->red[i].co.local.green = pmap->red[i].co.local.red;
+ pmap->red[i].co.local.blue = pmap->red[i].co.local.red;
+ }
+ }
+ return TRUE;
+}
+
+/* When simulating DirectColor on PseudoColor hardware, multiple
+ entries of the colormap must be updated
+ */
+
+#define AddElement(mask) { \
+ pixel = red | green | blue; \
+ for (i = 0; i < nresult; i++) \
+ if (outdefs[i].pixel == pixel) \
+ break; \
+ if (i == nresult) \
+ { \
+ nresult++; \
+ outdefs[i].pixel = pixel; \
+ outdefs[i].flags = 0; \
+ } \
+ outdefs[i].flags |= (mask); \
+ outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \
+ outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \
+ outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \
+}
+
+int
+miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs,
+ xColorItem *outdefs)
+{
+ int red, green, blue;
+ int maxred, maxgreen, maxblue;
+ int stepred, stepgreen, stepblue;
+ VisualPtr pVisual;
+ int pixel;
+ int nresult;
+ int i;
+
+ pVisual = pmap->pVisual;
+
+ stepred = 1 << pVisual->offsetRed;
+ stepgreen = 1 << pVisual->offsetGreen;
+ stepblue = 1 << pVisual->offsetBlue;
+ maxred = pVisual->redMask;
+ maxgreen = pVisual->greenMask;
+ maxblue = pVisual->blueMask;
+ nresult = 0;
+ for (;ndef--; indefs++)
+ {
+ if (indefs->flags & DoRed)
+ {
+ red = indefs->pixel & pVisual->redMask;
+ for (green = 0; green <= maxgreen; green += stepgreen)
+ {
+ for (blue = 0; blue <= maxblue; blue += stepblue)
+ {
+ AddElement (DoRed)
+ }
+ }
+ }
+ if (indefs->flags & DoGreen)
+ {
+ green = indefs->pixel & pVisual->greenMask;
+ for (red = 0; red <= maxred; red += stepred)
+ {
+ for (blue = 0; blue <= maxblue; blue += stepblue)
+ {
+ AddElement (DoGreen)
+ }
+ }
+ }
+ if (indefs->flags & DoBlue)
+ {
+ blue = indefs->pixel & pVisual->blueMask;
+ for (red = 0; red <= maxred; red += stepred)
+ {
+ for (green = 0; green <= maxgreen; green += stepgreen)
+ {
+ AddElement (DoBlue)
+ }
+ }
+ }
+ }
+ return nresult;
+}
+
+Bool
+miCreateDefColormap(ScreenPtr pScreen)
+{
+/*
+ * In the following sources PC X server vendors may want to delete
+ * "_not_tog" from "#ifdef WIN32_not_tog"
+ */
+#ifdef WIN32_not_tog
+ /*
+ * these are the MS-Windows desktop colors, adjusted for X's 16-bit
+ * color specifications.
+ */
+ static xColorItem citems[] = {
+ { 0, 0, 0, 0, 0, 0 },
+ { 1, 0x8000, 0, 0, 0, 0 },
+ { 2, 0, 0x8000, 0, 0, 0 },
+ { 3, 0x8000, 0x8000, 0, 0, 0 },
+ { 4, 0, 0, 0x8000, 0, 0 },
+ { 5, 0x8000, 0, 0x8000, 0, 0 },
+ { 6, 0, 0x8000, 0x8000, 0, 0 },
+ { 7, 0xc000, 0xc000, 0xc000, 0, 0 },
+ { 8, 0xc000, 0xdc00, 0xc000, 0, 0 },
+ { 9, 0xa600, 0xca00, 0xf000, 0, 0 },
+ { 246, 0xff00, 0xfb00, 0xf000, 0, 0 },
+ { 247, 0xa000, 0xa000, 0xa400, 0, 0 },
+ { 248, 0x8000, 0x8000, 0x8000, 0, 0 },
+ { 249, 0xff00, 0, 0, 0, 0 },
+ { 250, 0, 0xff00, 0, 0, 0 },
+ { 251, 0xff00, 0xff00, 0, 0, 0 },
+ { 252, 0, 0, 0xff00, 0, 0 },
+ { 253, 0xff00, 0, 0xff00, 0, 0 },
+ { 254, 0, 0xff00, 0xff00, 0, 0 },
+ { 255, 0xff00, 0xff00, 0xff00, 0, 0 }
+ };
+#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0]
+ int i;
+#else
+ unsigned short zero = 0, ones = 0xFFFF;
+#endif
+ Pixel wp, bp;
+ VisualPtr pVisual;
+ ColormapPtr cmap;
+ int alloctype;
+
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != pScreen->rootVisual;
+ pVisual++)
+ ;
+
+ if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass))
+ alloctype = AllocNone;
+ else
+ alloctype = AllocAll;
+
+ if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
+ alloctype, 0) != Success)
+ return FALSE;
+
+ if (pScreen->rootDepth > 1) {
+ wp = pScreen->whitePixel;
+ bp = pScreen->blackPixel;
+#ifdef WIN32_not_tog
+ for (i = 0; i < NUM_DESKTOP_COLORS; i++) {
+ if (AllocColor (cmap,
+ &citems[i].red, &citems[i].green, &citems[i].blue,
+ &citems[i].pixel, 0) != Success)
+ return FALSE;
+ }
+#else
+ if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) !=
+ Success) ||
+ (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) !=
+ Success))
+ return FALSE;
+ pScreen->whitePixel = wp;
+ pScreen->blackPixel = bp;
+#endif
+ }
+
+ (*pScreen->InstallColormap)(cmap);
+ return TRUE;
+}
+
+/*
+ * Default true color bitmasks, should be overridden by
+ * driver
+ */
+
+#define _RZ(d) ((d + 2) / 3)
+#define _RS(d) 0
+#define _RM(d) ((1 << _RZ(d)) - 1)
+#define _GZ(d) ((d - _RZ(d) + 1) / 2)
+#define _GS(d) _RZ(d)
+#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d))
+#define _BZ(d) (d - _RZ(d) - _GZ(d))
+#define _BS(d) (_RZ(d) + _GZ(d))
+#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d))
+#define _CE(d) (1 << _RZ(d))
+
+typedef struct _miVisuals {
+ struct _miVisuals *next;
+ int depth;
+ int bitsPerRGB;
+ int visuals;
+ int count;
+ int preferredCVC;
+ Pixel redMask, greenMask, blueMask;
+} miVisualsRec, *miVisualsPtr;
+
+static int miVisualPriority[] = {
+ PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray
+};
+
+#define NUM_PRIORITY 6
+
+static miVisualsPtr miVisuals;
+
+void
+miClearVisualTypes(void)
+{
+ miVisualsPtr v;
+
+ while ((v = miVisuals)) {
+ miVisuals = v->next;
+ free(v);
+ }
+}
+
+
+Bool
+miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
+ int preferredCVC,
+ Pixel redMask, Pixel greenMask, Pixel blueMask)
+{
+ miVisualsPtr new, *prev, v;
+ int count;
+
+ new = malloc(sizeof *new);
+ if (!new)
+ return FALSE;
+ if (!redMask || !greenMask || !blueMask)
+ {
+ redMask = _RM(depth);
+ greenMask = _GM(depth);
+ blueMask = _BM(depth);
+ }
+ new->next = 0;
+ new->depth = depth;
+ new->visuals = visuals;
+ new->bitsPerRGB = bitsPerRGB;
+ new->preferredCVC = preferredCVC;
+ new->redMask = redMask;
+ new->greenMask = greenMask;
+ new->blueMask = blueMask;
+ count = (visuals >> 1) & 033333333333;
+ count = visuals - count - ((count >> 1) & 033333333333);
+ count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */
+ new->count = count;
+ for (prev = &miVisuals; (v = *prev); prev = &v->next);
+ *prev = new;
+ return TRUE;
+}
+
+Bool
+miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC)
+{
+ return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB,
+ preferredCVC, 0, 0, 0);
+}
+
+int
+miGetDefaultVisualMask(int depth)
+{
+ if (depth > MAX_PSEUDO_DEPTH)
+ return LARGE_VISUALS;
+ else if (depth >= MIN_TRUE_DEPTH)
+ return ALL_VISUALS;
+ else if (depth == 1)
+ return StaticGrayMask;
+ else
+ return SMALL_VISUALS;
+}
+
+static Bool
+miVisualTypesSet (int depth)
+{
+ miVisualsPtr visuals;
+
+ for (visuals = miVisuals; visuals; visuals = visuals->next)
+ if (visuals->depth == depth)
+ return TRUE;
+ return FALSE;
+}
+
+Bool
+miSetPixmapDepths (void)
+{
+ int d, f;
+
+ /* Add any unlisted depths from the pixmap formats */
+ for (f = 0; f < screenInfo.numPixmapFormats; f++)
+ {
+ d = screenInfo.formats[f].depth;
+ if (!miVisualTypesSet (d))
+ {
+ if (!miSetVisualTypes (d, 0, 0, -1))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Distance to least significant one bit
+ */
+static int
+maskShift (Pixel p)
+{
+ int s;
+
+ if (!p) return 0;
+ s = 0;
+ while (!(p & 1))
+ {
+ s++;
+ p >>= 1;
+ }
+ return s;
+}
+
+/*
+ * Given a list of formats for a screen, create a list
+ * of visuals and depths for the screen which corespond to
+ * the set which can be used with this version of cfb.
+ */
+
+Bool
+miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
+ int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
+ unsigned long sizes, int bitsPerRGB, int preferredVis)
+
+{
+ int i, j = 0, k;
+ VisualPtr visual;
+ DepthPtr depth;
+ VisualID *vid;
+ int d, b;
+ int f;
+ int ndepth, nvisual;
+ int nvtype;
+ int vtype;
+ miVisualsPtr visuals, nextVisuals;
+ int *preferredCVCs, *prefp;
+ int first_depth;
+
+ /* none specified, we'll guess from pixmap formats */
+ if (!miVisuals)
+ {
+ for (f = 0; f < screenInfo.numPixmapFormats; f++)
+ {
+ d = screenInfo.formats[f].depth;
+ b = screenInfo.formats[f].bitsPerPixel;
+ if (sizes & (1 << (b - 1)))
+ vtype = miGetDefaultVisualMask(d);
+ else
+ vtype = 0;
+ if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1))
+ return FALSE;
+ }
+ }
+ nvisual = 0;
+ ndepth = 0;
+ for (visuals = miVisuals; visuals; visuals = nextVisuals)
+ {
+ nextVisuals = visuals->next;
+ ndepth++;
+ nvisual += visuals->count;
+ }
+ depth = malloc(ndepth * sizeof (DepthRec));
+ visual = malloc(nvisual * sizeof (VisualRec));
+ preferredCVCs = malloc(ndepth * sizeof(int));
+ if (!depth || !visual || !preferredCVCs)
+ {
+ free(depth);
+ free(visual);
+ free(preferredCVCs);
+ return FALSE;
+ }
+ *depthp = depth;
+ *visualp = visual;
+ *ndepthp = ndepth;
+ *nvisualp = nvisual;
+ prefp = preferredCVCs;
+ for (visuals = miVisuals; visuals; visuals = nextVisuals)
+ {
+ nextVisuals = visuals->next;
+ d = visuals->depth;
+ vtype = visuals->visuals;
+ nvtype = visuals->count;
+ *prefp = visuals->preferredCVC;
+ prefp++;
+ vid = NULL;
+ if (nvtype)
+ {
+ vid = malloc(nvtype * sizeof (VisualID));
+ if (!vid) {
+ free(preferredCVCs);
+ return FALSE;
+ }
+ }
+ depth->depth = d;
+ depth->numVids = nvtype;
+ depth->vids = vid;
+ depth++;
+ for (i = 0; i < NUM_PRIORITY; i++) {
+ if (! (vtype & (1 << miVisualPriority[i])))
+ continue;
+ visual->class = miVisualPriority[i];
+ visual->bitsPerRGBValue = visuals->bitsPerRGB;
+ visual->ColormapEntries = 1 << d;
+ visual->nplanes = d;
+ visual->vid = *vid = FakeClientID (0);
+ switch (visual->class) {
+ case PseudoColor:
+ case GrayScale:
+ case StaticGray:
+ visual->redMask = 0;
+ visual->greenMask = 0;
+ visual->blueMask = 0;
+ visual->offsetRed = 0;
+ visual->offsetGreen = 0;
+ visual->offsetBlue = 0;
+ break;
+ case DirectColor:
+ case TrueColor:
+ visual->ColormapEntries = _CE(d);
+ /* fall through */
+ case StaticColor:
+ visual->redMask = visuals->redMask;
+ visual->greenMask = visuals->greenMask;
+ visual->blueMask = visuals->blueMask;
+ visual->offsetRed = maskShift (visuals->redMask);
+ visual->offsetGreen = maskShift (visuals->greenMask);
+ visual->offsetBlue = maskShift (visuals->blueMask);
+ }
+ vid++;
+ visual++;
+ }
+ free(visuals);
+ }
+ miVisuals = NULL;
+ visual = *visualp;
+ depth = *depthp;
+
+ /*
+ * if we did not supplyied by a preferred visual class
+ * check if there is a preferred class in one of the depth
+ * structures - if there is, we want to start looking for the
+ * default visual/depth from that depth.
+ */
+ first_depth = 0;
+ if (preferredVis < 0 && defaultColorVisualClass < 0 ) {
+ for (i = 0; i < ndepth; i++) {
+ if (preferredCVCs[i] >= 0) {
+ first_depth = i;
+ break;
+ }
+ }
+ }
+
+ for (i = first_depth; i < ndepth; i++)
+ {
+ int prefColorVisualClass = -1;
+
+ if (defaultColorVisualClass >= 0)
+ prefColorVisualClass = defaultColorVisualClass;
+ else if (preferredVis >= 0)
+ prefColorVisualClass = preferredVis;
+ else if (preferredCVCs[i] >= 0)
+ prefColorVisualClass = preferredCVCs[i];
+
+ if (*rootDepthp && *rootDepthp != depth[i].depth)
+ continue;
+
+ for (j = 0; j < depth[i].numVids; j++)
+ {
+ for (k = 0; k < nvisual; k++)
+ if (visual[k].vid == depth[i].vids[j])
+ break;
+ if (k == nvisual)
+ continue;
+ if (prefColorVisualClass < 0 ||
+ visual[k].class == prefColorVisualClass)
+ break;
+ }
+ if (j != depth[i].numVids)
+ break;
+ }
+ if (i == ndepth) {
+ i = 0;
+ j = 0;
+ }
+ *rootDepthp = depth[i].depth;
+ *defaultVisp = depth[i].vids[j];
+ free(preferredCVCs);
+
+ return TRUE;
+}
diff --git a/xorg-server/mi/micopy.c b/xorg-server/mi/micopy.c index 3719f4646..9d5c5ce5e 100644 --- a/xorg-server/mi/micopy.c +++ b/xorg-server/mi/micopy.c @@ -1,354 +1,354 @@ -/* - * Copyright © 1998 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 "mi.h" -#include "scrnintstr.h" -#include "gcstruct.h" -#include "pixmap.h" -#include "pixmapstr.h" -#include "windowstr.h" - -void -miCopyRegion (DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GCPtr pGC, - RegionPtr pDstRegion, - int dx, - int dy, - miCopyProc copyProc, - Pixel bitPlane, - void *closure) -{ - int careful; - Bool reverse; - Bool upsidedown; - BoxPtr pbox; - int nbox; - BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp; - - pbox = REGION_RECTS(pDstRegion); - nbox = REGION_NUM_RECTS(pDstRegion); - - /* XXX we have to err on the side of safety when both are windows, - * because we don't know if IncludeInferiors is being used. - */ - careful = ((pSrcDrawable == pDstDrawable) || - ((pSrcDrawable->type == DRAWABLE_WINDOW) && - (pDstDrawable->type == DRAWABLE_WINDOW))); - - pboxNew1 = NULL; - pboxNew2 = NULL; - if (careful && dy < 0) - { - upsidedown = TRUE; - - if (nbox > 1) - { - /* keep ordering in each band, reverse order of bands */ - pboxNew1 = (BoxPtr)xalloc(sizeof(BoxRec) * nbox); - if(!pboxNew1) - return; - pboxBase = pboxNext = pbox+nbox-1; - while (pboxBase >= pbox) - { - while ((pboxNext >= pbox) && - (pboxBase->y1 == pboxNext->y1)) - pboxNext--; - pboxTmp = pboxNext+1; - while (pboxTmp <= pboxBase) - { - *pboxNew1++ = *pboxTmp++; - } - pboxBase = pboxNext; - } - pboxNew1 -= nbox; - pbox = pboxNew1; - } - } - else - { - /* walk source top to bottom */ - upsidedown = FALSE; - } - - if (careful && dx < 0) - { - /* walk source right to left */ - if (dy <= 0) - reverse = TRUE; - else - reverse = FALSE; - - if (nbox > 1) - { - /* reverse order of rects in each band */ - pboxNew2 = (BoxPtr)xalloc(sizeof(BoxRec) * nbox); - if(!pboxNew2) - { - if (pboxNew1) - xfree(pboxNew1); - return; - } - pboxBase = pboxNext = pbox; - while (pboxBase < pbox+nbox) - { - while ((pboxNext < pbox+nbox) && - (pboxNext->y1 == pboxBase->y1)) - pboxNext++; - pboxTmp = pboxNext; - while (pboxTmp != pboxBase) - { - *pboxNew2++ = *--pboxTmp; - } - pboxBase = pboxNext; - } - pboxNew2 -= nbox; - pbox = pboxNew2; - } - } - else - { - /* walk source left to right */ - reverse = FALSE; - } - - (*copyProc) (pSrcDrawable, - pDstDrawable, - pGC, - pbox, - nbox, - dx, dy, - reverse, upsidedown, bitPlane, closure); - - if (pboxNew1) - xfree (pboxNew1); - if (pboxNew2) - xfree (pboxNew2); -} - -RegionPtr -miDoCopy (DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GCPtr pGC, - int xIn, - int yIn, - int widthSrc, - int heightSrc, - int xOut, - int yOut, - miCopyProc copyProc, - Pixel bitPlane, - void *closure) -{ - RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ - Bool freeSrcClip = FALSE; - RegionPtr prgnExposed = NULL; - RegionRec rgnDst; - int dx; - int dy; - int numRects; - int box_x1; - int box_y1; - int box_x2; - int box_y2; - Bool fastSrc = FALSE; /* for fast clipping with pixmap source */ - Bool fastDst = FALSE; /* for fast clipping with one rect dest */ - Bool fastExpose = FALSE; /* for fast exposures with pixmap source */ - - /* Short cut for unmapped windows */ - - if (pDstDrawable->type == DRAWABLE_WINDOW && - !((WindowPtr)pDstDrawable)->realized) - { - return NULL; - } - - if ((pSrcDrawable != pDstDrawable) && - pSrcDrawable->pScreen->SourceValidate) - { - (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc); - } - - /* Compute source clip region */ - if (pSrcDrawable->type == DRAWABLE_PIXMAP) - { - if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) - prgnSrcClip = miGetCompositeClip(pGC); - else - fastSrc = TRUE; - } - else - { - if (pGC->subWindowMode == IncludeInferiors) - { - /* - * XFree86 DDX empties the border clip when the - * VT is inactive, make sure the region isn't empty - */ - if (!((WindowPtr) pSrcDrawable)->parent && - REGION_NOTEMPTY (pSrcDrawable->pScreen, - &((WindowPtr) pSrcDrawable)->borderClip)) - { - /* - * special case bitblt from root window in - * IncludeInferiors mode; just like from a pixmap - */ - fastSrc = TRUE; - } - else if ((pSrcDrawable == pDstDrawable) && - (pGC->clientClipType == CT_NONE)) - { - prgnSrcClip = miGetCompositeClip(pGC); - } - else - { - prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); - freeSrcClip = TRUE; - } - } - else - { - prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; - } - } - - xIn += pSrcDrawable->x; - yIn += pSrcDrawable->y; - - xOut += pDstDrawable->x; - yOut += pDstDrawable->y; - - box_x1 = xIn; - box_y1 = yIn; - box_x2 = xIn + widthSrc; - box_y2 = yIn + heightSrc; - - dx = xIn - xOut; - dy = yIn - yOut; - - /* Don't create a source region if we are doing a fast clip */ - if (fastSrc) - { - RegionPtr cclip; - - fastExpose = TRUE; - /* - * clip the source; if regions extend beyond the source size, - * make sure exposure events get sent - */ - if (box_x1 < pSrcDrawable->x) - { - box_x1 = pSrcDrawable->x; - fastExpose = FALSE; - } - if (box_y1 < pSrcDrawable->y) - { - box_y1 = pSrcDrawable->y; - fastExpose = FALSE; - } - if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) - { - box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width; - fastExpose = FALSE; - } - if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) - { - box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height; - fastExpose = FALSE; - } - - /* Translate and clip the dst to the destination composite clip */ - box_x1 -= dx; - box_x2 -= dx; - box_y1 -= dy; - box_y2 -= dy; - - /* If the destination composite clip is one rectangle we can - do the clip directly. Otherwise we have to create a full - blown region and call intersect */ - - cclip = miGetCompositeClip(pGC); - if (REGION_NUM_RECTS(cclip) == 1) - { - BoxPtr pBox = REGION_RECTS(cclip); - - if (box_x1 < pBox->x1) box_x1 = pBox->x1; - if (box_x2 > pBox->x2) box_x2 = pBox->x2; - if (box_y1 < pBox->y1) box_y1 = pBox->y1; - if (box_y2 > pBox->y2) box_y2 = pBox->y2; - fastDst = TRUE; - } - } - - /* Check to see if the region is empty */ - if (box_x1 >= box_x2 || box_y1 >= box_y2) - { - REGION_NULL(pGC->pScreen, &rgnDst); - } - else - { - BoxRec box; - box.x1 = box_x1; - box.y1 = box_y1; - box.x2 = box_x2; - box.y2 = box_y2; - REGION_INIT(pGC->pScreen, &rgnDst, &box, 1); - } - - /* Clip against complex source if needed */ - if (!fastSrc) - { - REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); - REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); - } - - /* Clip against complex dest if needed */ - if (!fastDst) - { - REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, - miGetCompositeClip(pGC)); - } - - /* Do bit blitting */ - numRects = REGION_NUM_RECTS(&rgnDst); - if (numRects && widthSrc && heightSrc) - miCopyRegion (pSrcDrawable, pDstDrawable, pGC, - &rgnDst, dx, dy, copyProc, bitPlane, closure); - - /* Pixmap sources generate a NoExposed (we return NULL to do this) */ - if (!fastExpose && pGC->fExpose) - prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, - xIn - pSrcDrawable->x, - yIn - pSrcDrawable->y, - widthSrc, heightSrc, - xOut - pDstDrawable->x, - yOut - pDstDrawable->y, - (unsigned long) bitPlane); - REGION_UNINIT(pGC->pScreen, &rgnDst); - if (freeSrcClip) - REGION_DESTROY(pGC->pScreen, prgnSrcClip); - return prgnExposed; -} +/*
+ * Copyright © 1998 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 "mi.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmap.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+
+void
+miCopyRegion (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ RegionPtr pDstRegion,
+ int dx,
+ int dy,
+ miCopyProc copyProc,
+ Pixel bitPlane,
+ void *closure)
+{
+ int careful;
+ Bool reverse;
+ Bool upsidedown;
+ BoxPtr pbox;
+ int nbox;
+ BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp;
+
+ pbox = REGION_RECTS(pDstRegion);
+ nbox = REGION_NUM_RECTS(pDstRegion);
+
+ /* XXX we have to err on the side of safety when both are windows,
+ * because we don't know if IncludeInferiors is being used.
+ */
+ careful = ((pSrcDrawable == pDstDrawable) ||
+ ((pSrcDrawable->type == DRAWABLE_WINDOW) &&
+ (pDstDrawable->type == DRAWABLE_WINDOW)));
+
+ pboxNew1 = NULL;
+ pboxNew2 = NULL;
+ if (careful && dy < 0)
+ {
+ upsidedown = TRUE;
+
+ if (nbox > 1)
+ {
+ /* keep ordering in each band, reverse order of bands */
+ pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec) * nbox);
+ if(!pboxNew1)
+ return;
+ pboxBase = pboxNext = pbox+nbox-1;
+ while (pboxBase >= pbox)
+ {
+ while ((pboxNext >= pbox) &&
+ (pboxBase->y1 == pboxNext->y1))
+ pboxNext--;
+ pboxTmp = pboxNext+1;
+ while (pboxTmp <= pboxBase)
+ {
+ *pboxNew1++ = *pboxTmp++;
+ }
+ pboxBase = pboxNext;
+ }
+ pboxNew1 -= nbox;
+ pbox = pboxNew1;
+ }
+ }
+ else
+ {
+ /* walk source top to bottom */
+ upsidedown = FALSE;
+ }
+
+ if (careful && dx < 0)
+ {
+ /* walk source right to left */
+ if (dy <= 0)
+ reverse = TRUE;
+ else
+ reverse = FALSE;
+
+ if (nbox > 1)
+ {
+ /* reverse order of rects in each band */
+ pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec) * nbox);
+ if(!pboxNew2)
+ {
+ if (pboxNew1)
+ free(pboxNew1);
+ return;
+ }
+ pboxBase = pboxNext = pbox;
+ while (pboxBase < pbox+nbox)
+ {
+ while ((pboxNext < pbox+nbox) &&
+ (pboxNext->y1 == pboxBase->y1))
+ pboxNext++;
+ pboxTmp = pboxNext;
+ while (pboxTmp != pboxBase)
+ {
+ *pboxNew2++ = *--pboxTmp;
+ }
+ pboxBase = pboxNext;
+ }
+ pboxNew2 -= nbox;
+ pbox = pboxNew2;
+ }
+ }
+ else
+ {
+ /* walk source left to right */
+ reverse = FALSE;
+ }
+
+ (*copyProc) (pSrcDrawable,
+ pDstDrawable,
+ pGC,
+ pbox,
+ nbox,
+ dx, dy,
+ reverse, upsidedown, bitPlane, closure);
+
+ if (pboxNew1)
+ free(pboxNew1);
+ if (pboxNew2)
+ free(pboxNew2);
+}
+
+RegionPtr
+miDoCopy (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ int xIn,
+ int yIn,
+ int widthSrc,
+ int heightSrc,
+ int xOut,
+ int yOut,
+ miCopyProc copyProc,
+ Pixel bitPlane,
+ void *closure)
+{
+ RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */
+ Bool freeSrcClip = FALSE;
+ RegionPtr prgnExposed = NULL;
+ RegionRec rgnDst;
+ int dx;
+ int dy;
+ int numRects;
+ int box_x1;
+ int box_y1;
+ int box_x2;
+ int box_y2;
+ Bool fastSrc = FALSE; /* for fast clipping with pixmap source */
+ Bool fastDst = FALSE; /* for fast clipping with one rect dest */
+ Bool fastExpose = FALSE; /* for fast exposures with pixmap source */
+
+ /* Short cut for unmapped windows */
+
+ if (pDstDrawable->type == DRAWABLE_WINDOW &&
+ !((WindowPtr)pDstDrawable)->realized)
+ {
+ return NULL;
+ }
+
+ if ((pSrcDrawable != pDstDrawable) &&
+ pSrcDrawable->pScreen->SourceValidate)
+ {
+ (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc);
+ }
+
+ /* Compute source clip region */
+ if (pSrcDrawable->type == DRAWABLE_PIXMAP)
+ {
+ if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
+ prgnSrcClip = miGetCompositeClip(pGC);
+ else
+ fastSrc = TRUE;
+ }
+ else
+ {
+ if (pGC->subWindowMode == IncludeInferiors)
+ {
+ /*
+ * XFree86 DDX empties the border clip when the
+ * VT is inactive, make sure the region isn't empty
+ */
+ if (!((WindowPtr) pSrcDrawable)->parent &&
+ REGION_NOTEMPTY (pSrcDrawable->pScreen,
+ &((WindowPtr) pSrcDrawable)->borderClip))
+ {
+ /*
+ * special case bitblt from root window in
+ * IncludeInferiors mode; just like from a pixmap
+ */
+ fastSrc = TRUE;
+ }
+ else if ((pSrcDrawable == pDstDrawable) &&
+ (pGC->clientClipType == CT_NONE))
+ {
+ prgnSrcClip = miGetCompositeClip(pGC);
+ }
+ else
+ {
+ prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
+ freeSrcClip = TRUE;
+ }
+ }
+ else
+ {
+ prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
+ }
+ }
+
+ xIn += pSrcDrawable->x;
+ yIn += pSrcDrawable->y;
+
+ xOut += pDstDrawable->x;
+ yOut += pDstDrawable->y;
+
+ box_x1 = xIn;
+ box_y1 = yIn;
+ box_x2 = xIn + widthSrc;
+ box_y2 = yIn + heightSrc;
+
+ dx = xIn - xOut;
+ dy = yIn - yOut;
+
+ /* Don't create a source region if we are doing a fast clip */
+ if (fastSrc)
+ {
+ RegionPtr cclip;
+
+ fastExpose = TRUE;
+ /*
+ * clip the source; if regions extend beyond the source size,
+ * make sure exposure events get sent
+ */
+ if (box_x1 < pSrcDrawable->x)
+ {
+ box_x1 = pSrcDrawable->x;
+ fastExpose = FALSE;
+ }
+ if (box_y1 < pSrcDrawable->y)
+ {
+ box_y1 = pSrcDrawable->y;
+ fastExpose = FALSE;
+ }
+ if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
+ {
+ box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
+ fastExpose = FALSE;
+ }
+ if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
+ {
+ box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
+ fastExpose = FALSE;
+ }
+
+ /* Translate and clip the dst to the destination composite clip */
+ box_x1 -= dx;
+ box_x2 -= dx;
+ box_y1 -= dy;
+ box_y2 -= dy;
+
+ /* If the destination composite clip is one rectangle we can
+ do the clip directly. Otherwise we have to create a full
+ blown region and call intersect */
+
+ cclip = miGetCompositeClip(pGC);
+ if (REGION_NUM_RECTS(cclip) == 1)
+ {
+ BoxPtr pBox = REGION_RECTS(cclip);
+
+ if (box_x1 < pBox->x1) box_x1 = pBox->x1;
+ if (box_x2 > pBox->x2) box_x2 = pBox->x2;
+ if (box_y1 < pBox->y1) box_y1 = pBox->y1;
+ if (box_y2 > pBox->y2) box_y2 = pBox->y2;
+ fastDst = TRUE;
+ }
+ }
+
+ /* Check to see if the region is empty */
+ if (box_x1 >= box_x2 || box_y1 >= box_y2)
+ {
+ REGION_NULL(pGC->pScreen, &rgnDst);
+ }
+ else
+ {
+ BoxRec box;
+ box.x1 = box_x1;
+ box.y1 = box_y1;
+ box.x2 = box_x2;
+ box.y2 = box_y2;
+ REGION_INIT(pGC->pScreen, &rgnDst, &box, 1);
+ }
+
+ /* Clip against complex source if needed */
+ if (!fastSrc)
+ {
+ REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
+ REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
+ }
+
+ /* Clip against complex dest if needed */
+ if (!fastDst)
+ {
+ REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst,
+ miGetCompositeClip(pGC));
+ }
+
+ /* Do bit blitting */
+ numRects = REGION_NUM_RECTS(&rgnDst);
+ if (numRects && widthSrc && heightSrc)
+ miCopyRegion (pSrcDrawable, pDstDrawable, pGC,
+ &rgnDst, dx, dy, copyProc, bitPlane, closure);
+
+ /* Pixmap sources generate a NoExposed (we return NULL to do this) */
+ if (!fastExpose && pGC->fExpose)
+ prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
+ xIn - pSrcDrawable->x,
+ yIn - pSrcDrawable->y,
+ widthSrc, heightSrc,
+ xOut - pDstDrawable->x,
+ yOut - pDstDrawable->y,
+ (unsigned long) bitPlane);
+ REGION_UNINIT(pGC->pScreen, &rgnDst);
+ if (freeSrcClip)
+ REGION_DESTROY(pGC->pScreen, prgnSrcClip);
+ return prgnExposed;
+}
diff --git a/xorg-server/mi/midispcur.c b/xorg-server/mi/midispcur.c index 904163091..d4b7f132b 100644 --- a/xorg-server/mi/midispcur.c +++ b/xorg-server/mi/midispcur.c @@ -1,874 +1,874 @@ -/* - * midispcur.c - * - * machine independent cursor display routines - */ - - -/* - -Copyright 1989, 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 <X11/X.h> -# include "misc.h" -# include "input.h" -# include "cursorstr.h" -# include "windowstr.h" -# include "regionstr.h" -# include "dixstruct.h" -# include "scrnintstr.h" -# include "servermd.h" -# include "mipointer.h" -# include "misprite.h" -# include "gcstruct.h" - -#ifdef ARGB_CURSOR -# include "picturestr.h" -#endif - -# include "inputstr.h" - -/* per-screen private data */ -static int miDCScreenKeyIndex; -static DevPrivateKey miDCScreenKey = &miDCScreenKeyIndex; - -static Bool miDCCloseScreen(int index, ScreenPtr pScreen); - -/* per device per-screen private data */ -static int miDCSpriteKeyIndex[MAXSCREENS]; -static DevPrivateKey miDCSpriteKey = miDCSpriteKeyIndex; - -typedef struct { - GCPtr pSourceGC, pMaskGC; - GCPtr pSaveGC, pRestoreGC; - GCPtr pMoveGC; - GCPtr pPixSourceGC, pPixMaskGC; - PixmapPtr pSave, pTemp; -#ifdef ARGB_CURSOR - PicturePtr pRootPicture; - PicturePtr pTempPicture; -#endif -} miDCBufferRec, *miDCBufferPtr; - -#define MIDCBUFFER(dev, screen) \ - ((DevHasCursor(dev)) ? \ - (miDCBufferPtr)dixLookupPrivate(&dev->devPrivates, miDCSpriteKey + (screen)->myNum) : \ - (miDCBufferPtr)dixLookupPrivate(&dev->u.master->devPrivates, miDCSpriteKey + (screen)->myNum)) - -/* - * The core pointer buffer will point to the index of the virtual core pointer - * in the pCursorBuffers array. - */ -typedef struct { - CloseScreenProcPtr CloseScreen; -} miDCScreenRec, *miDCScreenPtr; - -/* per-cursor per-screen private data */ -typedef struct { - PixmapPtr sourceBits; /* source bits */ - PixmapPtr maskBits; /* mask bits */ -#ifdef ARGB_CURSOR - PicturePtr pPicture; -#endif -} miDCCursorRec, *miDCCursorPtr; - -/* - * sprite/cursor method table - */ - -static Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static Bool miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y, - unsigned long source, unsigned long mask); -static Bool miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, - int w, int h); -static Bool miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, - int w, int h); -static Bool miDCMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y, - int w, int h, int dx, int dy, - unsigned long source, unsigned long mask); -static Bool miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, int w, int h, - int dx, int dy); - -static Bool miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); -static void miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); - -static miSpriteCursorFuncRec miDCFuncs = { - miDCRealizeCursor, - miDCUnrealizeCursor, - miDCPutUpCursor, - miDCSaveUnderCursor, - miDCRestoreUnderCursor, - miDCMoveCursor, - miDCChangeSave, - miDCDeviceInitialize, - miDCDeviceCleanup -}; - -Bool -miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) -{ - miDCScreenPtr pScreenPriv; - - pScreenPriv = xalloc (sizeof (miDCScreenRec)); - if (!pScreenPriv) - return FALSE; - - - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = miDCCloseScreen; - - dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv); - - if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs)) - { - xfree ((pointer) pScreenPriv); - return FALSE; - } - return TRUE; -} - -static Bool -miDCCloseScreen (int index, ScreenPtr pScreen) -{ - miDCScreenPtr pScreenPriv; - - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); - pScreen->CloseScreen = pScreenPriv->CloseScreen; - xfree ((pointer) pScreenPriv); - return (*pScreen->CloseScreen) (index, pScreen); -} - -static Bool -miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) -{ - if (pCursor->bits->refcnt <= 1) - dixSetPrivate(&pCursor->bits->devPrivates, CursorScreenKey(pScreen), NULL); - return TRUE; -} - -#ifdef ARGB_CURSOR - -static VisualPtr -miDCGetWindowVisual (WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - VisualID vid = wVisual (pWin); - int i; - - for (i = 0; i < pScreen->numVisuals; i++) - if (pScreen->visuals[i].vid == vid) - return &pScreen->visuals[i]; - return 0; -} - -static PicturePtr -miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin) -{ - ScreenPtr pScreen = pDraw->pScreen; - VisualPtr pVisual; - PictFormatPtr pFormat; - XID subwindow_mode = IncludeInferiors; - PicturePtr pPicture; - int error; - - pVisual = miDCGetWindowVisual (pWin); - if (!pVisual) - return 0; - pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual); - if (!pFormat) - return 0; - pPicture = CreatePicture (0, pDraw, pFormat, - CPSubwindowMode, &subwindow_mode, - serverClient, &error); - *ppPicture = pPicture; - return pPicture; -} -#endif - -static miDCCursorPtr -miDCRealize (ScreenPtr pScreen, CursorPtr pCursor) -{ - miDCCursorPtr pPriv; - GCPtr pGC; - XID gcvals[3]; - - pPriv = xalloc (sizeof (miDCCursorRec)); - if (!pPriv) - return NULL; -#ifdef ARGB_CURSOR - if (pCursor->bits->argb) - { - PixmapPtr pPixmap; - PictFormatPtr pFormat; - int error; - - pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); - if (!pFormat) - { - xfree ((pointer) pPriv); - return NULL; - } - - pPriv->sourceBits = 0; - pPriv->maskBits = 0; - pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, - pCursor->bits->height, 32, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pPixmap) - { - xfree ((pointer) pPriv); - return NULL; - } - pGC = GetScratchGC (32, pScreen); - if (!pGC) - { - (*pScreen->DestroyPixmap) (pPixmap); - xfree ((pointer) pPriv); - return NULL; - } - ValidateGC (&pPixmap->drawable, pGC); - (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, - 0, 0, pCursor->bits->width, - pCursor->bits->height, - 0, ZPixmap, (char *) pCursor->bits->argb); - FreeScratchGC (pGC); - pPriv->pPicture = CreatePicture (0, &pPixmap->drawable, - pFormat, 0, 0, serverClient, &error); - (*pScreen->DestroyPixmap) (pPixmap); - if (!pPriv->pPicture) - { - xfree ((pointer) pPriv); - return NULL; - } - dixSetPrivate(&pCursor->bits->devPrivates, CursorScreenKey(pScreen), pPriv); - return pPriv; - } - pPriv->pPicture = 0; -#endif - pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0); - if (!pPriv->sourceBits) - { - xfree ((pointer) pPriv); - return NULL; - } - pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0); - if (!pPriv->maskBits) - { - (*pScreen->DestroyPixmap) (pPriv->sourceBits); - xfree ((pointer) pPriv); - return NULL; - } - dixSetPrivate(&pCursor->bits->devPrivates, CursorScreenKey(pScreen), pPriv); - - /* create the two sets of bits, clipping as appropriate */ - - pGC = GetScratchGC (1, pScreen); - if (!pGC) - { - (void) miDCUnrealizeCursor (pScreen, pCursor); - return NULL; - } - - ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); - (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, - 0, 0, pCursor->bits->width, pCursor->bits->height, - 0, XYPixmap, (char *)pCursor->bits->source); - gcvals[0] = GXand; - ChangeGC (pGC, GCFunction, gcvals); - ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); - (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, - 0, 0, pCursor->bits->width, pCursor->bits->height, - 0, XYPixmap, (char *)pCursor->bits->mask); - - /* mask bits -- pCursor->mask & ~pCursor->source */ - gcvals[0] = GXcopy; - ChangeGC (pGC, GCFunction, gcvals); - ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); - (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, - 0, 0, pCursor->bits->width, pCursor->bits->height, - 0, XYPixmap, (char *)pCursor->bits->mask); - gcvals[0] = GXandInverted; - ChangeGC (pGC, GCFunction, gcvals); - ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); - (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, - 0, 0, pCursor->bits->width, pCursor->bits->height, - 0, XYPixmap, (char *)pCursor->bits->source); - FreeScratchGC (pGC); - return pPriv; -} - -static Bool -miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) -{ - miDCCursorPtr pPriv; - - pPriv = (miDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates, - CursorScreenKey(pScreen)); - if (pPriv && (pCursor->bits->refcnt <= 1)) - { - if (pPriv->sourceBits) - (*pScreen->DestroyPixmap) (pPriv->sourceBits); - if (pPriv->maskBits) - (*pScreen->DestroyPixmap) (pPriv->maskBits); -#ifdef ARGB_CURSOR - if (pPriv->pPicture) - FreePicture (pPriv->pPicture, 0); -#endif - xfree ((pointer) pPriv); - dixSetPrivate(&pCursor->bits->devPrivates, CursorScreenKey(pScreen), NULL); - } - return TRUE; -} - -static void -miDCPutBits ( - DrawablePtr pDrawable, - miDCCursorPtr pPriv, - GCPtr sourceGC, - GCPtr maskGC, - int x_org, - int y_org, - unsigned w, - unsigned h, - unsigned long source, - unsigned long mask) -{ - XID gcvals[1]; - int x, y; - - if (sourceGC->fgPixel != source) - { - gcvals[0] = source; - DoChangeGC (sourceGC, GCForeground, gcvals, 0); - } - if (sourceGC->serialNumber != pDrawable->serialNumber) - ValidateGC (pDrawable, sourceGC); - - if(sourceGC->miTranslate) - { - x = pDrawable->x + x_org; - y = pDrawable->y + y_org; - } - else - { - x = x_org; - y = y_org; - } - - (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); - if (maskGC->fgPixel != mask) - { - gcvals[0] = mask; - DoChangeGC (maskGC, GCForeground, gcvals, 0); - } - if (maskGC->serialNumber != pDrawable->serialNumber) - ValidateGC (pDrawable, maskGC); - - if(maskGC->miTranslate) - { - x = pDrawable->x + x_org; - y = pDrawable->y + y_org; - } - else - { - x = x_org; - y = y_org; - } - - (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); -} - -static GCPtr -miDCMakeGC(WindowPtr pWin) -{ - GCPtr pGC; - int status; - XID gcvals[2]; - - gcvals[0] = IncludeInferiors; - gcvals[1] = FALSE; - pGC = CreateGC((DrawablePtr)pWin, - GCSubwindowMode|GCGraphicsExposures, gcvals, &status, - (XID)0, serverClient); - return pGC; -} - - -static Bool -miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, - int x, int y, unsigned long source, unsigned long mask) -{ - miDCScreenPtr pScreenPriv; - miDCCursorPtr pPriv; - miDCBufferPtr pBuffer; - WindowPtr pWin; - - pPriv = (miDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates, - CursorScreenKey(pScreen)); - if (!pPriv) - { - pPriv = miDCRealize(pScreen, pCursor); - if (!pPriv) - return FALSE; - } - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); - pWin = WindowTable[pScreen->myNum]; - pBuffer = MIDCBUFFER(pDev, pScreen); - -#ifdef ARGB_CURSOR - if (pPriv->pPicture) - { - CompositePicture (PictOpOver, - pPriv->pPicture, - NULL, - pBuffer->pRootPicture, - 0, 0, 0, 0, - x, y, - pCursor->bits->width, - pCursor->bits->height); - } - else -#endif - { - miDCPutBits ((DrawablePtr)pWin, pPriv, - pBuffer->pSourceGC, pBuffer->pMaskGC, - x, y, pCursor->bits->width, pCursor->bits->height, - source, mask); - } - return TRUE; -} - -static Bool -miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, int w, int h) -{ - miDCScreenPtr pScreenPriv; - miDCBufferPtr pBuffer; - PixmapPtr pSave; - WindowPtr pWin; - GCPtr pGC; - - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); - pBuffer = MIDCBUFFER(pDev, pScreen); - - pSave = pBuffer->pSave; - pWin = WindowTable[pScreen->myNum]; - if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) - { - if (pSave) - (*pScreen->DestroyPixmap) (pSave); - pBuffer->pSave = pSave = - (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0); - if (!pSave) - return FALSE; - } - - pGC = pBuffer->pSaveGC; - if (pSave->drawable.serialNumber != pGC->serialNumber) - ValidateGC ((DrawablePtr) pSave, pGC); - (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, - x, y, w, h, 0, 0); - return TRUE; -} - -static Bool -miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, int w, int h) -{ - miDCScreenPtr pScreenPriv; - miDCBufferPtr pBuffer; - PixmapPtr pSave; - WindowPtr pWin; - GCPtr pGC; - - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); - pBuffer = MIDCBUFFER(pDev, pScreen); - pSave = pBuffer->pSave; - - pWin = WindowTable[pScreen->myNum]; - if (!pSave) - return FALSE; - - pGC = pBuffer->pRestoreGC; - if (pWin->drawable.serialNumber != pGC->serialNumber) - ValidateGC ((DrawablePtr) pWin, pGC); - (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, - 0, 0, w, h, x, y); - return TRUE; -} - -static Bool -miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, int w, int h, int dx, int dy) -{ - miDCScreenPtr pScreenPriv; - miDCBufferPtr pBuffer; - PixmapPtr pSave; - WindowPtr pWin; - GCPtr pGC; - int sourcex, sourcey, destx, desty, copyw, copyh; - - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); - pBuffer = MIDCBUFFER(pDev, pScreen); - - pSave = pBuffer->pSave; - pWin = WindowTable[pScreen->myNum]; - /* - * restore the bits which are about to get trashed - */ - if (!pSave) - return FALSE; - - pGC = pBuffer->pRestoreGC; - if (pWin->drawable.serialNumber != pGC->serialNumber) - ValidateGC ((DrawablePtr) pWin, pGC); - /* - * copy the old bits to the screen. - */ - if (dy > 0) - { - (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, - 0, h - dy, w, dy, x + dx, y + h); - } - else if (dy < 0) - { - (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, - 0, 0, w, -dy, x + dx, y + dy); - } - if (dy >= 0) - { - desty = y + dy; - sourcey = 0; - copyh = h - dy; - } - else - { - desty = y; - sourcey = - dy; - copyh = h + dy; - } - if (dx > 0) - { - (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, - w - dx, sourcey, dx, copyh, x + w, desty); - } - else if (dx < 0) - { - (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, - 0, sourcey, -dx, copyh, x + dx, desty); - } - - pGC = pBuffer->pSaveGC; - if (pSave->drawable.serialNumber != pGC->serialNumber) - ValidateGC ((DrawablePtr) pSave, pGC); - /* - * move the bits that are still valid within the pixmap - */ - if (dx >= 0) - { - sourcex = 0; - destx = dx; - copyw = w - dx; - } - else - { - destx = 0; - sourcex = - dx; - copyw = w + dx; - } - if (dy >= 0) - { - sourcey = 0; - desty = dy; - copyh = h - dy; - } - else - { - desty = 0; - sourcey = -dy; - copyh = h + dy; - } - (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC, - sourcex, sourcey, copyw, copyh, destx, desty); - /* - * copy the new bits from the screen into the remaining areas of the - * pixmap - */ - if (dy > 0) - { - (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, - x, y, w, dy, 0, 0); - } - else if (dy < 0) - { - (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, - x, y + h + dy, w, -dy, 0, h + dy); - } - if (dy >= 0) - { - desty = dy; - sourcey = y + dy; - copyh = h - dy; - } - else - { - desty = 0; - sourcey = y; - copyh = h + dy; - } - if (dx > 0) - { - (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, - x, sourcey, dx, copyh, 0, desty); - } - else if (dx < 0) - { - (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, - x + w + dx, sourcey, -dx, copyh, w + dx, desty); - } - return TRUE; -} - -static Bool -miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, - int x, int y, int w, int h, int dx, int dy, - unsigned long source, unsigned long mask) -{ - miDCCursorPtr pPriv; - miDCScreenPtr pScreenPriv; - miDCBufferPtr pBuffer; - int status; - WindowPtr pWin; - GCPtr pGC; - XID gcval = FALSE; - PixmapPtr pTemp; - - pPriv = (miDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates, - CursorScreenKey(pScreen)); - if (!pPriv) - { - pPriv = miDCRealize(pScreen, pCursor); - if (!pPriv) - return FALSE; - } - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); - pWin = WindowTable[pScreen->myNum]; - pBuffer = MIDCBUFFER(pDev, pScreen); - - pTemp = pBuffer->pTemp; - if (!pTemp || - pTemp->drawable.width != pBuffer->pSave->drawable.width || - pTemp->drawable.height != pBuffer->pSave->drawable.height) - { - if (pTemp) - (*pScreen->DestroyPixmap) (pTemp); -#ifdef ARGB_CURSOR - if (pBuffer->pTempPicture) - { - FreePicture (pBuffer->pTempPicture, 0); - pBuffer->pTempPicture = 0; - } -#endif - pBuffer->pTemp = pTemp = (*pScreen->CreatePixmap) - (pScreen, w, h, pBuffer->pSave->drawable.depth, 0); - if (!pTemp) - return FALSE; - } - if (!pBuffer->pMoveGC) - { - pBuffer->pMoveGC = CreateGC ((DrawablePtr)pTemp, - GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pBuffer->pMoveGC) - return FALSE; - } - /* - * copy the saved area to a temporary pixmap - */ - pGC = pBuffer->pMoveGC; - if (pGC->serialNumber != pTemp->drawable.serialNumber) - ValidateGC ((DrawablePtr) pTemp, pGC); - (*pGC->ops->CopyArea)((DrawablePtr)pBuffer->pSave, - (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0); - - /* - * draw the cursor in the temporary pixmap - */ -#ifdef ARGB_CURSOR - if (pPriv->pPicture) - { - if (!pBuffer->pTempPicture) - miDCMakePicture(&pBuffer->pTempPicture, &pTemp->drawable, pWin); - - CompositePicture (PictOpOver, - pPriv->pPicture, - NULL, - pBuffer->pTempPicture, - 0, 0, 0, 0, - dx, dy, - pCursor->bits->width, - pCursor->bits->height); - } - else -#endif - { - miDCPutBits ((DrawablePtr)pTemp, pPriv, - pBuffer->pPixSourceGC, pBuffer->pPixMaskGC, - dx, dy, pCursor->bits->width, pCursor->bits->height, - source, mask); - } - - pGC = pBuffer->pRestoreGC; - if (pWin->drawable.serialNumber != pGC->serialNumber) - ValidateGC ((DrawablePtr) pWin, pGC); - - (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin, - pGC, - 0, 0, w, h, x, y); - return TRUE; -} - -static Bool -miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miDCBufferPtr pBuffer; - WindowPtr pWin; - XID gcval = FALSE; - int status; - int i; - - if (!DevHasCursor(pDev)) - return TRUE; - - for (i = 0; i < screenInfo.numScreens; i++) - { - pScreen = screenInfo.screens[i]; - - pBuffer = xalloc(sizeof(miDCBufferRec)); - if (!pBuffer) - goto failure; - - dixSetPrivate(&pDev->devPrivates, miDCSpriteKey + pScreen->myNum, pBuffer); - pWin = WindowTable[pScreen->myNum]; - - pBuffer->pSourceGC = miDCMakeGC(pWin); - if (!pBuffer->pSourceGC) - goto failure; - - pBuffer->pMaskGC = miDCMakeGC(pWin); - if (!pBuffer->pMaskGC) - goto failure; - - pBuffer->pSaveGC = miDCMakeGC(pWin); - if (!pBuffer->pSaveGC) - goto failure; - - pBuffer->pRestoreGC = miDCMakeGC(pWin); - if (!pBuffer->pRestoreGC) - goto failure; - - pBuffer->pMoveGC = CreateGC ((DrawablePtr)pWin, - GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pBuffer->pMoveGC) - goto failure; - - pBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pWin, - GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pBuffer->pPixSourceGC) - goto failure; - - pBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pWin, - GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pBuffer->pPixMaskGC) - goto failure; - -#ifdef ARGB_CURSOR - miDCMakePicture(&pBuffer->pRootPicture, &pWin->drawable, pWin); - if (!pBuffer->pRootPicture) - goto failure; - - pBuffer->pTempPicture = NULL; -#endif - - // these get (re)allocated lazily depending on the cursor size - pBuffer->pSave = pBuffer->pTemp = NULL; - } - - return TRUE; - -failure: - - miDCDeviceCleanup(pDev, pScreen); - - return FALSE; -} - -static void -miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miDCBufferPtr pBuffer; - int i; - - if (DevHasCursor(pDev)) - { - for (i = 0; i < screenInfo.numScreens; i++) - { - pScreen = screenInfo.screens[i]; - - pBuffer = MIDCBUFFER(pDev, pScreen); - - if (pBuffer) - { - if (pBuffer->pSourceGC) FreeGC(pBuffer->pSourceGC, (GContext) 0); - if (pBuffer->pMaskGC) FreeGC(pBuffer->pMaskGC, (GContext) 0); - if (pBuffer->pSaveGC) FreeGC(pBuffer->pSaveGC, (GContext) 0); - if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0); - if (pBuffer->pMoveGC) FreeGC(pBuffer->pMoveGC, (GContext) 0); - if (pBuffer->pPixSourceGC) FreeGC(pBuffer->pPixSourceGC, (GContext) 0); - if (pBuffer->pPixMaskGC) FreeGC(pBuffer->pPixMaskGC, (GContext) 0); - - if (pBuffer->pSave) (*pScreen->DestroyPixmap)(pBuffer->pSave); - if (pBuffer->pTemp) (*pScreen->DestroyPixmap)(pBuffer->pTemp); - - xfree(pBuffer); - dixSetPrivate(&pDev->devPrivates, miDCSpriteKey + pScreen->myNum, NULL); - } - } - } -} +/*
+ * midispcur.c
+ *
+ * machine independent cursor display routines
+ */
+
+
+/*
+
+Copyright 1989, 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 <X11/X.h>
+# include "misc.h"
+# include "input.h"
+# include "cursorstr.h"
+# include "windowstr.h"
+# include "regionstr.h"
+# include "dixstruct.h"
+# include "scrnintstr.h"
+# include "servermd.h"
+# include "mipointer.h"
+# include "misprite.h"
+# include "gcstruct.h"
+
+#ifdef ARGB_CURSOR
+# include "picturestr.h"
+#endif
+
+# include "inputstr.h"
+
+/* per-screen private data */
+static int miDCScreenKeyIndex;
+static DevPrivateKey miDCScreenKey = &miDCScreenKeyIndex;
+
+static Bool miDCCloseScreen(int index, ScreenPtr pScreen);
+
+/* per device per-screen private data */
+static int miDCSpriteKeyIndex[MAXSCREENS];
+static DevPrivateKey miDCSpriteKey = miDCSpriteKeyIndex;
+
+typedef struct {
+ GCPtr pSourceGC, pMaskGC;
+ GCPtr pSaveGC, pRestoreGC;
+ GCPtr pMoveGC;
+ GCPtr pPixSourceGC, pPixMaskGC;
+ PixmapPtr pSave, pTemp;
+#ifdef ARGB_CURSOR
+ PicturePtr pRootPicture;
+ PicturePtr pTempPicture;
+#endif
+} miDCBufferRec, *miDCBufferPtr;
+
+#define MIDCBUFFER(dev, screen) \
+ ((DevHasCursor(dev)) ? \
+ (miDCBufferPtr)dixLookupPrivate(&dev->devPrivates, miDCSpriteKey + (screen)->myNum) : \
+ (miDCBufferPtr)dixLookupPrivate(&dev->u.master->devPrivates, miDCSpriteKey + (screen)->myNum))
+
+/*
+ * The core pointer buffer will point to the index of the virtual core pointer
+ * in the pCursorBuffers array.
+ */
+typedef struct {
+ CloseScreenProcPtr CloseScreen;
+} miDCScreenRec, *miDCScreenPtr;
+
+/* per-cursor per-screen private data */
+typedef struct {
+ PixmapPtr sourceBits; /* source bits */
+ PixmapPtr maskBits; /* mask bits */
+#ifdef ARGB_CURSOR
+ PicturePtr pPicture;
+#endif
+} miDCCursorRec, *miDCCursorPtr;
+
+/*
+ * sprite/cursor method table
+ */
+
+static Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+static Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+static Bool miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor, int x, int y,
+ unsigned long source, unsigned long mask);
+static Bool miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y,
+ int w, int h);
+static Bool miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y,
+ int w, int h);
+static Bool miDCMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor, int x, int y,
+ int w, int h, int dx, int dy,
+ unsigned long source, unsigned long mask);
+static Bool miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y, int w, int h,
+ int dx, int dy);
+
+static Bool miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
+static void miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
+
+static miSpriteCursorFuncRec miDCFuncs = {
+ miDCRealizeCursor,
+ miDCUnrealizeCursor,
+ miDCPutUpCursor,
+ miDCSaveUnderCursor,
+ miDCRestoreUnderCursor,
+ miDCMoveCursor,
+ miDCChangeSave,
+ miDCDeviceInitialize,
+ miDCDeviceCleanup
+};
+
+Bool
+miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
+{
+ miDCScreenPtr pScreenPriv;
+
+ pScreenPriv = malloc(sizeof (miDCScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = miDCCloseScreen;
+
+ dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
+
+ if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
+ {
+ free((pointer) pScreenPriv);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+miDCCloseScreen (int index, ScreenPtr pScreen)
+{
+ miDCScreenPtr pScreenPriv;
+
+ pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ miDCScreenKey);
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ free((pointer) pScreenPriv);
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+static Bool
+miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ if (pCursor->bits->refcnt <= 1)
+ dixSetPrivate(&pCursor->bits->devPrivates, CursorScreenKey(pScreen), NULL);
+ return TRUE;
+}
+
+#ifdef ARGB_CURSOR
+
+static VisualPtr
+miDCGetWindowVisual (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ VisualID vid = wVisual (pWin);
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ if (pScreen->visuals[i].vid == vid)
+ return &pScreen->visuals[i];
+ return 0;
+}
+
+static PicturePtr
+miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ VisualPtr pVisual;
+ PictFormatPtr pFormat;
+ XID subwindow_mode = IncludeInferiors;
+ PicturePtr pPicture;
+ int error;
+
+ pVisual = miDCGetWindowVisual (pWin);
+ if (!pVisual)
+ return 0;
+ pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual);
+ if (!pFormat)
+ return 0;
+ pPicture = CreatePicture (0, pDraw, pFormat,
+ CPSubwindowMode, &subwindow_mode,
+ serverClient, &error);
+ *ppPicture = pPicture;
+ return pPicture;
+}
+#endif
+
+static miDCCursorPtr
+miDCRealize (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ miDCCursorPtr pPriv;
+ GCPtr pGC;
+ ChangeGCVal gcvals;
+
+ pPriv = malloc(sizeof (miDCCursorRec));
+ if (!pPriv)
+ return NULL;
+#ifdef ARGB_CURSOR
+ if (pCursor->bits->argb)
+ {
+ PixmapPtr pPixmap;
+ PictFormatPtr pFormat;
+ int error;
+
+ pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
+ if (!pFormat)
+ {
+ free((pointer) pPriv);
+ return NULL;
+ }
+
+ pPriv->sourceBits = 0;
+ pPriv->maskBits = 0;
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
+ pCursor->bits->height, 32,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap)
+ {
+ free((pointer) pPriv);
+ return NULL;
+ }
+ pGC = GetScratchGC (32, pScreen);
+ if (!pGC)
+ {
+ (*pScreen->DestroyPixmap) (pPixmap);
+ free((pointer) pPriv);
+ return NULL;
+ }
+ ValidateGC (&pPixmap->drawable, pGC);
+ (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
+ 0, 0, pCursor->bits->width,
+ pCursor->bits->height,
+ 0, ZPixmap, (char *) pCursor->bits->argb);
+ FreeScratchGC (pGC);
+ pPriv->pPicture = CreatePicture (0, &pPixmap->drawable,
+ pFormat, 0, 0, serverClient, &error);
+ (*pScreen->DestroyPixmap) (pPixmap);
+ if (!pPriv->pPicture)
+ {
+ free((pointer) pPriv);
+ return NULL;
+ }
+ dixSetPrivate(&pCursor->bits->devPrivates, CursorScreenKey(pScreen), pPriv);
+ return pPriv;
+ }
+ pPriv->pPicture = 0;
+#endif
+ pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
+ if (!pPriv->sourceBits)
+ {
+ free((pointer) pPriv);
+ return NULL;
+ }
+ pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
+ if (!pPriv->maskBits)
+ {
+ (*pScreen->DestroyPixmap) (pPriv->sourceBits);
+ free((pointer) pPriv);
+ return NULL;
+ }
+ dixSetPrivate(&pCursor->bits->devPrivates, CursorScreenKey(pScreen), pPriv);
+
+ /* create the two sets of bits, clipping as appropriate */
+
+ pGC = GetScratchGC (1, pScreen);
+ if (!pGC)
+ {
+ (void) miDCUnrealizeCursor (pScreen, pCursor);
+ return NULL;
+ }
+
+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->source);
+ gcvals.val = GXand;
+ ChangeGC (NullClient, pGC, GCFunction, &gcvals);
+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->mask);
+
+ /* mask bits -- pCursor->mask & ~pCursor->source */
+ gcvals.val = GXcopy;
+ ChangeGC (NullClient, pGC, GCFunction, &gcvals);
+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->mask);
+ gcvals.val = GXandInverted;
+ ChangeGC (NullClient, pGC, GCFunction, &gcvals);
+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->source);
+ FreeScratchGC (pGC);
+ return pPriv;
+}
+
+static Bool
+miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ miDCCursorPtr pPriv;
+
+ pPriv = (miDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates,
+ CursorScreenKey(pScreen));
+ if (pPriv && (pCursor->bits->refcnt <= 1))
+ {
+ if (pPriv->sourceBits)
+ (*pScreen->DestroyPixmap) (pPriv->sourceBits);
+ if (pPriv->maskBits)
+ (*pScreen->DestroyPixmap) (pPriv->maskBits);
+#ifdef ARGB_CURSOR
+ if (pPriv->pPicture)
+ FreePicture (pPriv->pPicture, 0);
+#endif
+ free((pointer) pPriv);
+ dixSetPrivate(&pCursor->bits->devPrivates, CursorScreenKey(pScreen), NULL);
+ }
+ return TRUE;
+}
+
+static void
+miDCPutBits (
+ DrawablePtr pDrawable,
+ miDCCursorPtr pPriv,
+ GCPtr sourceGC,
+ GCPtr maskGC,
+ int x_org,
+ int y_org,
+ unsigned w,
+ unsigned h,
+ unsigned long source,
+ unsigned long mask)
+{
+ ChangeGCVal gcval;
+ int x, y;
+
+ if (sourceGC->fgPixel != source)
+ {
+ gcval.val = source;
+ ChangeGC (NullClient, sourceGC, GCForeground, &gcval);
+ }
+ if (sourceGC->serialNumber != pDrawable->serialNumber)
+ ValidateGC (pDrawable, sourceGC);
+
+ if(sourceGC->miTranslate)
+ {
+ x = pDrawable->x + x_org;
+ y = pDrawable->y + y_org;
+ }
+ else
+ {
+ x = x_org;
+ y = y_org;
+ }
+
+ (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
+ if (maskGC->fgPixel != mask)
+ {
+ gcval.val = mask;
+ ChangeGC (NullClient, maskGC, GCForeground, &gcval);
+ }
+ if (maskGC->serialNumber != pDrawable->serialNumber)
+ ValidateGC (pDrawable, maskGC);
+
+ if(maskGC->miTranslate)
+ {
+ x = pDrawable->x + x_org;
+ y = pDrawable->y + y_org;
+ }
+ else
+ {
+ x = x_org;
+ y = y_org;
+ }
+
+ (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
+}
+
+static GCPtr
+miDCMakeGC(WindowPtr pWin)
+{
+ GCPtr pGC;
+ int status;
+ XID gcvals[2];
+
+ gcvals[0] = IncludeInferiors;
+ gcvals[1] = FALSE;
+ pGC = CreateGC((DrawablePtr)pWin,
+ GCSubwindowMode|GCGraphicsExposures, gcvals, &status,
+ (XID)0, serverClient);
+ return pGC;
+}
+
+
+static Bool
+miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
+ int x, int y, unsigned long source, unsigned long mask)
+{
+ miDCScreenPtr pScreenPriv;
+ miDCCursorPtr pPriv;
+ miDCBufferPtr pBuffer;
+ WindowPtr pWin;
+
+ pPriv = (miDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates,
+ CursorScreenKey(pScreen));
+ if (!pPriv)
+ {
+ pPriv = miDCRealize(pScreen, pCursor);
+ if (!pPriv)
+ return FALSE;
+ }
+ pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ miDCScreenKey);
+ pWin = WindowTable[pScreen->myNum];
+ pBuffer = MIDCBUFFER(pDev, pScreen);
+
+#ifdef ARGB_CURSOR
+ if (pPriv->pPicture)
+ {
+ CompositePicture (PictOpOver,
+ pPriv->pPicture,
+ NULL,
+ pBuffer->pRootPicture,
+ 0, 0, 0, 0,
+ x, y,
+ pCursor->bits->width,
+ pCursor->bits->height);
+ }
+ else
+#endif
+ {
+ miDCPutBits ((DrawablePtr)pWin, pPriv,
+ pBuffer->pSourceGC, pBuffer->pMaskGC,
+ x, y, pCursor->bits->width, pCursor->bits->height,
+ source, mask);
+ }
+ return TRUE;
+}
+
+static Bool
+miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y, int w, int h)
+{
+ miDCScreenPtr pScreenPriv;
+ miDCBufferPtr pBuffer;
+ PixmapPtr pSave;
+ WindowPtr pWin;
+ GCPtr pGC;
+
+ pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ miDCScreenKey);
+ pBuffer = MIDCBUFFER(pDev, pScreen);
+
+ pSave = pBuffer->pSave;
+ pWin = WindowTable[pScreen->myNum];
+ if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
+ {
+ if (pSave)
+ (*pScreen->DestroyPixmap) (pSave);
+ pBuffer->pSave = pSave =
+ (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
+ if (!pSave)
+ return FALSE;
+ }
+
+ pGC = pBuffer->pSaveGC;
+ if (pSave->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pSave, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, y, w, h, 0, 0);
+ return TRUE;
+}
+
+static Bool
+miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y, int w, int h)
+{
+ miDCScreenPtr pScreenPriv;
+ miDCBufferPtr pBuffer;
+ PixmapPtr pSave;
+ WindowPtr pWin;
+ GCPtr pGC;
+
+ pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ miDCScreenKey);
+ pBuffer = MIDCBUFFER(pDev, pScreen);
+ pSave = pBuffer->pSave;
+
+ pWin = WindowTable[pScreen->myNum];
+ if (!pSave)
+ return FALSE;
+
+ pGC = pBuffer->pRestoreGC;
+ if (pWin->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pWin, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, 0, w, h, x, y);
+ return TRUE;
+}
+
+static Bool
+miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y, int w, int h, int dx, int dy)
+{
+ miDCScreenPtr pScreenPriv;
+ miDCBufferPtr pBuffer;
+ PixmapPtr pSave;
+ WindowPtr pWin;
+ GCPtr pGC;
+ int sourcex, sourcey, destx, desty, copyw, copyh;
+
+ pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ miDCScreenKey);
+ pBuffer = MIDCBUFFER(pDev, pScreen);
+
+ pSave = pBuffer->pSave;
+ pWin = WindowTable[pScreen->myNum];
+ /*
+ * restore the bits which are about to get trashed
+ */
+ if (!pSave)
+ return FALSE;
+
+ pGC = pBuffer->pRestoreGC;
+ if (pWin->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pWin, pGC);
+ /*
+ * copy the old bits to the screen.
+ */
+ if (dy > 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, h - dy, w, dy, x + dx, y + h);
+ }
+ else if (dy < 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, 0, w, -dy, x + dx, y + dy);
+ }
+ if (dy >= 0)
+ {
+ desty = y + dy;
+ sourcey = 0;
+ copyh = h - dy;
+ }
+ else
+ {
+ desty = y;
+ sourcey = - dy;
+ copyh = h + dy;
+ }
+ if (dx > 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ w - dx, sourcey, dx, copyh, x + w, desty);
+ }
+ else if (dx < 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, sourcey, -dx, copyh, x + dx, desty);
+ }
+
+ pGC = pBuffer->pSaveGC;
+ if (pSave->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pSave, pGC);
+ /*
+ * move the bits that are still valid within the pixmap
+ */
+ if (dx >= 0)
+ {
+ sourcex = 0;
+ destx = dx;
+ copyw = w - dx;
+ }
+ else
+ {
+ destx = 0;
+ sourcex = - dx;
+ copyw = w + dx;
+ }
+ if (dy >= 0)
+ {
+ sourcey = 0;
+ desty = dy;
+ copyh = h - dy;
+ }
+ else
+ {
+ desty = 0;
+ sourcey = -dy;
+ copyh = h + dy;
+ }
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC,
+ sourcex, sourcey, copyw, copyh, destx, desty);
+ /*
+ * copy the new bits from the screen into the remaining areas of the
+ * pixmap
+ */
+ if (dy > 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, y, w, dy, 0, 0);
+ }
+ else if (dy < 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, y + h + dy, w, -dy, 0, h + dy);
+ }
+ if (dy >= 0)
+ {
+ desty = dy;
+ sourcey = y + dy;
+ copyh = h - dy;
+ }
+ else
+ {
+ desty = 0;
+ sourcey = y;
+ copyh = h + dy;
+ }
+ if (dx > 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, sourcey, dx, copyh, 0, desty);
+ }
+ else if (dx < 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x + w + dx, sourcey, -dx, copyh, w + dx, desty);
+ }
+ return TRUE;
+}
+
+static Bool
+miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
+ int x, int y, int w, int h, int dx, int dy,
+ unsigned long source, unsigned long mask)
+{
+ miDCCursorPtr pPriv;
+ miDCScreenPtr pScreenPriv;
+ miDCBufferPtr pBuffer;
+ int status;
+ WindowPtr pWin;
+ GCPtr pGC;
+ XID gcval = FALSE;
+ PixmapPtr pTemp;
+
+ pPriv = (miDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates,
+ CursorScreenKey(pScreen));
+ if (!pPriv)
+ {
+ pPriv = miDCRealize(pScreen, pCursor);
+ if (!pPriv)
+ return FALSE;
+ }
+ pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ miDCScreenKey);
+ pWin = WindowTable[pScreen->myNum];
+ pBuffer = MIDCBUFFER(pDev, pScreen);
+
+ pTemp = pBuffer->pTemp;
+ if (!pTemp ||
+ pTemp->drawable.width != pBuffer->pSave->drawable.width ||
+ pTemp->drawable.height != pBuffer->pSave->drawable.height)
+ {
+ if (pTemp)
+ (*pScreen->DestroyPixmap) (pTemp);
+#ifdef ARGB_CURSOR
+ if (pBuffer->pTempPicture)
+ {
+ FreePicture (pBuffer->pTempPicture, 0);
+ pBuffer->pTempPicture = 0;
+ }
+#endif
+ pBuffer->pTemp = pTemp = (*pScreen->CreatePixmap)
+ (pScreen, w, h, pBuffer->pSave->drawable.depth, 0);
+ if (!pTemp)
+ return FALSE;
+ }
+ if (!pBuffer->pMoveGC)
+ {
+ pBuffer->pMoveGC = CreateGC ((DrawablePtr)pTemp,
+ GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
+ if (!pBuffer->pMoveGC)
+ return FALSE;
+ }
+ /*
+ * copy the saved area to a temporary pixmap
+ */
+ pGC = pBuffer->pMoveGC;
+ if (pGC->serialNumber != pTemp->drawable.serialNumber)
+ ValidateGC ((DrawablePtr) pTemp, pGC);
+ (*pGC->ops->CopyArea)((DrawablePtr)pBuffer->pSave,
+ (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0);
+
+ /*
+ * draw the cursor in the temporary pixmap
+ */
+#ifdef ARGB_CURSOR
+ if (pPriv->pPicture)
+ {
+ if (!pBuffer->pTempPicture)
+ miDCMakePicture(&pBuffer->pTempPicture, &pTemp->drawable, pWin);
+
+ CompositePicture (PictOpOver,
+ pPriv->pPicture,
+ NULL,
+ pBuffer->pTempPicture,
+ 0, 0, 0, 0,
+ dx, dy,
+ pCursor->bits->width,
+ pCursor->bits->height);
+ }
+ else
+#endif
+ {
+ miDCPutBits ((DrawablePtr)pTemp, pPriv,
+ pBuffer->pPixSourceGC, pBuffer->pPixMaskGC,
+ dx, dy, pCursor->bits->width, pCursor->bits->height,
+ source, mask);
+ }
+
+ pGC = pBuffer->pRestoreGC;
+ if (pWin->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pWin, pGC);
+
+ (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin,
+ pGC,
+ 0, 0, w, h, x, y);
+ return TRUE;
+}
+
+static Bool
+miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miDCBufferPtr pBuffer;
+ WindowPtr pWin;
+ XID gcval = FALSE;
+ int status;
+ int i;
+
+ if (!DevHasCursor(pDev))
+ return TRUE;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+
+ pBuffer = malloc(sizeof(miDCBufferRec));
+ if (!pBuffer)
+ goto failure;
+
+ dixSetPrivate(&pDev->devPrivates, miDCSpriteKey + pScreen->myNum, pBuffer);
+ pWin = WindowTable[pScreen->myNum];
+
+ pBuffer->pSourceGC = miDCMakeGC(pWin);
+ if (!pBuffer->pSourceGC)
+ goto failure;
+
+ pBuffer->pMaskGC = miDCMakeGC(pWin);
+ if (!pBuffer->pMaskGC)
+ goto failure;
+
+ pBuffer->pSaveGC = miDCMakeGC(pWin);
+ if (!pBuffer->pSaveGC)
+ goto failure;
+
+ pBuffer->pRestoreGC = miDCMakeGC(pWin);
+ if (!pBuffer->pRestoreGC)
+ goto failure;
+
+ pBuffer->pMoveGC = CreateGC ((DrawablePtr)pWin,
+ GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
+ if (!pBuffer->pMoveGC)
+ goto failure;
+
+ pBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pWin,
+ GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
+ if (!pBuffer->pPixSourceGC)
+ goto failure;
+
+ pBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pWin,
+ GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
+ if (!pBuffer->pPixMaskGC)
+ goto failure;
+
+#ifdef ARGB_CURSOR
+ miDCMakePicture(&pBuffer->pRootPicture, &pWin->drawable, pWin);
+ if (!pBuffer->pRootPicture)
+ goto failure;
+
+ pBuffer->pTempPicture = NULL;
+#endif
+
+ // these get (re)allocated lazily depending on the cursor size
+ pBuffer->pSave = pBuffer->pTemp = NULL;
+ }
+
+ return TRUE;
+
+failure:
+
+ miDCDeviceCleanup(pDev, pScreen);
+
+ return FALSE;
+}
+
+static void
+miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miDCBufferPtr pBuffer;
+ int i;
+
+ if (DevHasCursor(pDev))
+ {
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+
+ pBuffer = MIDCBUFFER(pDev, pScreen);
+
+ if (pBuffer)
+ {
+ if (pBuffer->pSourceGC) FreeGC(pBuffer->pSourceGC, (GContext) 0);
+ if (pBuffer->pMaskGC) FreeGC(pBuffer->pMaskGC, (GContext) 0);
+ if (pBuffer->pSaveGC) FreeGC(pBuffer->pSaveGC, (GContext) 0);
+ if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0);
+ if (pBuffer->pMoveGC) FreeGC(pBuffer->pMoveGC, (GContext) 0);
+ if (pBuffer->pPixSourceGC) FreeGC(pBuffer->pPixSourceGC, (GContext) 0);
+ if (pBuffer->pPixMaskGC) FreeGC(pBuffer->pPixMaskGC, (GContext) 0);
+
+ if (pBuffer->pSave) (*pScreen->DestroyPixmap)(pBuffer->pSave);
+ if (pBuffer->pTemp) (*pScreen->DestroyPixmap)(pBuffer->pTemp);
+
+ free(pBuffer);
+ dixSetPrivate(&pDev->devPrivates, miDCSpriteKey + pScreen->myNum, NULL);
+ }
+ }
+ }
+}
diff --git a/xorg-server/mi/mieq.c b/xorg-server/mi/mieq.c index b06ff0447..58db72968 100644 --- a/xorg-server/mi/mieq.c +++ b/xorg-server/mi/mieq.c @@ -191,7 +191,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) if (evt->evlen < evlen)
{
evt->evlen = evlen;
- evt->event = xrealloc(evt->event, evt->evlen);
+ evt->event = realloc(evt->event, evt->evlen);
if (!evt->event)
{
ErrorF("[mi] Running out of memory. Tossing event.\n");
@@ -440,7 +440,7 @@ mieqProcessInputEvents(void) evlen = e->events->evlen;
if(evlen > event_size)
{
- event = xrealloc(event, evlen);
+ event = realloc(event, evlen);
event_size = evlen;
}
diff --git a/xorg-server/mi/miexpose.c b/xorg-server/mi/miexpose.c index f52b49211..f6f195daa 100644 --- a/xorg-server/mi/miexpose.c +++ b/xorg-server/mi/miexpose.c @@ -1,699 +1,700 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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. - -******************************************************************/ -/***************************************************************** - -Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software. - -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 -DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, -BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation -shall not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization from Digital -Equipment Corporation. - -******************************************************************/ - - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/Xprotostr.h> - -#include "misc.h" -#include "regionstr.h" -#include "scrnintstr.h" -#include "gcstruct.h" -#include "windowstr.h" -#include "pixmap.h" -#include "input.h" - -#include "dixstruct.h" -#include "mi.h" -#include <X11/Xmd.h> - -#include "globals.h" - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif - -/* - machine-independent graphics exposure code. any device that uses -the region package can call this. -*/ - -#ifndef RECTLIMIT -#define RECTLIMIT 25 /* pick a number, any number > 8 */ -#endif - -/* miHandleExposures - generate a region for exposures for areas that were copied from obscured or -non-existent areas to non-obscured areas of the destination. Paint the -background for the region, if the destination is a window. - -NOTE: - this should generally be called, even if graphicsExposures is false, -because this is where bits get recovered from backing store. - -NOTE: - added argument 'plane' is used to indicate how exposures from backing -store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea -should be used, else a CopyPlane of the indicated plane will be used. The -exposing is done by the backing store's GraphicsExpose function, of course. - -*/ - -RegionPtr -miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, - GCPtr pGC, int srcx, int srcy, int width, int height, - int dstx, int dsty, unsigned long plane) -{ - ScreenPtr pscr; - RegionPtr prgnSrcClip; /* drawable-relative source clip */ - RegionRec rgnSrcRec; - RegionPtr prgnDstClip; /* drawable-relative dest clip */ - RegionRec rgnDstRec; - BoxRec srcBox; /* unclipped source */ - RegionRec rgnExposed; /* exposed region, calculated source- - relative, made dst relative to - intersect with visible parts of - dest and send events to client, - and then screen relative to paint - the window background - */ - WindowPtr pSrcWin; - BoxRec expBox; - Bool extents; - - /* This prevents warning about pscr not being used. */ - pGC->pScreen = pscr = pGC->pScreen; - - /* avoid work if we can */ - if (!pGC->graphicsExposures && - (pDstDrawable->type == DRAWABLE_PIXMAP) && - ((pSrcDrawable->type == DRAWABLE_PIXMAP) || - (((WindowPtr)pSrcDrawable)->backStorage == NULL))) - return NULL; - - srcBox.x1 = srcx; - srcBox.y1 = srcy; - srcBox.x2 = srcx+width; - srcBox.y2 = srcy+height; - - if (pSrcDrawable->type != DRAWABLE_PIXMAP) - { - BoxRec TsrcBox; - - TsrcBox.x1 = srcx + pSrcDrawable->x; - TsrcBox.y1 = srcy + pSrcDrawable->y; - TsrcBox.x2 = TsrcBox.x1 + width; - TsrcBox.y2 = TsrcBox.y1 + height; - pSrcWin = (WindowPtr) pSrcDrawable; - if (pGC->subWindowMode == IncludeInferiors) - { - prgnSrcClip = NotClippedByChildren (pSrcWin); - if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) - { - REGION_DESTROY(pscr, prgnSrcClip); - return NULL; - } - } - else - { - if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) - return NULL; - prgnSrcClip = &rgnSrcRec; - REGION_NULL(pscr, prgnSrcClip); - REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); - } - REGION_TRANSLATE(pscr, prgnSrcClip, - -pSrcDrawable->x, -pSrcDrawable->y); - } - else - { - BoxRec box; - - if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && - (srcBox.x2 <= pSrcDrawable->width) && - (srcBox.y2 <= pSrcDrawable->height)) - return NULL; - - box.x1 = 0; - box.y1 = 0; - box.x2 = pSrcDrawable->width; - box.y2 = pSrcDrawable->height; - prgnSrcClip = &rgnSrcRec; - REGION_INIT(pscr, prgnSrcClip, &box, 1); - pSrcWin = NULL; - } - - if (pDstDrawable == pSrcDrawable) - { - prgnDstClip = prgnSrcClip; - } - else if (pDstDrawable->type != DRAWABLE_PIXMAP) - { - if (pGC->subWindowMode == IncludeInferiors) - { - prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); - } - else - { - prgnDstClip = &rgnDstRec; - REGION_NULL(pscr, prgnDstClip); - REGION_COPY(pscr, prgnDstClip, - &((WindowPtr)pDstDrawable)->clipList); - } - REGION_TRANSLATE(pscr, prgnDstClip, - -pDstDrawable->x, -pDstDrawable->y); - } - else - { - BoxRec box; - - box.x1 = 0; - box.y1 = 0; - box.x2 = pDstDrawable->width; - box.y2 = pDstDrawable->height; - prgnDstClip = &rgnDstRec; - REGION_INIT(pscr, prgnDstClip, &box, 1); - } - - /* drawable-relative source region */ - REGION_INIT(pscr, &rgnExposed, &srcBox, 1); - - /* now get the hidden parts of the source box*/ - REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); - - /* move them over the destination */ - REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); - - /* intersect with visible areas of dest */ - REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); - - /* intersect with client clip region. */ - if (pGC->clientClipType == CT_REGION) - REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, pGC->clientClip); - - /* - * If we have LOTS of rectangles, we decide to take the extents - * and force an exposure on that. This should require much less - * work overall, on both client and server. This is cheating, but - * isn't prohibited by the protocol ("spontaneous combustion" :-) - * for windows. - */ - extents = pGC->graphicsExposures && - (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && - (pDstDrawable->type != DRAWABLE_PIXMAP); - if (pSrcWin) - { - RegionPtr region; - if (!(region = wClipShape (pSrcWin))) - region = wBoundingShape (pSrcWin); - /* - * If you try to CopyArea the extents of a shaped window, compacting the - * exposed region will undo all our work! - */ - if (extents && pSrcWin && region && - (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) - extents = FALSE; - } - if (extents) - { - expBox = *REGION_EXTENTS(pscr, &rgnExposed); - REGION_RESET(pscr, &rgnExposed, &expBox); - } - if ((pDstDrawable->type != DRAWABLE_PIXMAP) && - (((WindowPtr)pDstDrawable)->backgroundState != None)) - { - WindowPtr pWin = (WindowPtr)pDstDrawable; - - /* make the exposed area screen-relative */ - REGION_TRANSLATE(pscr, &rgnExposed, - pDstDrawable->x, pDstDrawable->y); - - if (extents) - { - /* PaintWindowBackground doesn't clip, so we have to */ - REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); - } - miPaintWindow((WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); - - if (extents) - { - REGION_RESET(pscr, &rgnExposed, &expBox); - } - else - REGION_TRANSLATE(pscr, &rgnExposed, - -pDstDrawable->x, -pDstDrawable->y); - } - if (prgnDstClip == &rgnDstRec) - { - REGION_UNINIT(pscr, prgnDstClip); - } - else if (prgnDstClip != prgnSrcClip) - { - REGION_DESTROY(pscr, prgnDstClip); - } - - if (prgnSrcClip == &rgnSrcRec) - { - REGION_UNINIT(pscr, prgnSrcClip); - } - else - { - REGION_DESTROY(pscr, prgnSrcClip); - } - - if (pGC->graphicsExposures) - { - /* don't look */ - RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); - *exposed = rgnExposed; - return exposed; - } - else - { - REGION_UNINIT(pscr, &rgnExposed); - return NULL; - } -} - -/* send GraphicsExpose events, or a NoExpose event, based on the region */ - -void -miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable, - int major, int minor) -{ - if (pRgn && !REGION_NIL(pRgn)) - { - xEvent *pEvent; - xEvent *pe; - BoxPtr pBox; - int i; - int numRects; - - numRects = REGION_NUM_RECTS(pRgn); - pBox = REGION_RECTS(pRgn); - if(!(pEvent = xalloc(numRects * sizeof(xEvent)))) - return; - pe = pEvent; - - for (i=1; i<=numRects; i++, pe++, pBox++) - { - pe->u.u.type = GraphicsExpose; - pe->u.graphicsExposure.drawable = drawable; - pe->u.graphicsExposure.x = pBox->x1; - pe->u.graphicsExposure.y = pBox->y1; - pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; - pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; - pe->u.graphicsExposure.count = numRects - i; - pe->u.graphicsExposure.majorEvent = major; - pe->u.graphicsExposure.minorEvent = minor; - } - TryClientEvents(client, NULL, pEvent, numRects, - (Mask)0, NoEventMask, NullGrab); - xfree(pEvent); - } - else - { - xEvent event; - memset(&event, 0, sizeof(xEvent)); - event.u.u.type = NoExpose; - event.u.noExposure.drawable = drawable; - event.u.noExposure.majorEvent = major; - event.u.noExposure.minorEvent = minor; - TryClientEvents(client, NULL, &event, 1, - (Mask)0, NoEventMask, NullGrab); - } -} - - -void -miSendExposures( WindowPtr pWin, RegionPtr pRgn, int dx, int dy) -{ - BoxPtr pBox; - int numRects; - xEvent *pEvent, *pe; - int i; - - pBox = REGION_RECTS(pRgn); - numRects = REGION_NUM_RECTS(pRgn); - if(!(pEvent = xcalloc(1, numRects * sizeof(xEvent)))) - return; - - for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) - { - pe->u.u.type = Expose; - pe->u.expose.window = pWin->drawable.id; - pe->u.expose.x = pBox->x1 - dx; - pe->u.expose.y = pBox->y1 - dy; - pe->u.expose.width = pBox->x2 - pBox->x1; - pe->u.expose.height = pBox->y2 - pBox->y1; - pe->u.expose.count = i; - } - -#ifdef PANORAMIX - if(!noPanoramiXExtension) { - int scrnum = pWin->drawable.pScreen->myNum; - int x = 0, y = 0; - XID realWin = 0; - - if(!pWin->parent) { - x = panoramiXdataPtr[scrnum].x; - y = panoramiXdataPtr[scrnum].y; - pWin = WindowTable[0]; - realWin = pWin->drawable.id; - } else if (scrnum) { - PanoramiXRes *win; - win = PanoramiXFindIDByScrnum(XRT_WINDOW, - pWin->drawable.id, scrnum); - if(!win) { - xfree(pEvent); - return; - } - realWin = win->info[0].id; - dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess); - } - if(x || y || scrnum) - for (i = 0; i < numRects; i++) { - pEvent[i].u.expose.window = realWin; - pEvent[i].u.expose.x += x; - pEvent[i].u.expose.y += y; - } - } -#endif - - DeliverEvents(pWin, pEvent, numRects, NullWindow); - - xfree(pEvent); -} - -void -miWindowExposures( WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed) -{ - RegionPtr exposures = prgn; - if ((prgn && !REGION_NIL(prgn)) || - (exposures && !REGION_NIL(exposures)) || other_exposed) - { - RegionRec expRec; - int clientInterested; - - /* - * Restore from backing-store FIRST. - */ - clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; - if (other_exposed) - { - if (exposures) - { - REGION_UNION(pWin->drawable.pScreen, other_exposed, - exposures, - other_exposed); - if (exposures != prgn) - REGION_DESTROY(pWin->drawable.pScreen, exposures); - } - exposures = other_exposed; - } - if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) - { - /* - * If we have LOTS of rectangles, we decide to take the extents - * and force an exposure on that. This should require much less - * work overall, on both client and server. This is cheating, but - * isn't prohibited by the protocol ("spontaneous combustion" :-). - */ - BoxRec box; - - box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); - if (exposures == prgn) { - exposures = &expRec; - REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); - REGION_RESET( pWin->drawable.pScreen, prgn, &box); - } else { - REGION_RESET( pWin->drawable.pScreen, exposures, &box); - REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); - } - /* PaintWindowBackground doesn't clip, so we have to */ - REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); - } - if (prgn && !REGION_NIL(prgn)) - miPaintWindow(pWin, prgn, PW_BACKGROUND); - if (clientInterested && exposures && !REGION_NIL(exposures)) - miSendExposures(pWin, exposures, - pWin->drawable.x, pWin->drawable.y); - if (exposures == &expRec) - { - REGION_UNINIT( pWin->drawable.pScreen, exposures); - } - else if (exposures && exposures != prgn && exposures != other_exposed) - REGION_DESTROY( pWin->drawable.pScreen, exposures); - if (prgn) - REGION_EMPTY( pWin->drawable.pScreen, prgn); - } - else if (exposures && exposures != prgn) - REGION_DESTROY( pWin->drawable.pScreen, exposures); -} - -#ifdef ROOTLESS -/* Ugly, ugly, but we lost our hooks into miPaintWindow... =/ */ -void RootlessSetPixmapOfAncestors(WindowPtr pWin); -void RootlessStartDrawing(WindowPtr pWin); -void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn); -Bool IsFramedWindow(WindowPtr pWin); -#endif - -void -miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - ChangeGCVal gcval[6]; - BITS32 gcmask; - GCPtr pGC; - int i; - BoxPtr pbox; - xRectangle *prect; - int numRects; - /* - * Distance from screen to destination drawable, use this - * to adjust rendering coordinates which come in in screen space - */ - int draw_x_off, draw_y_off; - /* - * Tile offset for drawing; these need to align the tile - * to the appropriate window origin - */ - int tile_x_off, tile_y_off; - PixUnion fill; - Bool solid = TRUE; - DrawablePtr drawable = &pWin->drawable; - -#ifdef ROOTLESS - if(!drawable || drawable->type == UNDRAWABLE_WINDOW) - return; - - if(IsFramedWindow(pWin)) { - RootlessStartDrawing(pWin); - RootlessDamageRegion(pWin, prgn); - - if(pWin->backgroundState == ParentRelative) { - if((what == PW_BACKGROUND) || - (what == PW_BORDER && !pWin->borderIsPixel)) - RootlessSetPixmapOfAncestors(pWin); - } - } -#endif - - if (what == PW_BACKGROUND) - { - while (pWin->backgroundState == ParentRelative) - pWin = pWin->parent; - - draw_x_off = drawable->x; - draw_y_off = drawable->y; - - tile_x_off = pWin->drawable.x - draw_x_off; - tile_y_off = pWin->drawable.y - draw_y_off; - fill = pWin->background; - switch (pWin->backgroundState) { - case None: - return; - case BackgroundPixmap: - solid = FALSE; - break; - } - } - else - { - PixmapPtr pixmap; - - tile_x_off = drawable->x; - tile_y_off = drawable->y; - - /* servers without pixmaps draw their own borders */ - if (!pScreen->GetWindowPixmap) - return; - pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable); - drawable = &pixmap->drawable; -#ifdef COMPOSITE - draw_x_off = pixmap->screen_x; - draw_y_off = pixmap->screen_y; - tile_x_off -= draw_x_off; - tile_y_off -= draw_y_off; -#else - draw_x_off = 0; - draw_y_off = 0; -#endif - fill = pWin->border; - solid = pWin->borderIsPixel; - } - - gcval[0].val = GXcopy; - gcmask = GCFunction; - -#ifdef ROOTLESS_SAFEALPHA -/* Bit mask for alpha channel with a particular number of bits per - * pixel. Note that we only care for 32bpp data. Mac OS X uses planar - * alpha for 16bpp. - */ -#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0) -#endif - - if (solid) - { -#ifdef ROOTLESS_SAFEALPHA - gcval[1].val = fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel); -#else - gcval[1].val = fill.pixel; -#endif - gcval[2].val = FillSolid; - gcmask |= GCForeground | GCFillStyle; - } - else - { - int c=1; -#ifdef ROOTLESS_SAFEALPHA - gcval[c++].val = ((CARD32)-1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel); - gcmask |= GCPlaneMask; -#endif - gcval[c++].val = FillTiled; - gcval[c++].ptr = (pointer)fill.pixmap; - gcval[c++].val = tile_x_off; - gcval[c++].val = tile_y_off; - gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin; - } - - prect = xalloc(REGION_NUM_RECTS(prgn) * sizeof(xRectangle)); - if (!prect) - return; - - pGC = GetScratchGC(drawable->depth, drawable->pScreen); - if (!pGC) - { - xfree(prect); - return; - } - - dixChangeGC (NullClient, pGC, gcmask, NULL, gcval); - ValidateGC (drawable, pGC); - - numRects = REGION_NUM_RECTS(prgn); - pbox = REGION_RECTS(prgn); - for (i= numRects; --i >= 0; pbox++, prect++) - { - prect->x = pbox->x1 - draw_x_off; - prect->y = pbox->y1 - draw_y_off; - prect->width = pbox->x2 - pbox->x1; - prect->height = pbox->y2 - pbox->y1; - } - prect -= numRects; - (*pGC->ops->PolyFillRect)(drawable, pGC, numRects, prect); - xfree(prect); - - FreeScratchGC(pGC); -} - - -/* MICLEARDRAWABLE -- sets the entire drawable to the background color of - * the GC. Useful when we have a scratch drawable and need to initialize - * it. */ -void -miClearDrawable(DrawablePtr pDraw, GCPtr pGC) -{ - XID fg = pGC->fgPixel; - XID bg = pGC->bgPixel; - xRectangle rect; - - rect.x = 0; - rect.y = 0; - rect.width = pDraw->width; - rect.height = pDraw->height; - DoChangeGC(pGC, GCForeground, &bg, 0); - ValidateGC(pDraw, pGC); - (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); - DoChangeGC(pGC, GCForeground, &fg, 0); - ValidateGC(pDraw, pGC); -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+******************************************************************/
+/*****************************************************************
+
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+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
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xprotostr.h>
+
+#include "misc.h"
+#include "regionstr.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "pixmap.h"
+#include "input.h"
+
+#include "dixstruct.h"
+#include "mi.h"
+#include <X11/Xmd.h>
+
+#include "globals.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+/*
+ machine-independent graphics exposure code. any device that uses
+the region package can call this.
+*/
+
+#ifndef RECTLIMIT
+#define RECTLIMIT 25 /* pick a number, any number > 8 */
+#endif
+
+/* miHandleExposures
+ generate a region for exposures for areas that were copied from obscured or
+non-existent areas to non-obscured areas of the destination. Paint the
+background for the region, if the destination is a window.
+
+NOTE:
+ this should generally be called, even if graphicsExposures is false,
+because this is where bits get recovered from backing store.
+
+NOTE:
+ added argument 'plane' is used to indicate how exposures from backing
+store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
+should be used, else a CopyPlane of the indicated plane will be used. The
+exposing is done by the backing store's GraphicsExpose function, of course.
+
+*/
+
+RegionPtr
+miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long plane)
+{
+ ScreenPtr pscr;
+ RegionPtr prgnSrcClip; /* drawable-relative source clip */
+ RegionRec rgnSrcRec;
+ RegionPtr prgnDstClip; /* drawable-relative dest clip */
+ RegionRec rgnDstRec;
+ BoxRec srcBox; /* unclipped source */
+ RegionRec rgnExposed; /* exposed region, calculated source-
+ relative, made dst relative to
+ intersect with visible parts of
+ dest and send events to client,
+ and then screen relative to paint
+ the window background
+ */
+ WindowPtr pSrcWin;
+ BoxRec expBox;
+ Bool extents;
+
+ /* This prevents warning about pscr not being used. */
+ pGC->pScreen = pscr = pGC->pScreen;
+
+ /* avoid work if we can */
+ if (!pGC->graphicsExposures &&
+ (pDstDrawable->type == DRAWABLE_PIXMAP) &&
+ ((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
+ (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
+ return NULL;
+
+ srcBox.x1 = srcx;
+ srcBox.y1 = srcy;
+ srcBox.x2 = srcx+width;
+ srcBox.y2 = srcy+height;
+
+ if (pSrcDrawable->type != DRAWABLE_PIXMAP)
+ {
+ BoxRec TsrcBox;
+
+ TsrcBox.x1 = srcx + pSrcDrawable->x;
+ TsrcBox.y1 = srcy + pSrcDrawable->y;
+ TsrcBox.x2 = TsrcBox.x1 + width;
+ TsrcBox.y2 = TsrcBox.y1 + height;
+ pSrcWin = (WindowPtr) pSrcDrawable;
+ if (pGC->subWindowMode == IncludeInferiors)
+ {
+ prgnSrcClip = NotClippedByChildren (pSrcWin);
+ if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN)
+ {
+ REGION_DESTROY(pscr, prgnSrcClip);
+ return NULL;
+ }
+ }
+ else
+ {
+ if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN)
+ return NULL;
+ prgnSrcClip = &rgnSrcRec;
+ REGION_NULL(pscr, prgnSrcClip);
+ REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList);
+ }
+ REGION_TRANSLATE(pscr, prgnSrcClip,
+ -pSrcDrawable->x, -pSrcDrawable->y);
+ }
+ else
+ {
+ BoxRec box;
+
+ if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
+ (srcBox.x2 <= pSrcDrawable->width) &&
+ (srcBox.y2 <= pSrcDrawable->height))
+ return NULL;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pSrcDrawable->width;
+ box.y2 = pSrcDrawable->height;
+ prgnSrcClip = &rgnSrcRec;
+ REGION_INIT(pscr, prgnSrcClip, &box, 1);
+ pSrcWin = NULL;
+ }
+
+ if (pDstDrawable == pSrcDrawable)
+ {
+ prgnDstClip = prgnSrcClip;
+ }
+ else if (pDstDrawable->type != DRAWABLE_PIXMAP)
+ {
+ if (pGC->subWindowMode == IncludeInferiors)
+ {
+ prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
+ }
+ else
+ {
+ prgnDstClip = &rgnDstRec;
+ REGION_NULL(pscr, prgnDstClip);
+ REGION_COPY(pscr, prgnDstClip,
+ &((WindowPtr)pDstDrawable)->clipList);
+ }
+ REGION_TRANSLATE(pscr, prgnDstClip,
+ -pDstDrawable->x, -pDstDrawable->y);
+ }
+ else
+ {
+ BoxRec box;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pDstDrawable->width;
+ box.y2 = pDstDrawable->height;
+ prgnDstClip = &rgnDstRec;
+ REGION_INIT(pscr, prgnDstClip, &box, 1);
+ }
+
+ /* drawable-relative source region */
+ REGION_INIT(pscr, &rgnExposed, &srcBox, 1);
+
+ /* now get the hidden parts of the source box*/
+ REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip);
+
+ /* move them over the destination */
+ REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy);
+
+ /* intersect with visible areas of dest */
+ REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip);
+
+ /* intersect with client clip region. */
+ if (pGC->clientClipType == CT_REGION)
+ REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, pGC->clientClip);
+
+ /*
+ * If we have LOTS of rectangles, we decide to take the extents
+ * and force an exposure on that. This should require much less
+ * work overall, on both client and server. This is cheating, but
+ * isn't prohibited by the protocol ("spontaneous combustion" :-)
+ * for windows.
+ */
+ extents = pGC->graphicsExposures &&
+ (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) &&
+ (pDstDrawable->type != DRAWABLE_PIXMAP);
+ if (pSrcWin)
+ {
+ RegionPtr region;
+ if (!(region = wClipShape (pSrcWin)))
+ region = wBoundingShape (pSrcWin);
+ /*
+ * If you try to CopyArea the extents of a shaped window, compacting the
+ * exposed region will undo all our work!
+ */
+ if (extents && pSrcWin && region &&
+ (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN))
+ extents = FALSE;
+ }
+ if (extents)
+ {
+ expBox = *REGION_EXTENTS(pscr, &rgnExposed);
+ REGION_RESET(pscr, &rgnExposed, &expBox);
+ }
+ if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
+ (((WindowPtr)pDstDrawable)->backgroundState != None))
+ {
+ WindowPtr pWin = (WindowPtr)pDstDrawable;
+
+ /* make the exposed area screen-relative */
+ REGION_TRANSLATE(pscr, &rgnExposed,
+ pDstDrawable->x, pDstDrawable->y);
+
+ if (extents)
+ {
+ /* miPaintWindow doesn't clip, so we have to */
+ REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList);
+ }
+ miPaintWindow((WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
+
+ if (extents)
+ {
+ REGION_RESET(pscr, &rgnExposed, &expBox);
+ }
+ else
+ REGION_TRANSLATE(pscr, &rgnExposed,
+ -pDstDrawable->x, -pDstDrawable->y);
+ }
+ if (prgnDstClip == &rgnDstRec)
+ {
+ REGION_UNINIT(pscr, prgnDstClip);
+ }
+ else if (prgnDstClip != prgnSrcClip)
+ {
+ REGION_DESTROY(pscr, prgnDstClip);
+ }
+
+ if (prgnSrcClip == &rgnSrcRec)
+ {
+ REGION_UNINIT(pscr, prgnSrcClip);
+ }
+ else
+ {
+ REGION_DESTROY(pscr, prgnSrcClip);
+ }
+
+ if (pGC->graphicsExposures)
+ {
+ /* don't look */
+ RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0);
+ *exposed = rgnExposed;
+ return exposed;
+ }
+ else
+ {
+ REGION_UNINIT(pscr, &rgnExposed);
+ return NULL;
+ }
+}
+
+/* send GraphicsExpose events, or a NoExpose event, based on the region */
+
+void
+miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable,
+ int major, int minor)
+{
+ if (pRgn && !REGION_NIL(pRgn))
+ {
+ xEvent *pEvent;
+ xEvent *pe;
+ BoxPtr pBox;
+ int i;
+ int numRects;
+
+ numRects = REGION_NUM_RECTS(pRgn);
+ pBox = REGION_RECTS(pRgn);
+ if(!(pEvent = malloc(numRects * sizeof(xEvent))))
+ return;
+ pe = pEvent;
+
+ for (i=1; i<=numRects; i++, pe++, pBox++)
+ {
+ pe->u.u.type = GraphicsExpose;
+ pe->u.graphicsExposure.drawable = drawable;
+ pe->u.graphicsExposure.x = pBox->x1;
+ pe->u.graphicsExposure.y = pBox->y1;
+ pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
+ pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
+ pe->u.graphicsExposure.count = numRects - i;
+ pe->u.graphicsExposure.majorEvent = major;
+ pe->u.graphicsExposure.minorEvent = minor;
+ }
+ TryClientEvents(client, NULL, pEvent, numRects,
+ (Mask)0, NoEventMask, NullGrab);
+ free(pEvent);
+ }
+ else
+ {
+ xEvent event;
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = NoExpose;
+ event.u.noExposure.drawable = drawable;
+ event.u.noExposure.majorEvent = major;
+ event.u.noExposure.minorEvent = minor;
+ TryClientEvents(client, NULL, &event, 1,
+ (Mask)0, NoEventMask, NullGrab);
+ }
+}
+
+
+void
+miSendExposures( WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
+{
+ BoxPtr pBox;
+ int numRects;
+ xEvent *pEvent, *pe;
+ int i;
+
+ pBox = REGION_RECTS(pRgn);
+ numRects = REGION_NUM_RECTS(pRgn);
+ if(!(pEvent = calloc(1, numRects * sizeof(xEvent))))
+ return;
+
+ for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
+ {
+ pe->u.u.type = Expose;
+ pe->u.expose.window = pWin->drawable.id;
+ pe->u.expose.x = pBox->x1 - dx;
+ pe->u.expose.y = pBox->y1 - dy;
+ pe->u.expose.width = pBox->x2 - pBox->x1;
+ pe->u.expose.height = pBox->y2 - pBox->y1;
+ pe->u.expose.count = i;
+ }
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ int scrnum = pWin->drawable.pScreen->myNum;
+ int x = 0, y = 0;
+ XID realWin = 0;
+
+ if(!pWin->parent) {
+ x = panoramiXdataPtr[scrnum].x;
+ y = panoramiXdataPtr[scrnum].y;
+ pWin = WindowTable[0];
+ realWin = pWin->drawable.id;
+ } else if (scrnum) {
+ PanoramiXRes *win;
+ win = PanoramiXFindIDByScrnum(XRT_WINDOW,
+ pWin->drawable.id, scrnum);
+ if(!win) {
+ free(pEvent);
+ return;
+ }
+ realWin = win->info[0].id;
+ dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess);
+ }
+ if(x || y || scrnum)
+ for (i = 0; i < numRects; i++) {
+ pEvent[i].u.expose.window = realWin;
+ pEvent[i].u.expose.x += x;
+ pEvent[i].u.expose.y += y;
+ }
+ }
+#endif
+
+ DeliverEvents(pWin, pEvent, numRects, NullWindow);
+
+ free(pEvent);
+}
+
+void
+miWindowExposures( WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
+{
+ RegionPtr exposures = prgn;
+ if ((prgn && !REGION_NIL(prgn)) ||
+ (exposures && !REGION_NIL(exposures)) || other_exposed)
+ {
+ RegionRec expRec;
+ int clientInterested;
+
+ /*
+ * Restore from backing-store FIRST.
+ */
+ clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
+ if (other_exposed)
+ {
+ if (exposures)
+ {
+ REGION_UNION(pWin->drawable.pScreen, other_exposed,
+ exposures,
+ other_exposed);
+ if (exposures != prgn)
+ REGION_DESTROY(pWin->drawable.pScreen, exposures);
+ }
+ exposures = other_exposed;
+ }
+ if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT))
+ {
+ /*
+ * If we have LOTS of rectangles, we decide to take the extents
+ * and force an exposure on that. This should require much less
+ * work overall, on both client and server. This is cheating, but
+ * isn't prohibited by the protocol ("spontaneous combustion" :-).
+ */
+ BoxRec box;
+
+ box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures);
+ if (exposures == prgn) {
+ exposures = &expRec;
+ REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1);
+ REGION_RESET( pWin->drawable.pScreen, prgn, &box);
+ } else {
+ REGION_RESET( pWin->drawable.pScreen, exposures, &box);
+ REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures);
+ }
+ /* miPaintWindow doesn't clip, so we have to */
+ REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList);
+ }
+ if (prgn && !REGION_NIL(prgn))
+ miPaintWindow(pWin, prgn, PW_BACKGROUND);
+ if (clientInterested && exposures && !REGION_NIL(exposures))
+ miSendExposures(pWin, exposures,
+ pWin->drawable.x, pWin->drawable.y);
+ if (exposures == &expRec)
+ {
+ REGION_UNINIT( pWin->drawable.pScreen, exposures);
+ }
+ else if (exposures && exposures != prgn && exposures != other_exposed)
+ REGION_DESTROY( pWin->drawable.pScreen, exposures);
+ if (prgn)
+ REGION_EMPTY( pWin->drawable.pScreen, prgn);
+ }
+ else if (exposures && exposures != prgn)
+ REGION_DESTROY( pWin->drawable.pScreen, exposures);
+}
+
+#ifdef ROOTLESS
+/* Ugly, ugly, but we lost our hooks into miPaintWindow... =/ */
+void RootlessSetPixmapOfAncestors(WindowPtr pWin);
+void RootlessStartDrawing(WindowPtr pWin);
+void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
+Bool IsFramedWindow(WindowPtr pWin);
+#endif
+
+void
+miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ChangeGCVal gcval[6];
+ BITS32 gcmask;
+ GCPtr pGC;
+ int i;
+ BoxPtr pbox;
+ xRectangle *prect;
+ int numRects;
+ /*
+ * Distance from screen to destination drawable, use this
+ * to adjust rendering coordinates which come in in screen space
+ */
+ int draw_x_off, draw_y_off;
+ /*
+ * Tile offset for drawing; these need to align the tile
+ * to the appropriate window origin
+ */
+ int tile_x_off, tile_y_off;
+ PixUnion fill;
+ Bool solid = TRUE;
+ DrawablePtr drawable = &pWin->drawable;
+
+#ifdef ROOTLESS
+ if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
+ return;
+
+ if(IsFramedWindow(pWin)) {
+ RootlessStartDrawing(pWin);
+ RootlessDamageRegion(pWin, prgn);
+
+ if(pWin->backgroundState == ParentRelative) {
+ if((what == PW_BACKGROUND) ||
+ (what == PW_BORDER && !pWin->borderIsPixel))
+ RootlessSetPixmapOfAncestors(pWin);
+ }
+ }
+#endif
+
+ if (what == PW_BACKGROUND)
+ {
+ while (pWin->backgroundState == ParentRelative)
+ pWin = pWin->parent;
+
+ draw_x_off = drawable->x;
+ draw_y_off = drawable->y;
+
+ tile_x_off = pWin->drawable.x - draw_x_off;
+ tile_y_off = pWin->drawable.y - draw_y_off;
+ fill = pWin->background;
+ switch (pWin->backgroundState) {
+ case None:
+ return;
+ case BackgroundPixmap:
+ solid = FALSE;
+ break;
+ }
+ }
+ else
+ {
+ PixmapPtr pixmap;
+
+ tile_x_off = drawable->x;
+ tile_y_off = drawable->y;
+
+ /* servers without pixmaps draw their own borders */
+ if (!pScreen->GetWindowPixmap)
+ return;
+ pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
+ drawable = &pixmap->drawable;
+#ifdef COMPOSITE
+ draw_x_off = pixmap->screen_x;
+ draw_y_off = pixmap->screen_y;
+ tile_x_off -= draw_x_off;
+ tile_y_off -= draw_y_off;
+#else
+ draw_x_off = 0;
+ draw_y_off = 0;
+#endif
+ fill = pWin->border;
+ solid = pWin->borderIsPixel;
+ }
+
+ gcval[0].val = GXcopy;
+ gcmask = GCFunction;
+
+#ifdef ROOTLESS_SAFEALPHA
+/* Bit mask for alpha channel with a particular number of bits per
+ * pixel. Note that we only care for 32bpp data. Mac OS X uses planar
+ * alpha for 16bpp.
+ */
+#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
+#endif
+
+ if (solid)
+ {
+#ifdef ROOTLESS_SAFEALPHA
+ gcval[1].val = fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
+#else
+ gcval[1].val = fill.pixel;
+#endif
+ gcval[2].val = FillSolid;
+ gcmask |= GCForeground | GCFillStyle;
+ }
+ else
+ {
+ int c=1;
+#ifdef ROOTLESS_SAFEALPHA
+ gcval[c++].val = ((CARD32)-1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel);
+ gcmask |= GCPlaneMask;
+#endif
+ gcval[c++].val = FillTiled;
+ gcval[c++].ptr = (pointer)fill.pixmap;
+ gcval[c++].val = tile_x_off;
+ gcval[c++].val = tile_y_off;
+ gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
+ }
+
+ prect = malloc(REGION_NUM_RECTS(prgn) * sizeof(xRectangle));
+ if (!prect)
+ return;
+
+ pGC = GetScratchGC(drawable->depth, drawable->pScreen);
+ if (!pGC)
+ {
+ free(prect);
+ return;
+ }
+
+ ChangeGC (NullClient, pGC, gcmask, gcval);
+ ValidateGC (drawable, pGC);
+
+ numRects = REGION_NUM_RECTS(prgn);
+ pbox = REGION_RECTS(prgn);
+ for (i= numRects; --i >= 0; pbox++, prect++)
+ {
+ prect->x = pbox->x1 - draw_x_off;
+ prect->y = pbox->y1 - draw_y_off;
+ prect->width = pbox->x2 - pbox->x1;
+ prect->height = pbox->y2 - pbox->y1;
+ }
+ prect -= numRects;
+ (*pGC->ops->PolyFillRect)(drawable, pGC, numRects, prect);
+ free(prect);
+
+ FreeScratchGC(pGC);
+}
+
+
+/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
+ * the GC. Useful when we have a scratch drawable and need to initialize
+ * it. */
+void
+miClearDrawable(DrawablePtr pDraw, GCPtr pGC)
+{
+ ChangeGCVal fg, bg;
+ xRectangle rect;
+
+ fg.val = pGC->fgPixel;
+ bg.val = pGC->bgPixel;
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = pDraw->width;
+ rect.height = pDraw->height;
+ ChangeGC(NullClient, pGC, GCForeground, &bg);
+ ValidateGC(pDraw, pGC);
+ (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
+ ChangeGC(NullClient, pGC, GCForeground, &fg);
+ ValidateGC(pDraw, pGC);
+}
diff --git a/xorg-server/mi/mifillarc.c b/xorg-server/mi/mifillarc.c index c22baf54c..dd0a7b91d 100644 --- a/xorg-server/mi/mifillarc.c +++ b/xorg-server/mi/mifillarc.c @@ -1,798 +1,798 @@ -/************************************************************ - -Copyright 1989, 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. - -Author: Bob Scheifler, MIT X Consortium - -********************************************************/ - - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <math.h> -#include <X11/X.h> -#include <X11/Xprotostr.h> -#include "regionstr.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "mifpoly.h" -#include "mi.h" -#include "mifillarc.h" - -#define QUADRANT (90 * 64) -#define HALFCIRCLE (180 * 64) -#define QUADRANT3 (270 * 64) - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define Dsin(d) sin((double)d*(M_PI/11520.0)) -#define Dcos(d) cos((double)d*(M_PI/11520.0)) - -void -miFillArcSetup(xArc *arc, miFillArcRec *info) -{ - info->y = arc->height >> 1; - info->dy = arc->height & 1; - info->yorg = arc->y + info->y; - info->dx = arc->width & 1; - info->xorg = arc->x + (arc->width >> 1) + info->dx; - info->dx = 1 - info->dx; - if (arc->width == arc->height) - { - /* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */ - /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ - info->ym = 8; - info->xm = 8; - info->yk = info->y << 3; - if (!info->dx) - { - info->xk = 0; - info->e = -1; - } - else - { - info->y++; - info->yk += 4; - info->xk = -4; - info->e = - (info->y << 3); - } - } - else - { - /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ - /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ - info->ym = (arc->width * arc->width) << 3; - info->xm = (arc->height * arc->height) << 3; - info->yk = info->y * info->ym; - if (!info->dy) - info->yk -= info->ym >> 1; - if (!info->dx) - { - info->xk = 0; - info->e = - (info->xm >> 3); - } - else - { - info->y++; - info->yk += info->ym; - info->xk = -(info->xm >> 1); - info->e = info->xk - info->yk; - } - } -} - -static void -miFillArcDSetup(xArc *arc, miFillArcDRec *info) -{ - /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ - /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ - info->y = arc->height >> 1; - info->dy = arc->height & 1; - info->yorg = arc->y + info->y; - info->dx = arc->width & 1; - info->xorg = arc->x + (arc->width >> 1) + info->dx; - info->dx = 1 - info->dx; - info->ym = ((double)arc->width) * (arc->width * 8); - info->xm = ((double)arc->height) * (arc->height * 8); - info->yk = info->y * info->ym; - if (!info->dy) - info->yk -= info->ym / 2.0; - if (!info->dx) - { - info->xk = 0; - info->e = - (info->xm / 8.0); - } - else - { - info->y++; - info->yk += info->ym; - info->xk = -info->xm / 2.0; - info->e = info->xk - info->yk; - } -} - -static void -miGetArcEdge( - xArc *arc, - miSliceEdgePtr edge, - int k, - Bool top, - Bool left ) -{ - int xady, y; - - y = arc->height >> 1; - if (!(arc->width & 1)) - y++; - if (!top) - { - y = -y; - if (arc->height & 1) - y--; - } - xady = k + y * edge->dx; - if (xady <= 0) - edge->x = - ((-xady) / edge->dy + 1); - else - edge->x = (xady - 1) / edge->dy; - edge->e = xady - edge->x * edge->dy; - if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0))) - edge->e = edge->dy - edge->e + 1; - if (left) - edge->x++; - edge->x += arc->x + (arc->width >> 1); - if (edge->dx > 0) - { - edge->deltax = 1; - edge->stepx = edge->dx / edge->dy; - edge->dx = edge->dx % edge->dy; - } - else - { - edge->deltax = -1; - edge->stepx = - ((-edge->dx) / edge->dy); - edge->dx = (-edge->dx) % edge->dy; - } - if (!top) - { - edge->deltax = -edge->deltax; - edge->stepx = -edge->stepx; - } -} - -static void -miEllipseAngleToSlope (int angle, int width, int height, int *dxp, int *dyp, - double *d_dxp, double *d_dyp) -{ - int dx, dy; - double d_dx, d_dy, scale; - Bool negative_dx, negative_dy; - - switch (angle) { - case 0: - *dxp = -1; - *dyp = 0; - if (d_dxp) { - *d_dxp = width / 2.0; - *d_dyp = 0; - } - break; - case QUADRANT: - *dxp = 0; - *dyp = 1; - if (d_dxp) { - *d_dxp = 0; - *d_dyp = - height / 2.0; - } - break; - case HALFCIRCLE: - *dxp = 1; - *dyp = 0; - if (d_dxp) { - *d_dxp = - width / 2.0; - *d_dyp = 0; - } - break; - case QUADRANT3: - *dxp = 0; - *dyp = -1; - if (d_dxp) { - *d_dxp = 0; - *d_dyp = height / 2.0; - } - break; - default: - d_dx = Dcos(angle) * width; - d_dy = Dsin(angle) * height; - if (d_dxp) { - *d_dxp = d_dx / 2.0; - *d_dyp = - d_dy / 2.0; - } - negative_dx = FALSE; - if (d_dx < 0.0) - { - d_dx = -d_dx; - negative_dx = TRUE; - } - negative_dy = FALSE; - if (d_dy < 0.0) - { - d_dy = -d_dy; - negative_dy = TRUE; - } - scale = d_dx; - if (d_dy > d_dx) - scale = d_dy; - dx = floor ((d_dx * 32768) / scale + 0.5); - if (negative_dx) - dx = -dx; - *dxp = dx; - dy = floor ((d_dy * 32768) / scale + 0.5); - if (negative_dy) - dy = -dy; - *dyp = dy; - break; - } -} - -static void -miGetPieEdge( - xArc *arc, - int angle, - miSliceEdgePtr edge, - Bool top, - Bool left ) -{ - int k; - int dx, dy; - - miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0); - - if (dy == 0) - { - edge->x = left ? -65536 : 65536; - edge->stepx = 0; - edge->e = 0; - edge->dx = -1; - return; - } - if (dx == 0) - { - edge->x = arc->x + (arc->width >> 1); - if (left && (arc->width & 1)) - edge->x++; - else if (!left && !(arc->width & 1)) - edge->x--; - edge->stepx = 0; - edge->e = 0; - edge->dx = -1; - return; - } - if (dy < 0) { - dx = -dx; - dy = -dy; - } - k = (arc->height & 1) ? dx : 0; - if (arc->width & 1) - k += dy; - edge->dx = dx << 1; - edge->dy = dy << 1; - miGetArcEdge(arc, edge, k, top, left); -} - -void -miFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC) -{ - int angle1, angle2; - - angle1 = arc->angle1; - if (arc->angle2 < 0) - { - angle2 = angle1; - angle1 += arc->angle2; - } - else - angle2 = angle1 + arc->angle2; - while (angle1 < 0) - angle1 += FULLCIRCLE; - while (angle1 >= FULLCIRCLE) - angle1 -= FULLCIRCLE; - while (angle2 < 0) - angle2 += FULLCIRCLE; - while (angle2 >= FULLCIRCLE) - angle2 -= FULLCIRCLE; - slice->min_top_y = 0; - slice->max_top_y = arc->height >> 1; - slice->min_bot_y = 1 - (arc->height & 1); - slice->max_bot_y = slice->max_top_y - 1; - slice->flip_top = FALSE; - slice->flip_bot = FALSE; - if (pGC->arcMode == ArcPieSlice) - { - slice->edge1_top = (angle1 < HALFCIRCLE); - slice->edge2_top = (angle2 <= HALFCIRCLE); - if ((angle2 == 0) || (angle1 == HALFCIRCLE)) - { - if (angle2 ? slice->edge2_top : slice->edge1_top) - slice->min_top_y = slice->min_bot_y; - else - slice->min_top_y = arc->height; - slice->min_bot_y = 0; - } - else if ((angle1 == 0) || (angle2 == HALFCIRCLE)) - { - slice->min_top_y = slice->min_bot_y; - if (angle1 ? slice->edge1_top : slice->edge2_top) - slice->min_bot_y = arc->height; - else - slice->min_bot_y = 0; - } - else if (slice->edge1_top == slice->edge2_top) - { - if (angle2 < angle1) - { - slice->flip_top = slice->edge1_top; - slice->flip_bot = !slice->edge1_top; - } - else if (slice->edge1_top) - { - slice->min_top_y = 1; - slice->min_bot_y = arc->height; - } - else - { - slice->min_bot_y = 0; - slice->min_top_y = arc->height; - } - } - miGetPieEdge(arc, angle1, &slice->edge1, - slice->edge1_top, !slice->edge1_top); - miGetPieEdge(arc, angle2, &slice->edge2, - slice->edge2_top, slice->edge2_top); - } - else - { - double w2, h2, x1, y1, x2, y2, dx, dy, scale; - int signdx, signdy, y, k; - Bool isInt1 = TRUE, isInt2 = TRUE; - - w2 = (double)arc->width / 2.0; - h2 = (double)arc->height / 2.0; - if ((angle1 == 0) || (angle1 == HALFCIRCLE)) - { - x1 = angle1 ? -w2 : w2; - y1 = 0.0; - } - else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3)) - { - x1 = 0.0; - y1 = (angle1 == QUADRANT) ? h2 : -h2; - } - else - { - isInt1 = FALSE; - x1 = Dcos(angle1) * w2; - y1 = Dsin(angle1) * h2; - } - if ((angle2 == 0) || (angle2 == HALFCIRCLE)) - { - x2 = angle2 ? -w2 : w2; - y2 = 0.0; - } - else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3)) - { - x2 = 0.0; - y2 = (angle2 == QUADRANT) ? h2 : -h2; - } - else - { - isInt2 = FALSE; - x2 = Dcos(angle2) * w2; - y2 = Dsin(angle2) * h2; - } - dx = x2 - x1; - dy = y2 - y1; - if (arc->height & 1) - { - y1 -= 0.5; - y2 -= 0.5; - } - if (arc->width & 1) - { - x1 += 0.5; - x2 += 0.5; - } - if (dy < 0.0) - { - dy = -dy; - signdy = -1; - } - else - signdy = 1; - if (dx < 0.0) - { - dx = -dx; - signdx = -1; - } - else - signdx = 1; - if (isInt1 && isInt2) - { - slice->edge1.dx = dx * 2; - slice->edge1.dy = dy * 2; - } - else - { - scale = (dx > dy) ? dx : dy; - slice->edge1.dx = floor((dx * 32768) / scale + .5); - slice->edge1.dy = floor((dy * 32768) / scale + .5); - } - if (!slice->edge1.dy) - { - if (signdx < 0) - { - y = floor(y1 + 1.0); - if (y >= 0) - { - slice->min_top_y = y; - slice->min_bot_y = arc->height; - } - else - { - slice->max_bot_y = -y - (arc->height & 1); - } - } - else - { - y = floor(y1); - if (y >= 0) - slice->max_top_y = y; - else - { - slice->min_top_y = arc->height; - slice->min_bot_y = -y - (arc->height & 1); - } - } - slice->edge1_top = TRUE; - slice->edge1.x = 65536; - slice->edge1.stepx = 0; - slice->edge1.e = 0; - slice->edge1.dx = -1; - slice->edge2 = slice->edge1; - slice->edge2_top = FALSE; - } - else if (!slice->edge1.dx) - { - if (signdy < 0) - x1 -= 1.0; - slice->edge1.x = ceil(x1); - slice->edge1_top = signdy < 0; - slice->edge1.x += arc->x + (arc->width >> 1); - slice->edge1.stepx = 0; - slice->edge1.e = 0; - slice->edge1.dx = -1; - slice->edge2_top = !slice->edge1_top; - slice->edge2 = slice->edge1; - } - else - { - if (signdx < 0) - slice->edge1.dx = -slice->edge1.dx; - if (signdy < 0) - slice->edge1.dx = -slice->edge1.dx; - k = ceil(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0); - slice->edge2.dx = slice->edge1.dx; - slice->edge2.dy = slice->edge1.dy; - slice->edge1_top = signdy < 0; - slice->edge2_top = !slice->edge1_top; - miGetArcEdge(arc, &slice->edge1, k, - slice->edge1_top, !slice->edge1_top); - miGetArcEdge(arc, &slice->edge2, k, - slice->edge2_top, slice->edge2_top); - } - } -} - -#define ADDSPANS() \ - pts->x = xorg - x; \ - pts->y = yorg - y; \ - *wids = slw; \ - pts++; \ - wids++; \ - if (miFillArcLower(slw)) \ - { \ - pts->x = xorg - x; \ - pts->y = yorg + y + dy; \ - pts++; \ - *wids++ = slw; \ - } - -static void -miFillEllipseI( - DrawablePtr pDraw, - GCPtr pGC, - xArc *arc ) -{ - int x, y, e; - int yk, xk, ym, xm, dx, dy, xorg, yorg; - int slw; - miFillArcRec info; - DDXPointPtr points; - DDXPointPtr pts; - int *widths; - int *wids; - - points = xalloc(sizeof(DDXPointRec) * arc->height); - if (!points) - return; - widths = xalloc(sizeof(int) * arc->height); - if (!widths) - { - xfree(points); - return; - } - miFillArcSetup(arc, &info); - MIFILLARCSETUP(); - if (pGC->miTranslate) - { - xorg += pDraw->x; - yorg += pDraw->y; - } - pts = points; - wids = widths; - while (y > 0) - { - MIFILLARCSTEP(slw); - ADDSPANS(); - } - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); - xfree(widths); - xfree(points); -} - -static void -miFillEllipseD( - DrawablePtr pDraw, - GCPtr pGC, - xArc *arc ) -{ - int x, y; - int xorg, yorg, dx, dy, slw; - double e, yk, xk, ym, xm; - miFillArcDRec info; - DDXPointPtr points; - DDXPointPtr pts; - int *widths; - int *wids; - - points = xalloc(sizeof(DDXPointRec) * arc->height); - if (!points) - return; - widths = xalloc(sizeof(int) * arc->height); - if (!widths) - { - xfree(points); - return; - } - miFillArcDSetup(arc, &info); - MIFILLARCSETUP(); - if (pGC->miTranslate) - { - xorg += pDraw->x; - yorg += pDraw->y; - } - pts = points; - wids = widths; - while (y > 0) - { - MIFILLARCSTEP(slw); - ADDSPANS(); - } - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); - xfree(widths); - xfree(points); -} - -#define ADDSPAN(l,r) \ - if (r >= l) \ - { \ - pts->x = l; \ - pts->y = ya; \ - pts++; \ - *wids++ = r - l + 1; \ - } - -#define ADDSLICESPANS(flip) \ - if (!flip) \ - { \ - ADDSPAN(xl, xr); \ - } \ - else \ - { \ - xc = xorg - x; \ - ADDSPAN(xc, xr); \ - xc += slw - 1; \ - ADDSPAN(xl, xc); \ - } - -static void -miFillArcSliceI( - DrawablePtr pDraw, - GCPtr pGC, - xArc *arc ) -{ - int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; - int x, y, e; - miFillArcRec info; - miArcSliceRec slice; - int ya, xl, xr, xc; - DDXPointPtr points; - DDXPointPtr pts; - int *widths; - int *wids; - - miFillArcSetup(arc, &info); - miFillArcSliceSetup(arc, &slice, pGC); - MIFILLARCSETUP(); - slw = arc->height; - if (slice.flip_top || slice.flip_bot) - slw += (arc->height >> 1) + 1; - points = xalloc(sizeof(DDXPointRec) * slw); - if (!points) - return; - widths = xalloc(sizeof(int) * slw); - if (!widths) - { - xfree(points); - return; - } - if (pGC->miTranslate) - { - xorg += pDraw->x; - yorg += pDraw->y; - slice.edge1.x += pDraw->x; - slice.edge2.x += pDraw->x; - } - pts = points; - wids = widths; - while (y > 0) - { - MIFILLARCSTEP(slw); - MIARCSLICESTEP(slice.edge1); - MIARCSLICESTEP(slice.edge2); - if (miFillSliceUpper(slice)) - { - ya = yorg - y; - MIARCSLICEUPPER(xl, xr, slice, slw); - ADDSLICESPANS(slice.flip_top); - } - if (miFillSliceLower(slice)) - { - ya = yorg + y + dy; - MIARCSLICELOWER(xl, xr, slice, slw); - ADDSLICESPANS(slice.flip_bot); - } - } - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); - xfree(widths); - xfree(points); -} - -static void -miFillArcSliceD( - DrawablePtr pDraw, - GCPtr pGC, - xArc *arc ) -{ - int x, y; - int dx, dy, xorg, yorg, slw; - double e, yk, xk, ym, xm; - miFillArcDRec info; - miArcSliceRec slice; - int ya, xl, xr, xc; - DDXPointPtr points; - DDXPointPtr pts; - int *widths; - int *wids; - - miFillArcDSetup(arc, &info); - miFillArcSliceSetup(arc, &slice, pGC); - MIFILLARCSETUP(); - slw = arc->height; - if (slice.flip_top || slice.flip_bot) - slw += (arc->height >> 1) + 1; - points = xalloc(sizeof(DDXPointRec) * slw); - if (!points) - return; - widths = xalloc(sizeof(int) * slw); - if (!widths) - { - xfree(points); - return; - } - if (pGC->miTranslate) - { - xorg += pDraw->x; - yorg += pDraw->y; - slice.edge1.x += pDraw->x; - slice.edge2.x += pDraw->x; - } - pts = points; - wids = widths; - while (y > 0) - { - MIFILLARCSTEP(slw); - MIARCSLICESTEP(slice.edge1); - MIARCSLICESTEP(slice.edge2); - if (miFillSliceUpper(slice)) - { - ya = yorg - y; - MIARCSLICEUPPER(xl, xr, slice, slw); - ADDSLICESPANS(slice.flip_top); - } - if (miFillSliceLower(slice)) - { - ya = yorg + y + dy; - MIARCSLICELOWER(xl, xr, slice, slw); - ADDSLICESPANS(slice.flip_bot); - } - } - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); - xfree(widths); - xfree(points); -} - -/* MIPOLYFILLARC -- The public entry for the PolyFillArc request. - * Since we don't have to worry about overlapping segments, we can just - * fill each arc as it comes. - */ -void -miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) -{ - int i; - xArc *arc; - - for(i = narcs, arc = parcs; --i >= 0; arc++) - { - if (miFillArcEmpty(arc)) - continue; - if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) - { - if (miCanFillArc(arc)) - miFillEllipseI(pDraw, pGC, arc); - else - miFillEllipseD(pDraw, pGC, arc); - } - else - { - if (miCanFillArc(arc)) - miFillArcSliceI(pDraw, pGC, arc); - else - miFillArcSliceD(pDraw, pGC, arc); - } - } -} +/************************************************************
+
+Copyright 1989, 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.
+
+Author: Bob Scheifler, MIT X Consortium
+
+********************************************************/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <math.h>
+#include <X11/X.h>
+#include <X11/Xprotostr.h>
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "mifpoly.h"
+#include "mi.h"
+#include "mifillarc.h"
+
+#define QUADRANT (90 * 64)
+#define HALFCIRCLE (180 * 64)
+#define QUADRANT3 (270 * 64)
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define Dsin(d) sin((double)d*(M_PI/11520.0))
+#define Dcos(d) cos((double)d*(M_PI/11520.0))
+
+void
+miFillArcSetup(xArc *arc, miFillArcRec *info)
+{
+ info->y = arc->height >> 1;
+ info->dy = arc->height & 1;
+ info->yorg = arc->y + info->y;
+ info->dx = arc->width & 1;
+ info->xorg = arc->x + (arc->width >> 1) + info->dx;
+ info->dx = 1 - info->dx;
+ if (arc->width == arc->height)
+ {
+ /* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */
+ /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
+ info->ym = 8;
+ info->xm = 8;
+ info->yk = info->y << 3;
+ if (!info->dx)
+ {
+ info->xk = 0;
+ info->e = -1;
+ }
+ else
+ {
+ info->y++;
+ info->yk += 4;
+ info->xk = -4;
+ info->e = - (info->y << 3);
+ }
+ }
+ else
+ {
+ /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
+ /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
+ info->ym = (arc->width * arc->width) << 3;
+ info->xm = (arc->height * arc->height) << 3;
+ info->yk = info->y * info->ym;
+ if (!info->dy)
+ info->yk -= info->ym >> 1;
+ if (!info->dx)
+ {
+ info->xk = 0;
+ info->e = - (info->xm >> 3);
+ }
+ else
+ {
+ info->y++;
+ info->yk += info->ym;
+ info->xk = -(info->xm >> 1);
+ info->e = info->xk - info->yk;
+ }
+ }
+}
+
+static void
+miFillArcDSetup(xArc *arc, miFillArcDRec *info)
+{
+ /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
+ /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
+ info->y = arc->height >> 1;
+ info->dy = arc->height & 1;
+ info->yorg = arc->y + info->y;
+ info->dx = arc->width & 1;
+ info->xorg = arc->x + (arc->width >> 1) + info->dx;
+ info->dx = 1 - info->dx;
+ info->ym = ((double)arc->width) * (arc->width * 8);
+ info->xm = ((double)arc->height) * (arc->height * 8);
+ info->yk = info->y * info->ym;
+ if (!info->dy)
+ info->yk -= info->ym / 2.0;
+ if (!info->dx)
+ {
+ info->xk = 0;
+ info->e = - (info->xm / 8.0);
+ }
+ else
+ {
+ info->y++;
+ info->yk += info->ym;
+ info->xk = -info->xm / 2.0;
+ info->e = info->xk - info->yk;
+ }
+}
+
+static void
+miGetArcEdge(
+ xArc *arc,
+ miSliceEdgePtr edge,
+ int k,
+ Bool top,
+ Bool left )
+{
+ int xady, y;
+
+ y = arc->height >> 1;
+ if (!(arc->width & 1))
+ y++;
+ if (!top)
+ {
+ y = -y;
+ if (arc->height & 1)
+ y--;
+ }
+ xady = k + y * edge->dx;
+ if (xady <= 0)
+ edge->x = - ((-xady) / edge->dy + 1);
+ else
+ edge->x = (xady - 1) / edge->dy;
+ edge->e = xady - edge->x * edge->dy;
+ if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0)))
+ edge->e = edge->dy - edge->e + 1;
+ if (left)
+ edge->x++;
+ edge->x += arc->x + (arc->width >> 1);
+ if (edge->dx > 0)
+ {
+ edge->deltax = 1;
+ edge->stepx = edge->dx / edge->dy;
+ edge->dx = edge->dx % edge->dy;
+ }
+ else
+ {
+ edge->deltax = -1;
+ edge->stepx = - ((-edge->dx) / edge->dy);
+ edge->dx = (-edge->dx) % edge->dy;
+ }
+ if (!top)
+ {
+ edge->deltax = -edge->deltax;
+ edge->stepx = -edge->stepx;
+ }
+}
+
+static void
+miEllipseAngleToSlope (int angle, int width, int height, int *dxp, int *dyp,
+ double *d_dxp, double *d_dyp)
+{
+ int dx, dy;
+ double d_dx, d_dy, scale;
+ Bool negative_dx, negative_dy;
+
+ switch (angle) {
+ case 0:
+ *dxp = -1;
+ *dyp = 0;
+ if (d_dxp) {
+ *d_dxp = width / 2.0;
+ *d_dyp = 0;
+ }
+ break;
+ case QUADRANT:
+ *dxp = 0;
+ *dyp = 1;
+ if (d_dxp) {
+ *d_dxp = 0;
+ *d_dyp = - height / 2.0;
+ }
+ break;
+ case HALFCIRCLE:
+ *dxp = 1;
+ *dyp = 0;
+ if (d_dxp) {
+ *d_dxp = - width / 2.0;
+ *d_dyp = 0;
+ }
+ break;
+ case QUADRANT3:
+ *dxp = 0;
+ *dyp = -1;
+ if (d_dxp) {
+ *d_dxp = 0;
+ *d_dyp = height / 2.0;
+ }
+ break;
+ default:
+ d_dx = Dcos(angle) * width;
+ d_dy = Dsin(angle) * height;
+ if (d_dxp) {
+ *d_dxp = d_dx / 2.0;
+ *d_dyp = - d_dy / 2.0;
+ }
+ negative_dx = FALSE;
+ if (d_dx < 0.0)
+ {
+ d_dx = -d_dx;
+ negative_dx = TRUE;
+ }
+ negative_dy = FALSE;
+ if (d_dy < 0.0)
+ {
+ d_dy = -d_dy;
+ negative_dy = TRUE;
+ }
+ scale = d_dx;
+ if (d_dy > d_dx)
+ scale = d_dy;
+ dx = floor ((d_dx * 32768) / scale + 0.5);
+ if (negative_dx)
+ dx = -dx;
+ *dxp = dx;
+ dy = floor ((d_dy * 32768) / scale + 0.5);
+ if (negative_dy)
+ dy = -dy;
+ *dyp = dy;
+ break;
+ }
+}
+
+static void
+miGetPieEdge(
+ xArc *arc,
+ int angle,
+ miSliceEdgePtr edge,
+ Bool top,
+ Bool left )
+{
+ int k;
+ int dx, dy;
+
+ miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0);
+
+ if (dy == 0)
+ {
+ edge->x = left ? -65536 : 65536;
+ edge->stepx = 0;
+ edge->e = 0;
+ edge->dx = -1;
+ return;
+ }
+ if (dx == 0)
+ {
+ edge->x = arc->x + (arc->width >> 1);
+ if (left && (arc->width & 1))
+ edge->x++;
+ else if (!left && !(arc->width & 1))
+ edge->x--;
+ edge->stepx = 0;
+ edge->e = 0;
+ edge->dx = -1;
+ return;
+ }
+ if (dy < 0) {
+ dx = -dx;
+ dy = -dy;
+ }
+ k = (arc->height & 1) ? dx : 0;
+ if (arc->width & 1)
+ k += dy;
+ edge->dx = dx << 1;
+ edge->dy = dy << 1;
+ miGetArcEdge(arc, edge, k, top, left);
+}
+
+void
+miFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC)
+{
+ int angle1, angle2;
+
+ angle1 = arc->angle1;
+ if (arc->angle2 < 0)
+ {
+ angle2 = angle1;
+ angle1 += arc->angle2;
+ }
+ else
+ angle2 = angle1 + arc->angle2;
+ while (angle1 < 0)
+ angle1 += FULLCIRCLE;
+ while (angle1 >= FULLCIRCLE)
+ angle1 -= FULLCIRCLE;
+ while (angle2 < 0)
+ angle2 += FULLCIRCLE;
+ while (angle2 >= FULLCIRCLE)
+ angle2 -= FULLCIRCLE;
+ slice->min_top_y = 0;
+ slice->max_top_y = arc->height >> 1;
+ slice->min_bot_y = 1 - (arc->height & 1);
+ slice->max_bot_y = slice->max_top_y - 1;
+ slice->flip_top = FALSE;
+ slice->flip_bot = FALSE;
+ if (pGC->arcMode == ArcPieSlice)
+ {
+ slice->edge1_top = (angle1 < HALFCIRCLE);
+ slice->edge2_top = (angle2 <= HALFCIRCLE);
+ if ((angle2 == 0) || (angle1 == HALFCIRCLE))
+ {
+ if (angle2 ? slice->edge2_top : slice->edge1_top)
+ slice->min_top_y = slice->min_bot_y;
+ else
+ slice->min_top_y = arc->height;
+ slice->min_bot_y = 0;
+ }
+ else if ((angle1 == 0) || (angle2 == HALFCIRCLE))
+ {
+ slice->min_top_y = slice->min_bot_y;
+ if (angle1 ? slice->edge1_top : slice->edge2_top)
+ slice->min_bot_y = arc->height;
+ else
+ slice->min_bot_y = 0;
+ }
+ else if (slice->edge1_top == slice->edge2_top)
+ {
+ if (angle2 < angle1)
+ {
+ slice->flip_top = slice->edge1_top;
+ slice->flip_bot = !slice->edge1_top;
+ }
+ else if (slice->edge1_top)
+ {
+ slice->min_top_y = 1;
+ slice->min_bot_y = arc->height;
+ }
+ else
+ {
+ slice->min_bot_y = 0;
+ slice->min_top_y = arc->height;
+ }
+ }
+ miGetPieEdge(arc, angle1, &slice->edge1,
+ slice->edge1_top, !slice->edge1_top);
+ miGetPieEdge(arc, angle2, &slice->edge2,
+ slice->edge2_top, slice->edge2_top);
+ }
+ else
+ {
+ double w2, h2, x1, y1, x2, y2, dx, dy, scale;
+ int signdx, signdy, y, k;
+ Bool isInt1 = TRUE, isInt2 = TRUE;
+
+ w2 = (double)arc->width / 2.0;
+ h2 = (double)arc->height / 2.0;
+ if ((angle1 == 0) || (angle1 == HALFCIRCLE))
+ {
+ x1 = angle1 ? -w2 : w2;
+ y1 = 0.0;
+ }
+ else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3))
+ {
+ x1 = 0.0;
+ y1 = (angle1 == QUADRANT) ? h2 : -h2;
+ }
+ else
+ {
+ isInt1 = FALSE;
+ x1 = Dcos(angle1) * w2;
+ y1 = Dsin(angle1) * h2;
+ }
+ if ((angle2 == 0) || (angle2 == HALFCIRCLE))
+ {
+ x2 = angle2 ? -w2 : w2;
+ y2 = 0.0;
+ }
+ else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3))
+ {
+ x2 = 0.0;
+ y2 = (angle2 == QUADRANT) ? h2 : -h2;
+ }
+ else
+ {
+ isInt2 = FALSE;
+ x2 = Dcos(angle2) * w2;
+ y2 = Dsin(angle2) * h2;
+ }
+ dx = x2 - x1;
+ dy = y2 - y1;
+ if (arc->height & 1)
+ {
+ y1 -= 0.5;
+ y2 -= 0.5;
+ }
+ if (arc->width & 1)
+ {
+ x1 += 0.5;
+ x2 += 0.5;
+ }
+ if (dy < 0.0)
+ {
+ dy = -dy;
+ signdy = -1;
+ }
+ else
+ signdy = 1;
+ if (dx < 0.0)
+ {
+ dx = -dx;
+ signdx = -1;
+ }
+ else
+ signdx = 1;
+ if (isInt1 && isInt2)
+ {
+ slice->edge1.dx = dx * 2;
+ slice->edge1.dy = dy * 2;
+ }
+ else
+ {
+ scale = (dx > dy) ? dx : dy;
+ slice->edge1.dx = floor((dx * 32768) / scale + .5);
+ slice->edge1.dy = floor((dy * 32768) / scale + .5);
+ }
+ if (!slice->edge1.dy)
+ {
+ if (signdx < 0)
+ {
+ y = floor(y1 + 1.0);
+ if (y >= 0)
+ {
+ slice->min_top_y = y;
+ slice->min_bot_y = arc->height;
+ }
+ else
+ {
+ slice->max_bot_y = -y - (arc->height & 1);
+ }
+ }
+ else
+ {
+ y = floor(y1);
+ if (y >= 0)
+ slice->max_top_y = y;
+ else
+ {
+ slice->min_top_y = arc->height;
+ slice->min_bot_y = -y - (arc->height & 1);
+ }
+ }
+ slice->edge1_top = TRUE;
+ slice->edge1.x = 65536;
+ slice->edge1.stepx = 0;
+ slice->edge1.e = 0;
+ slice->edge1.dx = -1;
+ slice->edge2 = slice->edge1;
+ slice->edge2_top = FALSE;
+ }
+ else if (!slice->edge1.dx)
+ {
+ if (signdy < 0)
+ x1 -= 1.0;
+ slice->edge1.x = ceil(x1);
+ slice->edge1_top = signdy < 0;
+ slice->edge1.x += arc->x + (arc->width >> 1);
+ slice->edge1.stepx = 0;
+ slice->edge1.e = 0;
+ slice->edge1.dx = -1;
+ slice->edge2_top = !slice->edge1_top;
+ slice->edge2 = slice->edge1;
+ }
+ else
+ {
+ if (signdx < 0)
+ slice->edge1.dx = -slice->edge1.dx;
+ if (signdy < 0)
+ slice->edge1.dx = -slice->edge1.dx;
+ k = ceil(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0);
+ slice->edge2.dx = slice->edge1.dx;
+ slice->edge2.dy = slice->edge1.dy;
+ slice->edge1_top = signdy < 0;
+ slice->edge2_top = !slice->edge1_top;
+ miGetArcEdge(arc, &slice->edge1, k,
+ slice->edge1_top, !slice->edge1_top);
+ miGetArcEdge(arc, &slice->edge2, k,
+ slice->edge2_top, slice->edge2_top);
+ }
+ }
+}
+
+#define ADDSPANS() \
+ pts->x = xorg - x; \
+ pts->y = yorg - y; \
+ *wids = slw; \
+ pts++; \
+ wids++; \
+ if (miFillArcLower(slw)) \
+ { \
+ pts->x = xorg - x; \
+ pts->y = yorg + y + dy; \
+ pts++; \
+ *wids++ = slw; \
+ }
+
+static void
+miFillEllipseI(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ xArc *arc )
+{
+ int x, y, e;
+ int yk, xk, ym, xm, dx, dy, xorg, yorg;
+ int slw;
+ miFillArcRec info;
+ DDXPointPtr points;
+ DDXPointPtr pts;
+ int *widths;
+ int *wids;
+
+ points = malloc(sizeof(DDXPointRec) * arc->height);
+ if (!points)
+ return;
+ widths = malloc(sizeof(int) * arc->height);
+ if (!widths)
+ {
+ free(points);
+ return;
+ }
+ miFillArcSetup(arc, &info);
+ MIFILLARCSETUP();
+ if (pGC->miTranslate)
+ {
+ xorg += pDraw->x;
+ yorg += pDraw->y;
+ }
+ pts = points;
+ wids = widths;
+ while (y > 0)
+ {
+ MIFILLARCSTEP(slw);
+ ADDSPANS();
+ }
+ (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
+ free(widths);
+ free(points);
+}
+
+static void
+miFillEllipseD(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ xArc *arc )
+{
+ int x, y;
+ int xorg, yorg, dx, dy, slw;
+ double e, yk, xk, ym, xm;
+ miFillArcDRec info;
+ DDXPointPtr points;
+ DDXPointPtr pts;
+ int *widths;
+ int *wids;
+
+ points = malloc(sizeof(DDXPointRec) * arc->height);
+ if (!points)
+ return;
+ widths = malloc(sizeof(int) * arc->height);
+ if (!widths)
+ {
+ free(points);
+ return;
+ }
+ miFillArcDSetup(arc, &info);
+ MIFILLARCSETUP();
+ if (pGC->miTranslate)
+ {
+ xorg += pDraw->x;
+ yorg += pDraw->y;
+ }
+ pts = points;
+ wids = widths;
+ while (y > 0)
+ {
+ MIFILLARCSTEP(slw);
+ ADDSPANS();
+ }
+ (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
+ free(widths);
+ free(points);
+}
+
+#define ADDSPAN(l,r) \
+ if (r >= l) \
+ { \
+ pts->x = l; \
+ pts->y = ya; \
+ pts++; \
+ *wids++ = r - l + 1; \
+ }
+
+#define ADDSLICESPANS(flip) \
+ if (!flip) \
+ { \
+ ADDSPAN(xl, xr); \
+ } \
+ else \
+ { \
+ xc = xorg - x; \
+ ADDSPAN(xc, xr); \
+ xc += slw - 1; \
+ ADDSPAN(xl, xc); \
+ }
+
+static void
+miFillArcSliceI(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ xArc *arc )
+{
+ int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
+ int x, y, e;
+ miFillArcRec info;
+ miArcSliceRec slice;
+ int ya, xl, xr, xc;
+ DDXPointPtr points;
+ DDXPointPtr pts;
+ int *widths;
+ int *wids;
+
+ miFillArcSetup(arc, &info);
+ miFillArcSliceSetup(arc, &slice, pGC);
+ MIFILLARCSETUP();
+ slw = arc->height;
+ if (slice.flip_top || slice.flip_bot)
+ slw += (arc->height >> 1) + 1;
+ points = malloc(sizeof(DDXPointRec) * slw);
+ if (!points)
+ return;
+ widths = malloc(sizeof(int) * slw);
+ if (!widths)
+ {
+ free(points);
+ return;
+ }
+ if (pGC->miTranslate)
+ {
+ xorg += pDraw->x;
+ yorg += pDraw->y;
+ slice.edge1.x += pDraw->x;
+ slice.edge2.x += pDraw->x;
+ }
+ pts = points;
+ wids = widths;
+ while (y > 0)
+ {
+ MIFILLARCSTEP(slw);
+ MIARCSLICESTEP(slice.edge1);
+ MIARCSLICESTEP(slice.edge2);
+ if (miFillSliceUpper(slice))
+ {
+ ya = yorg - y;
+ MIARCSLICEUPPER(xl, xr, slice, slw);
+ ADDSLICESPANS(slice.flip_top);
+ }
+ if (miFillSliceLower(slice))
+ {
+ ya = yorg + y + dy;
+ MIARCSLICELOWER(xl, xr, slice, slw);
+ ADDSLICESPANS(slice.flip_bot);
+ }
+ }
+ (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
+ free(widths);
+ free(points);
+}
+
+static void
+miFillArcSliceD(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ xArc *arc )
+{
+ int x, y;
+ int dx, dy, xorg, yorg, slw;
+ double e, yk, xk, ym, xm;
+ miFillArcDRec info;
+ miArcSliceRec slice;
+ int ya, xl, xr, xc;
+ DDXPointPtr points;
+ DDXPointPtr pts;
+ int *widths;
+ int *wids;
+
+ miFillArcDSetup(arc, &info);
+ miFillArcSliceSetup(arc, &slice, pGC);
+ MIFILLARCSETUP();
+ slw = arc->height;
+ if (slice.flip_top || slice.flip_bot)
+ slw += (arc->height >> 1) + 1;
+ points = malloc(sizeof(DDXPointRec) * slw);
+ if (!points)
+ return;
+ widths = malloc(sizeof(int) * slw);
+ if (!widths)
+ {
+ free(points);
+ return;
+ }
+ if (pGC->miTranslate)
+ {
+ xorg += pDraw->x;
+ yorg += pDraw->y;
+ slice.edge1.x += pDraw->x;
+ slice.edge2.x += pDraw->x;
+ }
+ pts = points;
+ wids = widths;
+ while (y > 0)
+ {
+ MIFILLARCSTEP(slw);
+ MIARCSLICESTEP(slice.edge1);
+ MIARCSLICESTEP(slice.edge2);
+ if (miFillSliceUpper(slice))
+ {
+ ya = yorg - y;
+ MIARCSLICEUPPER(xl, xr, slice, slw);
+ ADDSLICESPANS(slice.flip_top);
+ }
+ if (miFillSliceLower(slice))
+ {
+ ya = yorg + y + dy;
+ MIARCSLICELOWER(xl, xr, slice, slw);
+ ADDSLICESPANS(slice.flip_bot);
+ }
+ }
+ (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
+ free(widths);
+ free(points);
+}
+
+/* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
+ * Since we don't have to worry about overlapping segments, we can just
+ * fill each arc as it comes.
+ */
+void
+miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
+{
+ int i;
+ xArc *arc;
+
+ for(i = narcs, arc = parcs; --i >= 0; arc++)
+ {
+ if (miFillArcEmpty(arc))
+ continue;
+ if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
+ {
+ if (miCanFillArc(arc))
+ miFillEllipseI(pDraw, pGC, arc);
+ else
+ miFillEllipseD(pDraw, pGC, arc);
+ }
+ else
+ {
+ if (miCanFillArc(arc))
+ miFillArcSliceI(pDraw, pGC, arc);
+ else
+ miFillArcSliceD(pDraw, pGC, arc);
+ }
+ }
+}
diff --git a/xorg-server/mi/mifillrct.c b/xorg-server/mi/mifillrct.c index 6e9979099..a97e5ced3 100644 --- a/xorg-server/mi/mifillrct.c +++ b/xorg-server/mi/mifillrct.c @@ -1,143 +1,143 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <X11/X.h> -#include <X11/Xprotostr.h> -#include "gcstruct.h" -#include "windowstr.h" -#include "pixmap.h" -#include "mi.h" -#include "misc.h" - -/* mi rectangles - written by newman, with debts to all and sundry -*/ - -/* MIPOLYFILLRECT -- public entry for PolyFillRect request - * very straight forward: translate rectangles if necessary - * then call FillSpans to fill each rectangle. We let FillSpans worry about - * clipping to the destination - */ -void -miPolyFillRect( - DrawablePtr pDrawable, - GCPtr pGC, - int nrectFill, /* number of rectangles to fill */ - xRectangle *prectInit /* Pointer to first rectangle to fill */ - ) -{ - int i; - int height; - int width; - xRectangle *prect; - int xorg; - int yorg; - int maxheight; - DDXPointPtr pptFirst; - DDXPointPtr ppt; - int *pwFirst; - int *pw; - - if (pGC->miTranslate) - { - xorg = pDrawable->x; - yorg = pDrawable->y; - prect = prectInit; - maxheight = 0; - for (i = 0; i<nrectFill; i++, prect++) - { - prect->x += xorg; - prect->y += yorg; - maxheight = max(maxheight, prect->height); - } - } - else - { - prect = prectInit; - maxheight = 0; - for (i = 0; i<nrectFill; i++, prect++) - maxheight = max(maxheight, prect->height); - } - - pptFirst = xalloc(maxheight * sizeof(DDXPointRec)); - pwFirst = xalloc(maxheight * sizeof(int)); - if(!pptFirst || !pwFirst) - { - if (pwFirst) xfree(pwFirst); - if (pptFirst) xfree(pptFirst); - return; - } - - prect = prectInit; - while(nrectFill--) - { - ppt = pptFirst; - pw = pwFirst; - height = prect->height; - width = prect->width; - xorg = prect->x; - yorg = prect->y; - while(height--) - { - *pw++ = width; - ppt->x = xorg; - ppt->y = yorg; - ppt++; - yorg++; - } - (* pGC->ops->FillSpans)(pDrawable, pGC, - prect->height, pptFirst, pwFirst, - 1); - prect++; - } - xfree(pwFirst); - xfree(pptFirst); -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <X11/X.h>
+#include <X11/Xprotostr.h>
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "pixmap.h"
+#include "mi.h"
+#include "misc.h"
+
+/* mi rectangles
+ written by newman, with debts to all and sundry
+*/
+
+/* MIPOLYFILLRECT -- public entry for PolyFillRect request
+ * very straight forward: translate rectangles if necessary
+ * then call FillSpans to fill each rectangle. We let FillSpans worry about
+ * clipping to the destination
+ */
+void
+miPolyFillRect(
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nrectFill, /* number of rectangles to fill */
+ xRectangle *prectInit /* Pointer to first rectangle to fill */
+ )
+{
+ int i;
+ int height;
+ int width;
+ xRectangle *prect;
+ int xorg;
+ int yorg;
+ int maxheight;
+ DDXPointPtr pptFirst;
+ DDXPointPtr ppt;
+ int *pwFirst;
+ int *pw;
+
+ if (pGC->miTranslate)
+ {
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+ prect = prectInit;
+ maxheight = 0;
+ for (i = 0; i<nrectFill; i++, prect++)
+ {
+ prect->x += xorg;
+ prect->y += yorg;
+ maxheight = max(maxheight, prect->height);
+ }
+ }
+ else
+ {
+ prect = prectInit;
+ maxheight = 0;
+ for (i = 0; i<nrectFill; i++, prect++)
+ maxheight = max(maxheight, prect->height);
+ }
+
+ pptFirst = malloc(maxheight * sizeof(DDXPointRec));
+ pwFirst = malloc(maxheight * sizeof(int));
+ if(!pptFirst || !pwFirst)
+ {
+ if (pwFirst) free(pwFirst);
+ if (pptFirst) free(pptFirst);
+ return;
+ }
+
+ prect = prectInit;
+ while(nrectFill--)
+ {
+ ppt = pptFirst;
+ pw = pwFirst;
+ height = prect->height;
+ width = prect->width;
+ xorg = prect->x;
+ yorg = prect->y;
+ while(height--)
+ {
+ *pw++ = width;
+ ppt->x = xorg;
+ ppt->y = yorg;
+ ppt++;
+ yorg++;
+ }
+ (* pGC->ops->FillSpans)(pDrawable, pGC,
+ prect->height, pptFirst, pwFirst,
+ 1);
+ prect++;
+ }
+ free(pwFirst);
+ free(pptFirst);
+}
diff --git a/xorg-server/mi/mifpolycon.c b/xorg-server/mi/mifpolycon.c index 383502f64..8411a1570 100644 --- a/xorg-server/mi/mifpolycon.c +++ b/xorg-server/mi/mifpolycon.c @@ -1,280 +1,280 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <math.h> -#include <X11/X.h> -#include "gcstruct.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "mifpoly.h" - -static int GetFPolyYBounds(SppPointPtr pts, int n, double yFtrans, - int *by, int *ty); - -/* - * Written by Todd Newman; April. 1987. - * - * Fill a convex polygon. If the given polygon - * is not convex, then the result is undefined. - * The algorithm is to order the edges from smallest - * y to largest by partitioning the array into a left - * edge list and a right edge list. The algorithm used - * to traverse each edge is digital differencing analyzer - * line algorithm with y as the major axis. There's some funny linear - * interpolation involved because of the subpixel postioning. - */ -void -miFillSppPoly( - DrawablePtr dst, - GCPtr pgc, - int count, /* number of points */ - SppPointPtr ptsIn, /* the points */ - int xTrans, int yTrans, /* Translate each point by this */ - double xFtrans, - double yFtrans /* translate before conversion - by this amount. This provides - a mechanism to match rounding - errors with any shape that must - meet the polygon exactly. - */ - ) -{ - double xl = 0.0, xr = 0.0, /* x vals of left and right edges */ - ml = 0.0, /* left edge slope */ - mr = 0.0, /* right edge slope */ - dy, /* delta y */ - i; /* loop counter */ - int y, /* current scanline */ - j, - imin, /* index of vertex with smallest y */ - ymin, /* y-extents of polygon */ - ymax, - *width, - *FirstWidth, /* output buffer */ - *Marked; /* set if this vertex has been used */ - int left, right, /* indices to first endpoints */ - nextleft, - nextright; /* indices to second endpoints */ - DDXPointPtr ptsOut, - FirstPoint; /* output buffer */ - - if (pgc->miTranslate) - { - xTrans += dst->x; - yTrans += dst->y; - } - - imin = GetFPolyYBounds(ptsIn, count, yFtrans, &ymin, &ymax); - - y = ymax - ymin + 1; - if ((count < 3) || (y <= 0)) - return; - ptsOut = FirstPoint = xalloc(sizeof(DDXPointRec) * y); - width = FirstWidth = xalloc(sizeof(int) * y); - Marked = xalloc(sizeof(int) * count); - - if(!ptsOut || !width || !Marked) - { - if (Marked) xfree(Marked); - if (width) xfree(width); - if (ptsOut) xfree(ptsOut); - return; - } - - for(j = 0; j < count; j++) - Marked[j] = 0; - nextleft = nextright = imin; - Marked[imin] = -1; - y = ICEIL(ptsIn[nextleft].y + yFtrans); - - /* - * loop through all edges of the polygon - */ - do - { - /* add a left edge if we need to */ - if ((y > (ptsIn[nextleft].y + yFtrans) || - ISEQUAL(y, ptsIn[nextleft].y + yFtrans)) && - Marked[nextleft] != 1) - { - Marked[nextleft]++; - left = nextleft++; - - /* find the next edge, considering the end conditions */ - if (nextleft >= count) - nextleft = 0; - - /* now compute the starting point and slope */ - dy = ptsIn[nextleft].y - ptsIn[left].y; - if (dy != 0.0) - { - ml = (ptsIn[nextleft].x - ptsIn[left].x) / dy; - dy = y - (ptsIn[left].y + yFtrans); - xl = (ptsIn[left].x + xFtrans) + ml * max(dy, 0); - } - } - - /* add a right edge if we need to */ - if ((y > ptsIn[nextright].y + yFtrans) || - (ISEQUAL(y, ptsIn[nextright].y + yFtrans) - && Marked[nextright] != 1)) - { - Marked[nextright]++; - right = nextright--; - - /* find the next edge, considering the end conditions */ - if (nextright < 0) - nextright = count - 1; - - /* now compute the starting point and slope */ - dy = ptsIn[nextright].y - ptsIn[right].y; - if (dy != 0.0) - { - mr = (ptsIn[nextright].x - ptsIn[right].x) / dy; - dy = y - (ptsIn[right].y + yFtrans); - xr = (ptsIn[right].x + xFtrans) + mr * max(dy, 0); - } - } - - - /* - * generate scans to fill while we still have - * a right edge as well as a left edge. - */ - i = (min(ptsIn[nextleft].y, ptsIn[nextright].y) + yFtrans) - y; - - if (i < EPSILON) - { - if(Marked[nextleft] && Marked[nextright]) - { - /* Arrgh, we're trapped! (no more points) - * Out, we've got to get out of here before this decadence saps - * our will completely! */ - break; - } - continue; - } - else - { - j = (int) i; - if(!j) - j++; - } - while (j > 0) - { - int cxl, cxr; - - ptsOut->y = (y) + yTrans; - - cxl = ICEIL(xl); - cxr = ICEIL(xr); - /* reverse the edges if necessary */ - if (xl < xr) - { - *(width++) = cxr - cxl; - (ptsOut++)->x = cxl + xTrans; - } - else - { - *(width++) = cxl - cxr; - (ptsOut++)->x = cxr + xTrans; - } - y++; - - /* increment down the edges */ - xl += ml; - xr += mr; - j--; - } - } while (y <= ymax); - - /* Finally, fill the spans we've collected */ - (*pgc->ops->FillSpans)(dst, pgc, - ptsOut-FirstPoint, FirstPoint, FirstWidth, 1); - xfree(Marked); - xfree(FirstWidth); - xfree(FirstPoint); -} - - -/* Find the index of the point with the smallest y.also return the - * smallest and largest y */ -static -int -GetFPolyYBounds( - SppPointPtr pts, - int n, - double yFtrans, - int *by, - int *ty) -{ - SppPointPtr ptMin; - double ymin, ymax; - SppPointPtr ptsStart = pts; - - ptMin = pts; - ymin = ymax = (pts++)->y; - - while (--n > 0) { - if (pts->y < ymin) - { - ptMin = pts; - ymin = pts->y; - } - if(pts->y > ymax) - ymax = pts->y; - - pts++; - } - - *by = ICEIL(ymin + yFtrans); - *ty = ICEIL(ymax + yFtrans - 1); - return(ptMin-ptsStart); -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <math.h>
+#include <X11/X.h>
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "mifpoly.h"
+
+static int GetFPolyYBounds(SppPointPtr pts, int n, double yFtrans,
+ int *by, int *ty);
+
+/*
+ * Written by Todd Newman; April. 1987.
+ *
+ * Fill a convex polygon. If the given polygon
+ * is not convex, then the result is undefined.
+ * The algorithm is to order the edges from smallest
+ * y to largest by partitioning the array into a left
+ * edge list and a right edge list. The algorithm used
+ * to traverse each edge is digital differencing analyzer
+ * line algorithm with y as the major axis. There's some funny linear
+ * interpolation involved because of the subpixel postioning.
+ */
+void
+miFillSppPoly(
+ DrawablePtr dst,
+ GCPtr pgc,
+ int count, /* number of points */
+ SppPointPtr ptsIn, /* the points */
+ int xTrans, int yTrans, /* Translate each point by this */
+ double xFtrans,
+ double yFtrans /* translate before conversion
+ by this amount. This provides
+ a mechanism to match rounding
+ errors with any shape that must
+ meet the polygon exactly.
+ */
+ )
+{
+ double xl = 0.0, xr = 0.0, /* x vals of left and right edges */
+ ml = 0.0, /* left edge slope */
+ mr = 0.0, /* right edge slope */
+ dy, /* delta y */
+ i; /* loop counter */
+ int y, /* current scanline */
+ j,
+ imin, /* index of vertex with smallest y */
+ ymin, /* y-extents of polygon */
+ ymax,
+ *width,
+ *FirstWidth, /* output buffer */
+ *Marked; /* set if this vertex has been used */
+ int left, right, /* indices to first endpoints */
+ nextleft,
+ nextright; /* indices to second endpoints */
+ DDXPointPtr ptsOut,
+ FirstPoint; /* output buffer */
+
+ if (pgc->miTranslate)
+ {
+ xTrans += dst->x;
+ yTrans += dst->y;
+ }
+
+ imin = GetFPolyYBounds(ptsIn, count, yFtrans, &ymin, &ymax);
+
+ y = ymax - ymin + 1;
+ if ((count < 3) || (y <= 0))
+ return;
+ ptsOut = FirstPoint = malloc(sizeof(DDXPointRec) * y);
+ width = FirstWidth = malloc(sizeof(int) * y);
+ Marked = malloc(sizeof(int) * count);
+
+ if(!ptsOut || !width || !Marked)
+ {
+ if (Marked) free(Marked);
+ if (width) free(width);
+ if (ptsOut) free(ptsOut);
+ return;
+ }
+
+ for(j = 0; j < count; j++)
+ Marked[j] = 0;
+ nextleft = nextright = imin;
+ Marked[imin] = -1;
+ y = ICEIL(ptsIn[nextleft].y + yFtrans);
+
+ /*
+ * loop through all edges of the polygon
+ */
+ do
+ {
+ /* add a left edge if we need to */
+ if ((y > (ptsIn[nextleft].y + yFtrans) ||
+ ISEQUAL(y, ptsIn[nextleft].y + yFtrans)) &&
+ Marked[nextleft] != 1)
+ {
+ Marked[nextleft]++;
+ left = nextleft++;
+
+ /* find the next edge, considering the end conditions */
+ if (nextleft >= count)
+ nextleft = 0;
+
+ /* now compute the starting point and slope */
+ dy = ptsIn[nextleft].y - ptsIn[left].y;
+ if (dy != 0.0)
+ {
+ ml = (ptsIn[nextleft].x - ptsIn[left].x) / dy;
+ dy = y - (ptsIn[left].y + yFtrans);
+ xl = (ptsIn[left].x + xFtrans) + ml * max(dy, 0);
+ }
+ }
+
+ /* add a right edge if we need to */
+ if ((y > ptsIn[nextright].y + yFtrans) ||
+ (ISEQUAL(y, ptsIn[nextright].y + yFtrans)
+ && Marked[nextright] != 1))
+ {
+ Marked[nextright]++;
+ right = nextright--;
+
+ /* find the next edge, considering the end conditions */
+ if (nextright < 0)
+ nextright = count - 1;
+
+ /* now compute the starting point and slope */
+ dy = ptsIn[nextright].y - ptsIn[right].y;
+ if (dy != 0.0)
+ {
+ mr = (ptsIn[nextright].x - ptsIn[right].x) / dy;
+ dy = y - (ptsIn[right].y + yFtrans);
+ xr = (ptsIn[right].x + xFtrans) + mr * max(dy, 0);
+ }
+ }
+
+
+ /*
+ * generate scans to fill while we still have
+ * a right edge as well as a left edge.
+ */
+ i = (min(ptsIn[nextleft].y, ptsIn[nextright].y) + yFtrans) - y;
+
+ if (i < EPSILON)
+ {
+ if(Marked[nextleft] && Marked[nextright])
+ {
+ /* Arrgh, we're trapped! (no more points)
+ * Out, we've got to get out of here before this decadence saps
+ * our will completely! */
+ break;
+ }
+ continue;
+ }
+ else
+ {
+ j = (int) i;
+ if(!j)
+ j++;
+ }
+ while (j > 0)
+ {
+ int cxl, cxr;
+
+ ptsOut->y = (y) + yTrans;
+
+ cxl = ICEIL(xl);
+ cxr = ICEIL(xr);
+ /* reverse the edges if necessary */
+ if (xl < xr)
+ {
+ *(width++) = cxr - cxl;
+ (ptsOut++)->x = cxl + xTrans;
+ }
+ else
+ {
+ *(width++) = cxl - cxr;
+ (ptsOut++)->x = cxr + xTrans;
+ }
+ y++;
+
+ /* increment down the edges */
+ xl += ml;
+ xr += mr;
+ j--;
+ }
+ } while (y <= ymax);
+
+ /* Finally, fill the spans we've collected */
+ (*pgc->ops->FillSpans)(dst, pgc,
+ ptsOut-FirstPoint, FirstPoint, FirstWidth, 1);
+ free(Marked);
+ free(FirstWidth);
+ free(FirstPoint);
+}
+
+
+/* Find the index of the point with the smallest y.also return the
+ * smallest and largest y */
+static
+int
+GetFPolyYBounds(
+ SppPointPtr pts,
+ int n,
+ double yFtrans,
+ int *by,
+ int *ty)
+{
+ SppPointPtr ptMin;
+ double ymin, ymax;
+ SppPointPtr ptsStart = pts;
+
+ ptMin = pts;
+ ymin = ymax = (pts++)->y;
+
+ while (--n > 0) {
+ if (pts->y < ymin)
+ {
+ ptMin = pts;
+ ymin = pts->y;
+ }
+ if(pts->y > ymax)
+ ymax = pts->y;
+
+ pts++;
+ }
+
+ *by = ICEIL(ymin + yFtrans);
+ *ty = ICEIL(ymax + yFtrans - 1);
+ return(ptMin-ptsStart);
+}
diff --git a/xorg-server/mi/migc.c b/xorg-server/mi/migc.c index a797099cd..e42f29810 100644 --- a/xorg-server/mi/migc.c +++ b/xorg-server/mi/migc.c @@ -1,255 +1,255 @@ -/* - -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) - REGION_DESTROY(pGC->pScreen, 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 - */ - REGION_DESTROY(pGC->pScreen, 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) BITMAP_TO_REGION(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) RECTS_TO_REGION(pGC->pScreen, nrects, - (xRectangle *) pvalue, - type); - xfree(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 = REGION_CREATE(pgcSrc->pScreen, NULL, 1); - REGION_COPY(pgcDst->pScreen, 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) -{ - ScreenPtr pScreen; - - /* This prevents warnings about pScreen not being used. */ - pGC->pScreen = pScreen = pGC->pScreen; - - 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) - REGION_DESTROY(pScreen, 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. - */ - - REGION_TRANSLATE(pScreen, pGC->clientClip, - pDrawable->x + pGC->clipOrg.x, - pDrawable->y + pGC->clipOrg.y); - - if (freeCompClip) - { - REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip, - pregWin, pGC->clientClip); - if (freeTmpClip) - REGION_DESTROY(pScreen, pregWin); - } - else if (freeTmpClip) - { - REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip); - pGC->pCompositeClip = pregWin; - } - else - { - pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0); - REGION_INTERSECT(pScreen, pGC->pCompositeClip, - pregWin, pGC->clientClip); - } - pGC->freeCompClip = TRUE; - REGION_TRANSLATE(pScreen, 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) - { - REGION_RESET(pScreen, pGC->pCompositeClip, &pixbounds); - } - else - { - pGC->freeCompClip = TRUE; - pGC->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1); - } - - if (pGC->clientClipType == CT_REGION) - { - if(pDrawable->x || pDrawable->y) { - REGION_TRANSLATE(pScreen, pGC->clientClip, - pDrawable->x + pGC->clipOrg.x, - pDrawable->y + pGC->clipOrg.y); - REGION_INTERSECT(pScreen, pGC->pCompositeClip, - pGC->pCompositeClip, pGC->clientClip); - REGION_TRANSLATE(pScreen, pGC->clientClip, - -(pDrawable->x + pGC->clipOrg.x), - -(pDrawable->y + pGC->clipOrg.y)); - } else { - REGION_TRANSLATE(pScreen, pGC->pCompositeClip, - -pGC->clipOrg.x, -pGC->clipOrg.y); - REGION_INTERSECT(pScreen, pGC->pCompositeClip, - pGC->pCompositeClip, pGC->clientClip); - REGION_TRANSLATE(pScreen, pGC->pCompositeClip, - pGC->clipOrg.x, pGC->clipOrg.y); - } - } - } /* end of composite clip for pixmap */ -} /* end miComputeCompositeClip */ +/*
+
+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)
+ REGION_DESTROY(pGC->pScreen, 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
+ */
+ REGION_DESTROY(pGC->pScreen, 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) BITMAP_TO_REGION(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) RECTS_TO_REGION(pGC->pScreen, 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 = REGION_CREATE(pgcSrc->pScreen, NULL, 1);
+ REGION_COPY(pgcDst->pScreen, 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)
+{
+ ScreenPtr pScreen;
+
+ /* This prevents warnings about pScreen not being used. */
+ pGC->pScreen = pScreen = pGC->pScreen;
+
+ 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)
+ REGION_DESTROY(pScreen, 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.
+ */
+
+ REGION_TRANSLATE(pScreen, pGC->clientClip,
+ pDrawable->x + pGC->clipOrg.x,
+ pDrawable->y + pGC->clipOrg.y);
+
+ if (freeCompClip)
+ {
+ REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
+ pregWin, pGC->clientClip);
+ if (freeTmpClip)
+ REGION_DESTROY(pScreen, pregWin);
+ }
+ else if (freeTmpClip)
+ {
+ REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip);
+ pGC->pCompositeClip = pregWin;
+ }
+ else
+ {
+ pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
+ REGION_INTERSECT(pScreen, pGC->pCompositeClip,
+ pregWin, pGC->clientClip);
+ }
+ pGC->freeCompClip = TRUE;
+ REGION_TRANSLATE(pScreen, 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)
+ {
+ REGION_RESET(pScreen, pGC->pCompositeClip, &pixbounds);
+ }
+ else
+ {
+ pGC->freeCompClip = TRUE;
+ pGC->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1);
+ }
+
+ if (pGC->clientClipType == CT_REGION)
+ {
+ if(pDrawable->x || pDrawable->y) {
+ REGION_TRANSLATE(pScreen, pGC->clientClip,
+ pDrawable->x + pGC->clipOrg.x,
+ pDrawable->y + pGC->clipOrg.y);
+ REGION_INTERSECT(pScreen, pGC->pCompositeClip,
+ pGC->pCompositeClip, pGC->clientClip);
+ REGION_TRANSLATE(pScreen, pGC->clientClip,
+ -(pDrawable->x + pGC->clipOrg.x),
+ -(pDrawable->y + pGC->clipOrg.y));
+ } else {
+ REGION_TRANSLATE(pScreen, pGC->pCompositeClip,
+ -pGC->clipOrg.x, -pGC->clipOrg.y);
+ REGION_INTERSECT(pScreen, pGC->pCompositeClip,
+ pGC->pCompositeClip, pGC->clientClip);
+ REGION_TRANSLATE(pScreen, pGC->pCompositeClip,
+ pGC->clipOrg.x, pGC->clipOrg.y);
+ }
+ }
+ } /* end of composite clip for pixmap */
+} /* end miComputeCompositeClip */
diff --git a/xorg-server/mi/miglblt.c b/xorg-server/mi/miglblt.c index bc715aee9..c299fe554 100644 --- a/xorg-server/mi/miglblt.c +++ b/xorg-server/mi/miglblt.c @@ -1,258 +1,258 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <X11/X.h> -#include <X11/Xmd.h> -#include <X11/Xproto.h> -#include "misc.h" -#include <X11/fonts/fontstruct.h> -#include "dixfontstr.h" -#include "gcstruct.h" -#include "windowstr.h" -#include "scrnintstr.h" -#include "pixmap.h" -#include "servermd.h" -#include "mi.h" - -/* - machine-independent glyph blt. - assumes that glyph bits in snf are written in bytes, -have same bit order as the server's bitmap format, -and are byte padded. this corresponds to the snf distributed -with the sample server. - - get a scratch GC. - in the scratch GC set alu = GXcopy, fg = 1, bg = 0 - allocate a bitmap big enough to hold the largest glyph in the font - validate the scratch gc with the bitmap - for each glyph - carefully put the bits of the glyph in a buffer, - padded to the server pixmap scanline padding rules - fake a call to PutImage from the buffer into the bitmap - use the bitmap in a call to PushPixels -*/ - -void -miPolyGlyphBlt( - DrawablePtr pDrawable, - GC *pGC, - int x, - int y, - unsigned int nglyph, - CharInfoPtr *ppci, /* array of character info */ - pointer pglyphBase /* start of array of glyphs */ - ) -{ - int width, height; - PixmapPtr pPixmap; - int nbyLine; /* bytes per line of padded pixmap */ - FontPtr pfont; - GCPtr pGCtmp; - int i; - int j; - unsigned char *pbits; /* buffer for PutImage */ - unsigned char *pb; /* temp pointer into buffer */ - CharInfoPtr pci; /* currect char info */ - unsigned char *pglyph; /* pointer bits in glyph */ - int gWidth, gHeight; /* width and height of glyph */ - int nbyGlyphWidth; /* bytes per scanline of glyph */ - int nbyPadGlyph; /* server padded line of glyph */ - - XID gcvals[3]; - - if (pGC->miTranslate) - { - x += pDrawable->x; - y += pDrawable->y; - } - - pfont = pGC->font; - width = FONTMAXBOUNDS(pfont,rightSideBearing) - - FONTMINBOUNDS(pfont,leftSideBearing); - height = FONTMAXBOUNDS(pfont,ascent) + - FONTMAXBOUNDS(pfont,descent); - - pPixmap = (*pDrawable->pScreen->CreatePixmap)(pDrawable->pScreen, - width, height, 1, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pPixmap) - return; - - pGCtmp = GetScratchGC(1, pDrawable->pScreen); - if (!pGCtmp) - { - (*pDrawable->pScreen->DestroyPixmap)(pPixmap); - return; - } - - gcvals[0] = GXcopy; - gcvals[1] = 1; - gcvals[2] = 0; - - DoChangeGC(pGCtmp, GCFunction|GCForeground|GCBackground, gcvals, 0); - - nbyLine = BitmapBytePad(width); - pbits = xalloc(height*nbyLine); - if (!pbits) - { - (*pDrawable->pScreen->DestroyPixmap)(pPixmap); - FreeScratchGC(pGCtmp); - return; - } - while(nglyph--) - { - pci = *ppci++; - pglyph = FONTGLYPHBITS(pglyphBase, pci); - gWidth = GLYPHWIDTHPIXELS(pci); - gHeight = GLYPHHEIGHTPIXELS(pci); - if (gWidth && gHeight) - { - nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci); - nbyPadGlyph = BitmapBytePad(gWidth); - - if (nbyGlyphWidth == nbyPadGlyph -#if GLYPHPADBYTES != 4 - && (((int) pglyph) & 3) == 0 -#endif - ) - { - pb = pglyph; - } - else - { - for (i=0, pb = pbits; i<gHeight; i++, pb = pbits+(i*nbyPadGlyph)) - for (j = 0; j < nbyGlyphWidth; j++) - *pb++ = *pglyph++; - pb = pbits; - } - - if ((pGCtmp->serialNumber) != (pPixmap->drawable.serialNumber)) - ValidateGC((DrawablePtr)pPixmap, pGCtmp); - (*pGCtmp->ops->PutImage)((DrawablePtr)pPixmap, pGCtmp, - pPixmap->drawable.depth, - 0, 0, gWidth, gHeight, - 0, XYBitmap, (char *)pb); - - if ((pGC->serialNumber) != (pDrawable->serialNumber)) - ValidateGC(pDrawable, pGC); - (*pGC->ops->PushPixels)(pGC, pPixmap, pDrawable, - gWidth, gHeight, - x + pci->metrics.leftSideBearing, - y - pci->metrics.ascent); - } - x += pci->metrics.characterWidth; - } - (*pDrawable->pScreen->DestroyPixmap)(pPixmap); - xfree(pbits); - FreeScratchGC(pGCtmp); -} - - -void -miImageGlyphBlt( - DrawablePtr pDrawable, - GC *pGC, - int x, - int y, - unsigned int nglyph, - CharInfoPtr *ppci, /* array of character info */ - pointer pglyphBase /* start of array of glyphs */ - ) -{ - ExtentInfoRec info; /* used by QueryGlyphExtents() */ - XID gcvals[3]; - int oldAlu, oldFS; - unsigned long oldFG; - xRectangle backrect; - - QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info); - - if (info.overallWidth >= 0) - { - backrect.x = x; - backrect.width = info.overallWidth; - } - else - { - backrect.x = x + info.overallWidth; - backrect.width = -info.overallWidth; - } - backrect.y = y - FONTASCENT(pGC->font); - backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); - - oldAlu = pGC->alu; - oldFG = pGC->fgPixel; - oldFS = pGC->fillStyle; - - /* fill in the background */ - gcvals[0] = GXcopy; - gcvals[1] = pGC->bgPixel; - gcvals[2] = FillSolid; - DoChangeGC(pGC, GCFunction|GCForeground|GCFillStyle, gcvals, 0); - ValidateGC(pDrawable, pGC); - (*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &backrect); - - /* put down the glyphs */ - gcvals[0] = oldFG; - DoChangeGC(pGC, GCForeground, gcvals, 0); - ValidateGC(pDrawable, pGC); - (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci, - pglyphBase); - - /* put all the toys away when done playing */ - gcvals[0] = oldAlu; - gcvals[1] = oldFG; - gcvals[2] = oldFS; - DoChangeGC(pGC, GCFunction|GCForeground|GCFillStyle, gcvals, 0); - ValidateGC(pDrawable, pGC); - -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <X11/X.h>
+#include <X11/Xmd.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "pixmap.h"
+#include "servermd.h"
+#include "mi.h"
+
+/*
+ machine-independent glyph blt.
+ assumes that glyph bits in snf are written in bytes,
+have same bit order as the server's bitmap format,
+and are byte padded. this corresponds to the snf distributed
+with the sample server.
+
+ get a scratch GC.
+ in the scratch GC set alu = GXcopy, fg = 1, bg = 0
+ allocate a bitmap big enough to hold the largest glyph in the font
+ validate the scratch gc with the bitmap
+ for each glyph
+ carefully put the bits of the glyph in a buffer,
+ padded to the server pixmap scanline padding rules
+ fake a call to PutImage from the buffer into the bitmap
+ use the bitmap in a call to PushPixels
+*/
+
+void
+miPolyGlyphBlt(
+ DrawablePtr pDrawable,
+ GC *pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci, /* array of character info */
+ pointer pglyphBase /* start of array of glyphs */
+ )
+{
+ int width, height;
+ PixmapPtr pPixmap;
+ int nbyLine; /* bytes per line of padded pixmap */
+ FontPtr pfont;
+ GCPtr pGCtmp;
+ int i;
+ int j;
+ unsigned char *pbits; /* buffer for PutImage */
+ unsigned char *pb; /* temp pointer into buffer */
+ CharInfoPtr pci; /* currect char info */
+ unsigned char *pglyph; /* pointer bits in glyph */
+ int gWidth, gHeight; /* width and height of glyph */
+ int nbyGlyphWidth; /* bytes per scanline of glyph */
+ int nbyPadGlyph; /* server padded line of glyph */
+
+ ChangeGCVal gcvals[3];
+
+ if (pGC->miTranslate)
+ {
+ x += pDrawable->x;
+ y += pDrawable->y;
+ }
+
+ pfont = pGC->font;
+ width = FONTMAXBOUNDS(pfont,rightSideBearing) -
+ FONTMINBOUNDS(pfont,leftSideBearing);
+ height = FONTMAXBOUNDS(pfont,ascent) +
+ FONTMAXBOUNDS(pfont,descent);
+
+ pPixmap = (*pDrawable->pScreen->CreatePixmap)(pDrawable->pScreen,
+ width, height, 1,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap)
+ return;
+
+ pGCtmp = GetScratchGC(1, pDrawable->pScreen);
+ if (!pGCtmp)
+ {
+ (*pDrawable->pScreen->DestroyPixmap)(pPixmap);
+ return;
+ }
+
+ gcvals[0].val = GXcopy;
+ gcvals[1].val = 1;
+ gcvals[2].val = 0;
+
+ ChangeGC(NullClient, pGCtmp, GCFunction|GCForeground|GCBackground, gcvals);
+
+ nbyLine = BitmapBytePad(width);
+ pbits = malloc(height*nbyLine);
+ if (!pbits)
+ {
+ (*pDrawable->pScreen->DestroyPixmap)(pPixmap);
+ FreeScratchGC(pGCtmp);
+ return;
+ }
+ while(nglyph--)
+ {
+ pci = *ppci++;
+ pglyph = FONTGLYPHBITS(pglyphBase, pci);
+ gWidth = GLYPHWIDTHPIXELS(pci);
+ gHeight = GLYPHHEIGHTPIXELS(pci);
+ if (gWidth && gHeight)
+ {
+ nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci);
+ nbyPadGlyph = BitmapBytePad(gWidth);
+
+ if (nbyGlyphWidth == nbyPadGlyph
+#if GLYPHPADBYTES != 4
+ && (((int) pglyph) & 3) == 0
+#endif
+ )
+ {
+ pb = pglyph;
+ }
+ else
+ {
+ for (i=0, pb = pbits; i<gHeight; i++, pb = pbits+(i*nbyPadGlyph))
+ for (j = 0; j < nbyGlyphWidth; j++)
+ *pb++ = *pglyph++;
+ pb = pbits;
+ }
+
+ if ((pGCtmp->serialNumber) != (pPixmap->drawable.serialNumber))
+ ValidateGC((DrawablePtr)pPixmap, pGCtmp);
+ (*pGCtmp->ops->PutImage)((DrawablePtr)pPixmap, pGCtmp,
+ pPixmap->drawable.depth,
+ 0, 0, gWidth, gHeight,
+ 0, XYBitmap, (char *)pb);
+
+ if ((pGC->serialNumber) != (pDrawable->serialNumber))
+ ValidateGC(pDrawable, pGC);
+ (*pGC->ops->PushPixels)(pGC, pPixmap, pDrawable,
+ gWidth, gHeight,
+ x + pci->metrics.leftSideBearing,
+ y - pci->metrics.ascent);
+ }
+ x += pci->metrics.characterWidth;
+ }
+ (*pDrawable->pScreen->DestroyPixmap)(pPixmap);
+ free(pbits);
+ FreeScratchGC(pGCtmp);
+}
+
+
+void
+miImageGlyphBlt(
+ DrawablePtr pDrawable,
+ GC *pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci, /* array of character info */
+ pointer pglyphBase /* start of array of glyphs */
+ )
+{
+ ExtentInfoRec info; /* used by QueryGlyphExtents() */
+ ChangeGCVal gcvals[3];
+ int oldAlu, oldFS;
+ unsigned long oldFG;
+ xRectangle backrect;
+
+ QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info);
+
+ if (info.overallWidth >= 0)
+ {
+ backrect.x = x;
+ backrect.width = info.overallWidth;
+ }
+ else
+ {
+ backrect.x = x + info.overallWidth;
+ backrect.width = -info.overallWidth;
+ }
+ backrect.y = y - FONTASCENT(pGC->font);
+ backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
+
+ oldAlu = pGC->alu;
+ oldFG = pGC->fgPixel;
+ oldFS = pGC->fillStyle;
+
+ /* fill in the background */
+ gcvals[0].val = GXcopy;
+ gcvals[1].val = pGC->bgPixel;
+ gcvals[2].val = FillSolid;
+ ChangeGC(NullClient, pGC, GCFunction|GCForeground|GCFillStyle, gcvals);
+ ValidateGC(pDrawable, pGC);
+ (*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &backrect);
+
+ /* put down the glyphs */
+ gcvals[0].val = oldFG;
+ ChangeGC(NullClient, pGC, GCForeground, gcvals);
+ ValidateGC(pDrawable, pGC);
+ (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci,
+ pglyphBase);
+
+ /* put all the toys away when done playing */
+ gcvals[0].val = oldAlu;
+ gcvals[1].val = oldFG;
+ gcvals[2].val = oldFS;
+ ChangeGC(NullClient, pGC, GCFunction|GCForeground|GCFillStyle, gcvals);
+ ValidateGC(pDrawable, pGC);
+
+}
diff --git a/xorg-server/mi/mioverlay.c b/xorg-server/mi/mioverlay.c index e0aa88017..3de826b74 100644 --- a/xorg-server/mi/mioverlay.c +++ b/xorg-server/mi/mioverlay.c @@ -1,1948 +1,1948 @@ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/X.h> -#include "scrnintstr.h" -#include "validate.h" -#include "windowstr.h" -#include "mi.h" -#include "gcstruct.h" -#include "regionstr.h" -#include "privates.h" -#include "mivalidate.h" -#include "mioverlay.h" -#include "migc.h" - -#include "globals.h" - - -typedef struct { - RegionRec exposed; - RegionRec borderExposed; - RegionPtr borderVisible; - DDXPointRec oldAbsCorner; -} miOverlayValDataRec, *miOverlayValDataPtr; - -typedef struct _TreeRec { - WindowPtr pWin; - struct _TreeRec *parent; - struct _TreeRec *firstChild; - struct _TreeRec *lastChild; - struct _TreeRec *prevSib; - struct _TreeRec *nextSib; - RegionRec borderClip; - RegionRec clipList; - unsigned visibility; - miOverlayValDataPtr valdata; -} miOverlayTreeRec, *miOverlayTreePtr; - -typedef struct { - miOverlayTreePtr tree; -} miOverlayWindowRec, *miOverlayWindowPtr; - -typedef struct { - CloseScreenProcPtr CloseScreen; - CreateWindowProcPtr CreateWindow; - DestroyWindowProcPtr DestroyWindow; - UnrealizeWindowProcPtr UnrealizeWindow; - RealizeWindowProcPtr RealizeWindow; - miOverlayTransFunc MakeTransparent; - miOverlayInOverlayFunc InOverlay; - Bool underlayMarked; - Bool copyUnderlay; -} miOverlayScreenRec, *miOverlayScreenPtr; - -static int miOverlayWindowKeyKeyIndex; -static DevPrivateKey miOverlayWindowKey = &miOverlayWindowKeyKeyIndex; -static int miOverlayScreenKeyIndex; -static DevPrivateKey miOverlayScreenKey = &miOverlayScreenKeyIndex; - -static void RebuildTree(WindowPtr); -static Bool HasUnderlayChildren(WindowPtr); -static void MarkUnderlayWindow(WindowPtr); -static Bool CollectUnderlayChildrenRegions(WindowPtr, RegionPtr); - -static Bool miOverlayCloseScreen(int, ScreenPtr); -static Bool miOverlayCreateWindow(WindowPtr); -static Bool miOverlayDestroyWindow(WindowPtr); -static Bool miOverlayUnrealizeWindow(WindowPtr); -static Bool miOverlayRealizeWindow(WindowPtr); -static void miOverlayMarkWindow(WindowPtr); -static void miOverlayReparentWindow(WindowPtr, WindowPtr); -static void miOverlayRestackWindow(WindowPtr, WindowPtr); -static Bool miOverlayMarkOverlappedWindows(WindowPtr, WindowPtr, WindowPtr*); -static void miOverlayMarkUnrealizedWindow(WindowPtr, WindowPtr, Bool); -static int miOverlayValidateTree(WindowPtr, WindowPtr, VTKind); -static void miOverlayHandleExposures(WindowPtr); -static void miOverlayMoveWindow(WindowPtr, int, int, WindowPtr, VTKind); -static void miOverlayWindowExposures(WindowPtr, RegionPtr, RegionPtr); -static void miOverlayResizeWindow(WindowPtr, int, int, unsigned int, - unsigned int, WindowPtr); -static void miOverlayClearToBackground(WindowPtr, int, int, int, int, Bool); - -static void miOverlaySetShape(WindowPtr); -static void miOverlayChangeBorderWidth(WindowPtr, unsigned int); - -#define MIOVERLAY_GET_SCREEN_PRIVATE(pScreen) ((miOverlayScreenPtr) \ - dixLookupPrivate(&(pScreen)->devPrivates, miOverlayScreenKey)) -#define MIOVERLAY_GET_WINDOW_PRIVATE(pWin) ((miOverlayWindowPtr) \ - dixLookupPrivate(&(pWin)->devPrivates, miOverlayWindowKey)) -#define MIOVERLAY_GET_WINDOW_TREE(pWin) \ - (MIOVERLAY_GET_WINDOW_PRIVATE(pWin)->tree) - -#define IN_UNDERLAY(w) MIOVERLAY_GET_WINDOW_TREE(w) -#define IN_OVERLAY(w) !MIOVERLAY_GET_WINDOW_TREE(w) - -#define MARK_OVERLAY(w) miMarkWindow(w) -#define MARK_UNDERLAY(w) MarkUnderlayWindow(w) - -#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \ - HasBorder(w) && \ - (w)->backgroundState == ParentRelative) - -Bool -miInitOverlay( - ScreenPtr pScreen, - miOverlayInOverlayFunc inOverlayFunc, - miOverlayTransFunc transFunc -){ - miOverlayScreenPtr pScreenPriv; - - if(!inOverlayFunc || !transFunc) return FALSE; - - if(!dixRequestPrivate(miOverlayWindowKey, sizeof(miOverlayWindowRec))) - return FALSE; - - if(!(pScreenPriv = xalloc(sizeof(miOverlayScreenRec)))) - return FALSE; - - dixSetPrivate(&pScreen->devPrivates, miOverlayScreenKey, pScreenPriv); - - pScreenPriv->InOverlay = inOverlayFunc; - pScreenPriv->MakeTransparent = transFunc; - pScreenPriv->underlayMarked = FALSE; - - - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreenPriv->CreateWindow = pScreen->CreateWindow; - pScreenPriv->DestroyWindow = pScreen->DestroyWindow; - pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow; - pScreenPriv->RealizeWindow = pScreen->RealizeWindow; - - pScreen->CloseScreen = miOverlayCloseScreen; - pScreen->CreateWindow = miOverlayCreateWindow; - pScreen->DestroyWindow = miOverlayDestroyWindow; - pScreen->UnrealizeWindow = miOverlayUnrealizeWindow; - pScreen->RealizeWindow = miOverlayRealizeWindow; - - pScreen->ReparentWindow = miOverlayReparentWindow; - pScreen->RestackWindow = miOverlayRestackWindow; - pScreen->MarkOverlappedWindows = miOverlayMarkOverlappedWindows; - pScreen->MarkUnrealizedWindow = miOverlayMarkUnrealizedWindow; - pScreen->ValidateTree = miOverlayValidateTree; - pScreen->HandleExposures = miOverlayHandleExposures; - pScreen->MoveWindow = miOverlayMoveWindow; - pScreen->WindowExposures = miOverlayWindowExposures; - pScreen->ResizeWindow = miOverlayResizeWindow; - pScreen->MarkWindow = miOverlayMarkWindow; - pScreen->ClearToBackground = miOverlayClearToBackground; - pScreen->SetShape = miOverlaySetShape; - pScreen->ChangeBorderWidth = miOverlayChangeBorderWidth; - - return TRUE; -} - - -static Bool -miOverlayCloseScreen(int i, ScreenPtr pScreen) -{ - miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->CreateWindow = pScreenPriv->CreateWindow; - pScreen->DestroyWindow = pScreenPriv->DestroyWindow; - pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow; - pScreen->RealizeWindow = pScreenPriv->RealizeWindow; - - xfree(pScreenPriv); - - return (*pScreen->CloseScreen)(i, pScreen); -} - - -static Bool -miOverlayCreateWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - miOverlayWindowPtr pWinPriv = MIOVERLAY_GET_WINDOW_PRIVATE(pWin); - miOverlayTreePtr pTree = NULL; - Bool result = TRUE; - - pWinPriv->tree = NULL; - - if(!pWin->parent || !((*pScreenPriv->InOverlay)(pWin))) { - if(!(pTree = (miOverlayTreePtr)xcalloc(1, sizeof(miOverlayTreeRec)))) - return FALSE; - } - - if(pScreenPriv->CreateWindow) { - pScreen->CreateWindow = pScreenPriv->CreateWindow; - result = (*pScreen->CreateWindow)(pWin); - pScreen->CreateWindow = miOverlayCreateWindow; - } - - if (pTree) { - if(result) { - pTree->pWin = pWin; - pTree->visibility = VisibilityNotViewable; - pWinPriv->tree = pTree; - if(pWin->parent) { - REGION_NULL(pScreen, &(pTree->borderClip)); - REGION_NULL(pScreen, &(pTree->clipList)); - RebuildTree(pWin); - } else { - BoxRec fullBox; - fullBox.x1 = 0; - fullBox.y1 = 0; - fullBox.x2 = pScreen->width; - fullBox.y2 = pScreen->height; - REGION_INIT(pScreen, &(pTree->borderClip), &fullBox, 1); - REGION_INIT(pScreen, &(pTree->clipList), &fullBox, 1); - } - } else xfree(pTree); - } - - return TRUE; -} - - -static Bool -miOverlayDestroyWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - Bool result = TRUE; - - if (pTree) { - if(pTree->prevSib) - pTree->prevSib->nextSib = pTree->nextSib; - else if(pTree->parent) - pTree->parent->firstChild = pTree->nextSib; - - if(pTree->nextSib) - pTree->nextSib->prevSib = pTree->prevSib; - else if(pTree->parent) - pTree->parent->lastChild = pTree->prevSib; - - REGION_UNINIT(pScreen, &(pTree->borderClip)); - REGION_UNINIT(pScreen, &(pTree->clipList)); - xfree(pTree); - } - - if(pScreenPriv->DestroyWindow) { - pScreen->DestroyWindow = pScreenPriv->DestroyWindow; - result = (*pScreen->DestroyWindow)(pWin); - pScreen->DestroyWindow = miOverlayDestroyWindow; - } - - return result; -} - -static Bool -miOverlayUnrealizeWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - Bool result = TRUE; - - if(pTree) pTree->visibility = VisibilityNotViewable; - - if(pScreenPriv->UnrealizeWindow) { - pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow; - result = (*pScreen->UnrealizeWindow)(pWin); - pScreen->UnrealizeWindow = miOverlayUnrealizeWindow; - } - - return result; -} - - -static Bool -miOverlayRealizeWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - Bool result = TRUE; - - if(pScreenPriv->RealizeWindow) { - pScreen->RealizeWindow = pScreenPriv->RealizeWindow; - result = (*pScreen->RealizeWindow)(pWin); - pScreen->RealizeWindow = miOverlayRealizeWindow; - } - - /* we only need to catch the root window realization */ - - if(result && !pWin->parent && !((*pScreenPriv->InOverlay)(pWin))) - { - BoxRec box; - box.x1 = box.y1 = 0; - box.x2 = pWin->drawable.width; - box.y2 = pWin->drawable.height; - (*pScreenPriv->MakeTransparent)(pScreen, 1, &box); - } - - return result; -} - - -static void -miOverlayReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) -{ - if(IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) { - /* This could probably be more optimal */ - RebuildTree(WindowTable[pWin->drawable.pScreen->myNum]->firstChild); - } -} - -static void -miOverlayRestackWindow(WindowPtr pWin, WindowPtr oldNextSib) -{ - if(IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) { - /* This could probably be more optimal */ - RebuildTree(pWin); - } -} - - -static Bool -miOverlayMarkOverlappedWindows( - WindowPtr pWin, - WindowPtr pFirst, - WindowPtr *pLayerWin -){ - ScreenPtr pScreen = pWin->drawable.pScreen; - WindowPtr pChild, pLast; - Bool overMarked, underMarked, doUnderlay, markAll; - miOverlayTreePtr pTree = NULL, tLast, tChild; - BoxPtr box; - - overMarked = underMarked = markAll = FALSE; - - if(pLayerWin) *pLayerWin = pWin; /* hah! */ - - doUnderlay = (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)); - - box = REGION_EXTENTS(pScreen, &pWin->borderSize); - - if((pChild = pFirst)) { - pLast = pChild->parent->lastChild; - while (1) { - if (pChild == pWin) markAll = TRUE; - - if(doUnderlay && IN_UNDERLAY(pChild)) - pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); - - if(pChild->viewable) { - if (REGION_BROKEN (pScreen, &pChild->winSize)) - SetWinSize (pChild); - if (REGION_BROKEN (pScreen, &pChild->borderSize)) - SetBorderSize (pChild); - - if (markAll || - RECT_IN_REGION(pScreen, &pChild->borderSize, box)) - { - MARK_OVERLAY(pChild); - overMarked = TRUE; - if(doUnderlay && IN_UNDERLAY(pChild)) { - MARK_UNDERLAY(pChild); - underMarked = TRUE; - } - if (pChild->firstChild) { - pChild = pChild->firstChild; - continue; - } - } - } - while (!pChild->nextSib && (pChild != pLast)) { - pChild = pChild->parent; - if(doUnderlay && IN_UNDERLAY(pChild)) - pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); - } - - if(pChild == pWin) markAll = FALSE; - - if (pChild == pLast) break; - - pChild = pChild->nextSib; - } - if(overMarked) - MARK_OVERLAY(pWin->parent); - } - - if(doUnderlay && !pTree) { - if(!(pTree = MIOVERLAY_GET_WINDOW_TREE(pWin))) { - pChild = pWin->lastChild; - while(1) { - if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) - break; - - if(pChild->lastChild) { - pChild = pChild->lastChild; - continue; - } - - while(!pChild->prevSib) pChild = pChild->parent; - - pChild = pChild->prevSib; - } - } - } - - if(pTree && pTree->nextSib) { - tChild = pTree->parent->lastChild; - tLast = pTree->nextSib; - - while(1) { - if(tChild->pWin->viewable) { - if (REGION_BROKEN (pScreen, &tChild->pWin->winSize)) - SetWinSize (tChild->pWin); - if (REGION_BROKEN (pScreen, &tChild->pWin->borderSize)) - SetBorderSize (tChild->pWin); - - if(RECT_IN_REGION(pScreen, &(tChild->pWin->borderSize), box)) - { - MARK_UNDERLAY(tChild->pWin); - underMarked = TRUE; - } - } - - if(tChild->lastChild) { - tChild = tChild->lastChild; - continue; - } - - while(!tChild->prevSib && (tChild != tLast)) - tChild = tChild->parent; - - if(tChild == tLast) break; - - tChild = tChild->prevSib; - } - } - - if(underMarked) { - MARK_UNDERLAY(pTree->parent->pWin); - MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->underlayMarked = TRUE; - } - - return (underMarked || overMarked); -} - - -static void -miOverlayComputeClips( - WindowPtr pParent, - RegionPtr universe, - VTKind kind, - RegionPtr exposed -){ - ScreenPtr pScreen = pParent->drawable.pScreen; - int oldVis, newVis, dx, dy; - BoxRec borderSize; - RegionPtr borderVisible; - RegionRec childUniverse, childUnion; - miOverlayTreePtr tParent = MIOVERLAY_GET_WINDOW_TREE(pParent); - miOverlayTreePtr tChild; - Bool overlap; - - borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent); - borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent); - dx = (int) pParent->drawable.x + (int) pParent->drawable.width + - wBorderWidth(pParent); - if (dx > 32767) dx = 32767; - borderSize.x2 = dx; - dy = (int) pParent->drawable.y + (int) pParent->drawable.height + - wBorderWidth(pParent); - if (dy > 32767) dy = 32767; - borderSize.y2 = dy; - - oldVis = tParent->visibility; - switch (RECT_IN_REGION( pScreen, universe, &borderSize)) { - case rgnIN: - newVis = VisibilityUnobscured; - break; - case rgnPART: - newVis = VisibilityPartiallyObscured; - { - RegionPtr pBounding; - - if ((pBounding = wBoundingShape (pParent))) { - switch (miShapedWindowIn (pScreen, universe, pBounding, - &borderSize, - pParent->drawable.x, - pParent->drawable.y)) - { - case rgnIN: - newVis = VisibilityUnobscured; - break; - case rgnOUT: - newVis = VisibilityFullyObscured; - break; - } - } - } - break; - default: - newVis = VisibilityFullyObscured; - break; - } - tParent->visibility = newVis; - - dx = pParent->drawable.x - tParent->valdata->oldAbsCorner.x; - dy = pParent->drawable.y - tParent->valdata->oldAbsCorner.y; - - switch (kind) { - case VTMap: - case VTStack: - case VTUnmap: - break; - case VTMove: - if ((oldVis == newVis) && - ((oldVis == VisibilityFullyObscured) || - (oldVis == VisibilityUnobscured))) - { - tChild = tParent; - while (1) { - if (tChild->pWin->viewable) { - if (tChild->visibility != VisibilityFullyObscured) { - REGION_TRANSLATE( pScreen, &tChild->borderClip, dx, dy); - REGION_TRANSLATE( pScreen, &tChild->clipList, dx, dy); - - tChild->pWin->drawable.serialNumber = - NEXT_SERIAL_NUMBER; - if (pScreen->ClipNotify) - (* pScreen->ClipNotify) (tChild->pWin, dx, dy); - } - if (tChild->valdata) { - REGION_NULL(pScreen, &tChild->valdata->borderExposed); - if (HasParentRelativeBorder(tChild->pWin)){ - REGION_SUBTRACT(pScreen, - &tChild->valdata->borderExposed, - &tChild->borderClip, - &tChild->pWin->winSize); - } - REGION_NULL(pScreen, &tChild->valdata->exposed); - } - if (tChild->firstChild) { - tChild = tChild->firstChild; - continue; - } - } - while (!tChild->nextSib && (tChild != tParent)) - tChild = tChild->parent; - if (tChild == tParent) - break; - tChild = tChild->nextSib; - } - return; - } - /* fall through */ - default: - if (dx || dy) { - REGION_TRANSLATE( pScreen, &tParent->borderClip, dx, dy); - REGION_TRANSLATE( pScreen, &tParent->clipList, dx, dy); - } - break; - case VTBroken: - REGION_EMPTY (pScreen, &tParent->borderClip); - REGION_EMPTY (pScreen, &tParent->clipList); - break; - } - - borderVisible = tParent->valdata->borderVisible; - REGION_NULL(pScreen, &tParent->valdata->borderExposed); - REGION_NULL(pScreen, &tParent->valdata->exposed); - - if (HasBorder (pParent)) { - if (borderVisible) { - REGION_SUBTRACT( pScreen, exposed, universe, borderVisible); - REGION_DESTROY( pScreen, borderVisible); - } else - REGION_SUBTRACT( pScreen, exposed, universe, &tParent->borderClip); - - if (HasParentRelativeBorder(pParent) && (dx || dy)) - REGION_SUBTRACT( pScreen, &tParent->valdata->borderExposed, - universe, &pParent->winSize); - else - REGION_SUBTRACT( pScreen, &tParent->valdata->borderExposed, - exposed, &pParent->winSize); - - REGION_COPY( pScreen, &tParent->borderClip, universe); - REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize); - } - else - REGION_COPY( pScreen, &tParent->borderClip, universe); - - if ((tChild = tParent->firstChild) && pParent->mapped) { - REGION_NULL(pScreen, &childUniverse); - REGION_NULL(pScreen, &childUnion); - - for (; tChild; tChild = tChild->nextSib) { - if (tChild->pWin->viewable) - REGION_APPEND( pScreen, &childUnion, &tChild->pWin->borderSize); - } - - REGION_VALIDATE( pScreen, &childUnion, &overlap); - - for (tChild = tParent->firstChild; - tChild; - tChild = tChild->nextSib) - { - if (tChild->pWin->viewable) { - if (tChild->valdata) { - REGION_INTERSECT( pScreen, &childUniverse, universe, - &tChild->pWin->borderSize); - miOverlayComputeClips (tChild->pWin, &childUniverse, - kind, exposed); - } - if (overlap) - REGION_SUBTRACT( pScreen, universe, universe, - &tChild->pWin->borderSize); - } - } - if (!overlap) - REGION_SUBTRACT( pScreen, universe, universe, &childUnion); - REGION_UNINIT( pScreen, &childUnion); - REGION_UNINIT( pScreen, &childUniverse); - } - - if (oldVis == VisibilityFullyObscured || - oldVis == VisibilityNotViewable) - { - REGION_COPY( pScreen, &tParent->valdata->exposed, universe); - } - else if (newVis != VisibilityFullyObscured && - newVis != VisibilityNotViewable) - { - REGION_SUBTRACT( pScreen, &tParent->valdata->exposed, - universe, &tParent->clipList); - } - - /* HACK ALERT - copying contents of regions, instead of regions */ - { - RegionRec tmp; - - tmp = tParent->clipList; - tParent->clipList = *universe; - *universe = tmp; - } - - pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; - - if (pScreen->ClipNotify) - (* pScreen->ClipNotify) (pParent, dx, dy); -} - - -static void -miOverlayMarkWindow(WindowPtr pWin) -{ - miOverlayTreePtr pTree = NULL; - WindowPtr pChild, pGrandChild; - - miMarkWindow(pWin); - - /* look for UnmapValdata among immediate children */ - - if(!(pChild = pWin->firstChild)) return; - - for( ; pChild; pChild = pChild->nextSib) { - if(pChild->valdata == UnmapValData) { - if(IN_UNDERLAY(pChild)) { - pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); - pTree->valdata = (miOverlayValDataPtr)UnmapValData; - continue; - } else { - if(!(pGrandChild = pChild->firstChild)) - continue; - - while(1) { - if(IN_UNDERLAY(pGrandChild)) { - pTree = MIOVERLAY_GET_WINDOW_TREE(pGrandChild); - pTree->valdata = (miOverlayValDataPtr)UnmapValData; - } else if(pGrandChild->firstChild) { - pGrandChild = pGrandChild->firstChild; - continue; - } - - while(!pGrandChild->nextSib && (pGrandChild != pChild)) - pGrandChild = pGrandChild->parent; - - if(pChild == pGrandChild) break; - - pGrandChild = pGrandChild->nextSib; - } - } - } - } - - if(pTree) { - MARK_UNDERLAY(pTree->parent->pWin); - MIOVERLAY_GET_SCREEN_PRIVATE( - pWin->drawable.pScreen)->underlayMarked = TRUE; - } -} - -static void -miOverlayMarkUnrealizedWindow( - WindowPtr pChild, - WindowPtr pWin, - Bool fromConfigure -){ - if ((pChild != pWin) || fromConfigure) { - miOverlayTreePtr pTree; - - REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); - if (pChild->drawable.pScreen->ClipNotify) - (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); - REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); - if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) { - if(pTree->valdata != (miOverlayValDataPtr)UnmapValData) { - REGION_EMPTY(pChild->drawable.pScreen, &pTree->clipList); - REGION_EMPTY(pChild->drawable.pScreen, &pTree->borderClip); - } - } - } -} - - -static int -miOverlayValidateTree( - WindowPtr pParent, - WindowPtr pChild, /* first child effected */ - VTKind kind -){ - ScreenPtr pScreen = pParent->drawable.pScreen; - miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - RegionRec totalClip, childClip, exposed; - miOverlayTreePtr tParent, tChild, tWin; - Bool overlap; - WindowPtr newParent; - - if(!pPriv->underlayMarked) - goto SKIP_UNDERLAY; - - if (!pChild) pChild = pParent->firstChild; - - REGION_NULL(pScreen, &totalClip); - REGION_NULL(pScreen, &childClip); - REGION_NULL(pScreen, &exposed); - - newParent = pParent; - - while(IN_OVERLAY(newParent)) - newParent = newParent->parent; - - tParent = MIOVERLAY_GET_WINDOW_TREE(newParent); - - if(IN_UNDERLAY(pChild)) - tChild = MIOVERLAY_GET_WINDOW_TREE(pChild); - else - tChild = tParent->firstChild; - - if (REGION_BROKEN (pScreen, &tParent->clipList) && - !REGION_BROKEN (pScreen, &tParent->borderClip)) - { - kind = VTBroken; - REGION_COPY (pScreen, &totalClip, &tParent->borderClip); - REGION_INTERSECT (pScreen, &totalClip, &totalClip, - &tParent->pWin->winSize); - - for (tWin = tParent->firstChild; tWin != tChild; tWin = tWin->nextSib) { - if (tWin->pWin->viewable) - REGION_SUBTRACT (pScreen, &totalClip, &totalClip, - &tWin->pWin->borderSize); - } - REGION_EMPTY (pScreen, &tParent->clipList); - } else { - for(tWin = tChild; tWin; tWin = tWin->nextSib) { - if(tWin->valdata) - REGION_APPEND(pScreen, &totalClip, &tWin->borderClip); - } - REGION_VALIDATE(pScreen, &totalClip, &overlap); - } - - if(kind != VTStack) - REGION_UNION(pScreen, &totalClip, &totalClip, &tParent->clipList); - - for(tWin = tChild; tWin; tWin = tWin->nextSib) { - if(tWin->valdata) { - if(tWin->pWin->viewable) { - REGION_INTERSECT(pScreen, &childClip, &totalClip, - &tWin->pWin->borderSize); - miOverlayComputeClips(tWin->pWin, &childClip, kind, &exposed); - REGION_SUBTRACT(pScreen, &totalClip, &totalClip, - &tWin->pWin->borderSize); - } else { /* Means we are unmapping */ - REGION_EMPTY(pScreen, &tWin->clipList); - REGION_EMPTY( pScreen, &tWin->borderClip); - tWin->valdata = NULL; - } - } - } - - REGION_UNINIT(pScreen, &childClip); - - if(!((*pPriv->InOverlay)(newParent))) { - REGION_NULL(pScreen, &tParent->valdata->exposed); - REGION_NULL(pScreen, &tParent->valdata->borderExposed); - } - - switch (kind) { - case VTStack: - break; - default: - if(!((*pPriv->InOverlay)(newParent))) - REGION_SUBTRACT(pScreen, &tParent->valdata->exposed, &totalClip, - &tParent->clipList); - /* fall through */ - case VTMap: - REGION_COPY( pScreen, &tParent->clipList, &totalClip); - if(!((*pPriv->InOverlay)(newParent))) - newParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; - break; - } - - REGION_UNINIT( pScreen, &totalClip); - REGION_UNINIT( pScreen, &exposed); - -SKIP_UNDERLAY: - - miValidateTree(pParent, pChild, kind); - - return 1; -} - - -static void -miOverlayHandleExposures(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - WindowPtr pChild; - ValidatePtr val; - void (* WindowExposures)(WindowPtr, RegionPtr, RegionPtr); - - WindowExposures = pWin->drawable.pScreen->WindowExposures; - if(pPriv->underlayMarked) { - miOverlayTreePtr pTree; - miOverlayValDataPtr mival; - - pChild = pWin; - while(IN_OVERLAY(pChild)) - pChild = pChild->parent; - - pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); - - while (1) { - if((mival = pTree->valdata)) { - if(!((*pPriv->InOverlay)(pTree->pWin))) { - if (REGION_NOTEMPTY(pScreen, &mival->borderExposed)) { - miPaintWindow(pTree->pWin, &mival->borderExposed, - PW_BORDER); - } - REGION_UNINIT(pScreen, &mival->borderExposed); - - (*WindowExposures)(pTree->pWin,&mival->exposed,NullRegion); - REGION_UNINIT(pScreen, &mival->exposed); - } - xfree(mival); - pTree->valdata = NULL; - if (pTree->firstChild) { - pTree = pTree->firstChild; - continue; - } - } - while (!pTree->nextSib && (pTree->pWin != pChild)) - pTree = pTree->parent; - if (pTree->pWin == pChild) - break; - pTree = pTree->nextSib; - } - pPriv->underlayMarked = FALSE; - } - - pChild = pWin; - while (1) { - if ( (val = pChild->valdata) ) { - if(!((*pPriv->InOverlay)(pChild))) { - REGION_UNION(pScreen, &val->after.exposed, &val->after.exposed, - &val->after.borderExposed); - - if (REGION_NOTEMPTY(pScreen, &val->after.exposed)) { - (*(MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent))( - pScreen, - REGION_NUM_RECTS(&val->after.exposed), - REGION_RECTS(&val->after.exposed)); - } - } else { - if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) { - miPaintWindow(pChild, &val->after.borderExposed, - PW_BORDER); - } - (*WindowExposures)(pChild, &val->after.exposed, NullRegion); - } - REGION_UNINIT(pScreen, &val->after.borderExposed); - REGION_UNINIT(pScreen, &val->after.exposed); - xfree(val); - pChild->valdata = NULL; - if (pChild->firstChild) - { - pChild = pChild->firstChild; - continue; - } - } - while (!pChild->nextSib && (pChild != pWin)) - pChild = pChild->parent; - if (pChild == pWin) - break; - pChild = pChild->nextSib; - } -} - - -static void -miOverlayMoveWindow( - WindowPtr pWin, - int x, - int y, - WindowPtr pNextSib, - VTKind kind -){ - ScreenPtr pScreen = pWin->drawable.pScreen; - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - WindowPtr pParent, windowToValidate; - Bool WasViewable = (Bool)(pWin->viewable); - short bw; - RegionRec overReg, underReg; - DDXPointRec oldpt; - - if (!(pParent = pWin->parent)) - return ; - bw = wBorderWidth (pWin); - - oldpt.x = pWin->drawable.x; - oldpt.y = pWin->drawable.y; - if (WasViewable) { - REGION_NULL(pScreen, &overReg); - REGION_NULL(pScreen, &underReg); - if(pTree) { - REGION_COPY(pScreen, &overReg, &pWin->borderClip); - REGION_COPY(pScreen, &underReg, &pTree->borderClip); - } else { - REGION_COPY(pScreen, &overReg, &pWin->borderClip); - CollectUnderlayChildrenRegions(pWin, &underReg); - } - (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL); - } - pWin->origin.x = x + (int)bw; - pWin->origin.y = y + (int)bw; - x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; - y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; - - SetWinSize (pWin); - SetBorderSize (pWin); - - (*pScreen->PositionWindow)(pWin, x, y); - - windowToValidate = MoveWindowInStack(pWin, pNextSib); - - ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); - - if (WasViewable) { - miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - (*pScreen->MarkOverlappedWindows) (pWin, windowToValidate, NULL); - - - (*pScreen->ValidateTree)(pWin->parent, NullWindow, kind); - if(REGION_NOTEMPTY(pScreen, &underReg)) { - pPriv->copyUnderlay = TRUE; - (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, &underReg); - } - REGION_UNINIT(pScreen, &underReg); - if(REGION_NOTEMPTY(pScreen, &overReg)) { - pPriv->copyUnderlay = FALSE; - (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, &overReg); - } - REGION_UNINIT(pScreen, &overReg); - (*pScreen->HandleExposures)(pWin->parent); - - if (pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pWin->parent, NullWindow, kind); - } - if (pWin->realized) - WindowsRestructured (); -} - -#ifndef RECTLIMIT -#define RECTLIMIT 25 -#endif - -static void -miOverlayWindowExposures( - WindowPtr pWin, - RegionPtr prgn, - RegionPtr other_exposed -){ - RegionPtr exposures = prgn; - ScreenPtr pScreen = pWin->drawable.pScreen; - - if ((prgn && !REGION_NIL(prgn)) || - (exposures && !REGION_NIL(exposures)) || other_exposed) - { - RegionRec expRec; - int clientInterested; - - clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & - ExposureMask; - if (other_exposed) { - if (exposures) { - REGION_UNION(pScreen, other_exposed, exposures, other_exposed); - if (exposures != prgn) - REGION_DESTROY(pScreen, exposures); - } - exposures = other_exposed; - } - if (clientInterested && exposures && - (REGION_NUM_RECTS(exposures) > RECTLIMIT)) - { - miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - BoxRec box; - - box = *REGION_EXTENTS(pScreen, exposures); - if (exposures == prgn) { - exposures = &expRec; - REGION_INIT(pScreen, exposures, &box, 1); - REGION_RESET(pScreen, prgn, &box); - } else { - REGION_RESET(pScreen, exposures, &box); - REGION_UNION(pScreen, prgn, prgn, exposures); - } - /* This is the only reason why we are replacing mi's version - of this file */ - - if(!((*pPriv->InOverlay)(pWin))) { - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - REGION_INTERSECT(pScreen, prgn, prgn, &pTree->clipList); - } else - REGION_INTERSECT(pScreen, prgn, prgn, &pWin->clipList); - } - if (prgn && !REGION_NIL(prgn)) - miPaintWindow(pWin, prgn, PW_BACKGROUND); - if (clientInterested && exposures && !REGION_NIL(exposures)) - miSendExposures(pWin, exposures, - pWin->drawable.x, pWin->drawable.y); - if (exposures == &expRec) { - REGION_UNINIT(pScreen, exposures); - } - else if (exposures && exposures != prgn && exposures != other_exposed) - REGION_DESTROY(pScreen, exposures); - if (prgn) - REGION_EMPTY(pScreen, prgn); - } - else if (exposures && exposures != prgn) - REGION_DESTROY(pScreen, exposures); -} - - -typedef struct { - RegionPtr over; - RegionPtr under; -} miOverlayTwoRegions; - -static int -miOverlayRecomputeExposures ( - WindowPtr pWin, - pointer value -){ - ScreenPtr pScreen; - miOverlayTwoRegions *pValid = (miOverlayTwoRegions*)value; - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - - /* This prevents warning about pScreen not being used. */ - pWin->drawable.pScreen = pScreen = pWin->drawable.pScreen; - - if (pWin->valdata) { - /* - * compute exposed regions of this window - */ - REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, - &pWin->clipList, pValid->over); - /* - * compute exposed regions of the border - */ - REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, - &pWin->borderClip, &pWin->winSize); - REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, - &pWin->valdata->after.borderExposed, pValid->over); - } - - if(pTree && pTree->valdata) { - REGION_SUBTRACT(pScreen, &pTree->valdata->exposed, - &pTree->clipList, pValid->under); - REGION_SUBTRACT(pScreen, &pTree->valdata->borderExposed, - &pTree->borderClip, &pWin->winSize); - REGION_SUBTRACT(pScreen, &pTree->valdata->borderExposed, - &pTree->valdata->borderExposed, pValid->under); - } else if (!pWin->valdata) - return WT_NOMATCH; - - return WT_WALKCHILDREN; -} - -static void -miOverlayResizeWindow( - WindowPtr pWin, - int x, int y, - unsigned int w, unsigned int h, - WindowPtr pSib -){ - ScreenPtr pScreen = pWin->drawable.pScreen; - WindowPtr pParent; - miOverlayTreePtr tChild, pTree; - Bool WasViewable = (Bool)(pWin->viewable); - unsigned short width = pWin->drawable.width; - unsigned short height = pWin->drawable.height; - short oldx = pWin->drawable.x; - short oldy = pWin->drawable.y; - int bw = wBorderWidth (pWin); - short dw, dh; - DDXPointRec oldpt; - RegionPtr oldRegion = NULL, oldRegion2 = NULL; - WindowPtr pFirstChange; - WindowPtr pChild; - RegionPtr gravitate[StaticGravity + 1]; - RegionPtr gravitate2[StaticGravity + 1]; - unsigned g; - int nx, ny; /* destination x,y */ - int newx, newy; /* new inner window position */ - RegionPtr pRegion = NULL; - RegionPtr destClip, destClip2; - RegionPtr oldWinClip = NULL, oldWinClip2 = NULL; - RegionPtr borderVisible = NullRegion; - RegionPtr borderVisible2 = NullRegion; - Bool shrunk = FALSE; /* shrunk in an inner dimension */ - Bool moved = FALSE; /* window position changed */ - Bool doUnderlay; - - /* if this is a root window, can't be resized */ - if (!(pParent = pWin->parent)) - return ; - - pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - doUnderlay = ((pTree) || HasUnderlayChildren(pWin)); - newx = pParent->drawable.x + x + bw; - newy = pParent->drawable.y + y + bw; - if (WasViewable) - { - /* - * save the visible region of the window - */ - oldRegion = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, oldRegion, &pWin->winSize); - if(doUnderlay) { - oldRegion2 = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, oldRegion2, &pWin->winSize); - } - - /* - * categorize child windows into regions to be moved - */ - for (g = 0; g <= StaticGravity; g++) - gravitate[g] = gravitate2[g] = NULL; - for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { - g = pChild->winGravity; - if (g != UnmapGravity) { - if (!gravitate[g]) - gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); - REGION_UNION(pScreen, gravitate[g], - gravitate[g], &pChild->borderClip); - - if(doUnderlay) { - if (!gravitate2[g]) - gravitate2[g] = REGION_CREATE(pScreen, NullBox, 0); - - if((tChild = MIOVERLAY_GET_WINDOW_TREE(pChild))) { - REGION_UNION(pScreen, gravitate2[g], - gravitate2[g], &tChild->borderClip); - } else - CollectUnderlayChildrenRegions(pChild, gravitate2[g]); - } - } else { - UnmapWindow(pChild, TRUE); - } - } - (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL); - - - oldWinClip = oldWinClip2 = NULL; - if (pWin->bitGravity != ForgetGravity) { - oldWinClip = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, oldWinClip, &pWin->clipList); - if(pTree) { - oldWinClip2 = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, oldWinClip2, &pTree->clipList); - } - } - /* - * if the window is changing size, borderExposed - * can't be computed correctly without some help. - */ - if (pWin->drawable.height > h || pWin->drawable.width > w) - shrunk = TRUE; - - if (newx != oldx || newy != oldy) - moved = TRUE; - - if ((pWin->drawable.height != h || pWin->drawable.width != w) && - HasBorder (pWin)) - { - borderVisible = REGION_CREATE(pScreen, NullBox, 1); - if(pTree) - borderVisible2 = REGION_CREATE(pScreen, NullBox, 1); - /* for tiled borders, we punt and draw the whole thing */ - if (pWin->borderIsPixel || !moved) - { - if (shrunk || moved) - REGION_SUBTRACT(pScreen, borderVisible, - &pWin->borderClip, - &pWin->winSize); - else - REGION_COPY(pScreen, borderVisible, - &pWin->borderClip); - if(pTree) { - if (shrunk || moved) - REGION_SUBTRACT(pScreen, borderVisible, - &pTree->borderClip, - &pWin->winSize); - else - REGION_COPY(pScreen, borderVisible, - &pTree->borderClip); - } - } - } - } - pWin->origin.x = x + bw; - pWin->origin.y = y + bw; - pWin->drawable.height = h; - pWin->drawable.width = w; - - x = pWin->drawable.x = newx; - y = pWin->drawable.y = newy; - - SetWinSize (pWin); - SetBorderSize (pWin); - - dw = (int)w - (int)width; - dh = (int)h - (int)height; - ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); - - /* let the hardware adjust background and border pixmaps, if any */ - (*pScreen->PositionWindow)(pWin, x, y); - - pFirstChange = MoveWindowInStack(pWin, pSib); - - if (WasViewable) { - pRegion = REGION_CREATE(pScreen, NullBox, 1); - - (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, NULL); - - pWin->valdata->before.resized = TRUE; - pWin->valdata->before.borderVisible = borderVisible; - if(pTree) - pTree->valdata->borderVisible = borderVisible2; - - - (*pScreen->ValidateTree)(pWin->parent, pFirstChange, VTOther); - /* - * the entire window is trashed unless bitGravity - * recovers portions of it - */ - REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); - if(pTree) - REGION_COPY(pScreen, &pTree->valdata->exposed, &pTree->clipList); - } - - GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); - - if (WasViewable) { - miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - miOverlayTwoRegions TwoRegions; - - /* avoid the border */ - if (HasBorder (pWin)) { - int offx, offy, dx, dy; - - /* kruft to avoid double translates for each gravity */ - offx = 0; - offy = 0; - for (g = 0; g <= StaticGravity; g++) { - if (!gravitate[g] && !gravitate2[g]) - continue; - - /* align winSize to gravitate[g]. - * winSize is in new coordinates, - * gravitate[g] is still in old coordinates */ - GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); - - dx = (oldx - nx) - offx; - dy = (oldy - ny) - offy; - if (dx || dy) { - REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); - offx += dx; - offy += dy; - } - if(gravitate[g]) - REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], - &pWin->winSize); - if(gravitate2[g]) - REGION_INTERSECT(pScreen, gravitate2[g], gravitate2[g], - &pWin->winSize); - } - /* get winSize back where it belongs */ - if (offx || offy) - REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); - } - /* - * add screen bits to the appropriate bucket - */ - - if (oldWinClip2) - { - REGION_COPY(pScreen, pRegion, oldWinClip2); - REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); - REGION_INTERSECT(pScreen, oldWinClip2, pRegion, &pTree->clipList); - - for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) { - if (gravitate2[g]) - REGION_SUBTRACT(pScreen, oldWinClip2, oldWinClip2, - gravitate2[g]); - } - REGION_TRANSLATE(pScreen, oldWinClip2, oldx - nx, oldy - ny); - g = pWin->bitGravity; - if (!gravitate2[g]) - gravitate2[g] = oldWinClip2; - else { - REGION_UNION(pScreen,gravitate2[g],gravitate2[g],oldWinClip2); - REGION_DESTROY(pScreen, oldWinClip2); - } - } - - if (oldWinClip) - { - /* - * clip to new clipList - */ - REGION_COPY(pScreen, pRegion, oldWinClip); - REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); - REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); - /* - * don't step on any gravity bits which will be copied after this - * region. Note -- this assumes that the regions will be copied - * in gravity order. - */ - for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) { - if (gravitate[g]) - REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, - gravitate[g]); - } - REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); - g = pWin->bitGravity; - if (!gravitate[g]) - gravitate[g] = oldWinClip; - else { - REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); - REGION_DESTROY(pScreen, oldWinClip); - } - } - - /* - * move the bits on the screen - */ - - destClip = destClip2 = NULL; - - for (g = 0; g <= StaticGravity; g++) { - if (!gravitate[g] && !gravitate2[g]) - continue; - - GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); - - oldpt.x = oldx + (x - nx); - oldpt.y = oldy + (y - ny); - - /* Note that gravitate[g] is *translated* by CopyWindow */ - - /* only copy the remaining useful bits */ - - if(gravitate[g]) - REGION_INTERSECT(pScreen, gravitate[g], - gravitate[g], oldRegion); - if(gravitate2[g]) - REGION_INTERSECT(pScreen, gravitate2[g], - gravitate2[g], oldRegion2); - - /* clip to not overwrite already copied areas */ - - if (destClip && gravitate[g]) { - REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); - REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); - REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); - } - if (destClip2 && gravitate2[g]) { - REGION_TRANSLATE(pScreen, destClip2, oldpt.x - x, oldpt.y - y); - REGION_SUBTRACT(pScreen,gravitate2[g],gravitate2[g],destClip2); - REGION_TRANSLATE(pScreen, destClip2, x - oldpt.x, y - oldpt.y); - } - - /* and move those bits */ - - if (oldpt.x != x || oldpt.y != y) { - if(gravitate2[g]) { - pPriv->copyUnderlay = TRUE; - (*pWin->drawable.pScreen->CopyWindow)( - pWin, oldpt, gravitate2[g]); - } - if(gravitate[g]) { - pPriv->copyUnderlay = FALSE; - (*pWin->drawable.pScreen->CopyWindow)( - pWin, oldpt, gravitate[g]); - } - } - - /* remove any overwritten bits from the remaining useful bits */ - - if(gravitate[g]) - REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); - if(gravitate2[g]) - REGION_SUBTRACT(pScreen, oldRegion2, oldRegion2, gravitate2[g]); - - /* - * recompute exposed regions of child windows - */ - - - for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { - if (pChild->winGravity != g) - continue; - - TwoRegions.over = gravitate[g]; - TwoRegions.under = gravitate2[g]; - - TraverseTree (pChild, miOverlayRecomputeExposures, - (pointer)(&TwoRegions)); - } - - /* - * remove the successfully copied regions of the - * window from its exposed region - */ - - if (g == pWin->bitGravity) { - if(gravitate[g]) - REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, - &pWin->valdata->after.exposed, gravitate[g]); - if(gravitate2[g] && pTree) - REGION_SUBTRACT(pScreen, &pTree->valdata->exposed, - &pTree->valdata->exposed, gravitate2[g]); - } - if(gravitate[g]) { - if (!destClip) - destClip = gravitate[g]; - else { - REGION_UNION(pScreen, destClip, destClip, gravitate[g]); - REGION_DESTROY(pScreen, gravitate[g]); - } - } - if(gravitate2[g]) { - if (!destClip2) - destClip2 = gravitate2[g]; - else { - REGION_UNION(pScreen, destClip2, destClip2, gravitate2[g]); - REGION_DESTROY(pScreen, gravitate2[g]); - } - } - } - - REGION_DESTROY(pScreen, pRegion); - REGION_DESTROY(pScreen, oldRegion); - if(doUnderlay) - REGION_DESTROY(pScreen, oldRegion2); - if (destClip) - REGION_DESTROY(pScreen, destClip); - if (destClip2) - REGION_DESTROY(pScreen, destClip2); - (*pScreen->HandleExposures)(pWin->parent); - if (pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pWin->parent, pFirstChange, VTOther); - } - if (pWin->realized) - WindowsRestructured (); -} - - -static void -miOverlaySetShape(WindowPtr pWin) -{ - Bool WasViewable = (Bool)(pWin->viewable); - ScreenPtr pScreen = pWin->drawable.pScreen; - - if (WasViewable) { - (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL); - - if (HasBorder (pWin)) { - RegionPtr borderVisible; - - borderVisible = REGION_CREATE(pScreen, NullBox, 1); - REGION_SUBTRACT(pScreen, borderVisible, - &pWin->borderClip, &pWin->winSize); - pWin->valdata->before.borderVisible = borderVisible; - pWin->valdata->before.resized = TRUE; - if(IN_UNDERLAY(pWin)) { - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - RegionPtr borderVisible2; - - borderVisible2 = REGION_CREATE(pScreen, NULL, 1); - REGION_SUBTRACT(pScreen, borderVisible2, - &pTree->borderClip, &pWin->winSize); - pTree->valdata->borderVisible = borderVisible2; - } - } - } - - SetWinSize (pWin); - SetBorderSize (pWin); - - ResizeChildrenWinSize(pWin, 0, 0, 0, 0); - - if (WasViewable) { - (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL); - - - (*pScreen->ValidateTree)(pWin->parent, NullWindow, VTOther); - } - - if (WasViewable) { - (*pScreen->HandleExposures)(pWin->parent); - if (pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pWin->parent, NullWindow, VTOther); - } - if (pWin->realized) - WindowsRestructured (); - CheckCursorConfinement(pWin); -} - - - -static void -miOverlayChangeBorderWidth( - WindowPtr pWin, - unsigned int width -){ - int oldwidth; - ScreenPtr pScreen; - Bool WasViewable = (Bool)(pWin->viewable); - Bool HadBorder; - - oldwidth = wBorderWidth (pWin); - if (oldwidth == width) - return; - HadBorder = HasBorder(pWin); - pScreen = pWin->drawable.pScreen; - if (WasViewable && (width < oldwidth)) - (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL); - - pWin->borderWidth = width; - SetBorderSize (pWin); - - if (WasViewable) { - if (width > oldwidth) { - (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL); - - if (HadBorder) { - RegionPtr borderVisible; - borderVisible = REGION_CREATE(pScreen, NULL, 1); - REGION_SUBTRACT(pScreen, borderVisible, - &pWin->borderClip, &pWin->winSize); - pWin->valdata->before.borderVisible = borderVisible; - if(IN_UNDERLAY(pWin)) { - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - RegionPtr borderVisible2; - - borderVisible2 = REGION_CREATE(pScreen, NULL, 1); - REGION_SUBTRACT(pScreen, borderVisible2, - &pTree->borderClip, &pWin->winSize); - pTree->valdata->borderVisible = borderVisible2; - } - } - } - (*pScreen->ValidateTree)(pWin->parent, pWin, VTOther); - (*pScreen->HandleExposures)(pWin->parent); - - if (pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pWin->parent, pWin, VTOther); - } - if (pWin->realized) - WindowsRestructured (); -} - -/* We need this as an addition since the xf86 common code doesn't - know about the second tree which is static to this file. */ - -void -miOverlaySetRootClip(ScreenPtr pScreen, Bool enable) -{ - WindowPtr pRoot = WindowTable[pScreen->myNum]; - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pRoot); - - MARK_UNDERLAY(pRoot); - - if(enable) { - BoxRec box; - - box.x1 = 0; - box.y1 = 0; - box.x2 = pScreen->width; - box.y2 = pScreen->height; - - REGION_RESET(pScreen, &pTree->borderClip, &box); - } else - REGION_EMPTY(pScreen, &pTree->borderClip); - - REGION_BREAK(pScreen, &pTree->clipList); -} - -static void -miOverlayClearToBackground( - WindowPtr pWin, - int x, int y, - int w, int h, - Bool generateExposures -) -{ - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - BoxRec box; - RegionRec reg; - RegionPtr pBSReg = NullRegion; - ScreenPtr pScreen = pWin->drawable.pScreen; - miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); - RegionPtr clipList; - BoxPtr extents; - int x1, y1, x2, y2; - - x1 = pWin->drawable.x + x; - y1 = pWin->drawable.y + y; - if (w) - x2 = x1 + (int) w; - else - x2 = x1 + (int) pWin->drawable.width - (int) x; - if (h) - y2 = y1 + h; - else - y2 = y1 + (int) pWin->drawable.height - (int) y; - - clipList = ((*pScreenPriv->InOverlay)(pWin)) ? &pWin->clipList : - &pTree->clipList; - - extents = REGION_EXTENTS(pScreen, clipList); - - if (x1 < extents->x1) x1 = extents->x1; - if (x2 > extents->x2) x2 = extents->x2; - if (y1 < extents->y1) y1 = extents->y1; - if (y2 > extents->y2) y2 = extents->y2; - - if (x2 <= x1 || y2 <= y1) - x2 = x1 = y2 = y1 = 0; - - box.x1 = x1; box.x2 = x2; - box.y1 = y1; box.y2 = y2; - - REGION_INIT(pScreen, ®, &box, 1); - - REGION_INTERSECT(pScreen, ®, ®, clipList); - if (generateExposures) - (*pScreen->WindowExposures)(pWin, ®, pBSReg); - else if (pWin->backgroundState != None) - miPaintWindow(pWin, ®, PW_BACKGROUND); - REGION_UNINIT(pScreen, ®); - if (pBSReg) - REGION_DESTROY(pScreen, pBSReg); -} - - -/****************************************************************/ - -/* not used */ -Bool -miOverlayGetPrivateClips( - WindowPtr pWin, - RegionPtr *borderClip, - RegionPtr *clipList -){ - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - - if(pTree) { - *borderClip = &(pTree->borderClip); - *clipList = &(pTree->clipList); - return TRUE; - } - - *borderClip = *clipList = NULL; - - return FALSE; -} - -void -miOverlaySetTransFunction ( - ScreenPtr pScreen, - miOverlayTransFunc transFunc -){ - MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc; -} - -Bool -miOverlayCopyUnderlay(ScreenPtr pScreen) -{ - return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay; -} - -void -miOverlayComputeCompositeClip(GCPtr pGC, WindowPtr pWin) -{ - ScreenPtr pScreen = pGC->pScreen; - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - RegionPtr pregWin; - Bool freeTmpClip, freeCompClip; - - if(!pTree) { - miComputeCompositeClip(pGC, &pWin->drawable); - return; - } - - if (pGC->subWindowMode == IncludeInferiors) { - pregWin = REGION_CREATE(pScreen, NullBox, 1); - freeTmpClip = TRUE; - if (pWin->parent || (screenIsSaved != SCREEN_SAVER_ON) || - !HasSaverWindow (pScreen->myNum)) - { - REGION_INTERSECT(pScreen,pregWin,&pTree->borderClip,&pWin->winSize); - } - } else { - pregWin = &pTree->clipList; - freeTmpClip = FALSE; - } - freeCompClip = pGC->freeCompClip; - if (pGC->clientClipType == CT_NONE) { - if (freeCompClip) - REGION_DESTROY(pScreen, pGC->pCompositeClip); - pGC->pCompositeClip = pregWin; - pGC->freeCompClip = freeTmpClip; - } else { - REGION_TRANSLATE(pScreen, pGC->clientClip, - pWin->drawable.x + pGC->clipOrg.x, - pWin->drawable.y + pGC->clipOrg.y); - - if (freeCompClip) { - REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip, - pregWin, pGC->clientClip); - if (freeTmpClip) - REGION_DESTROY(pScreen, pregWin); - } else if (freeTmpClip) { - REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip); - pGC->pCompositeClip = pregWin; - } else { - pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0); - REGION_INTERSECT(pScreen, pGC->pCompositeClip, - pregWin, pGC->clientClip); - } - pGC->freeCompClip = TRUE; - REGION_TRANSLATE(pScreen, pGC->clientClip, - -(pWin->drawable.x + pGC->clipOrg.x), - -(pWin->drawable.y + pGC->clipOrg.y)); - } -} - -Bool -miOverlayCollectUnderlayRegions( - WindowPtr pWin, - RegionPtr *region -){ - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - - if(pTree) { - *region = &pTree->borderClip; - return FALSE; - } - - *region = REGION_CREATE(pWin->drawable.pScreen, NullBox, 0); - - CollectUnderlayChildrenRegions(pWin, *region); - - return TRUE; -} - - -static miOverlayTreePtr -DoLeaf( - WindowPtr pWin, - miOverlayTreePtr parent, - miOverlayTreePtr prevSib -){ - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - - pTree->parent = parent; - pTree->firstChild = NULL; - pTree->lastChild = NULL; - pTree->prevSib = prevSib; - pTree->nextSib = NULL; - - if(prevSib) - prevSib->nextSib = pTree; - - if(!parent->firstChild) - parent->firstChild = parent->lastChild = pTree; - else if(parent->lastChild == prevSib) - parent->lastChild = pTree; - - return pTree; -} - -static void -RebuildTree(WindowPtr pWin) -{ - miOverlayTreePtr parent, prevSib, tChild; - WindowPtr pChild; - - prevSib = tChild = NULL; - - pWin = pWin->parent; - - while(IN_OVERLAY(pWin)) - pWin = pWin->parent; - - parent = MIOVERLAY_GET_WINDOW_TREE(pWin); - - pChild = pWin->firstChild; - parent->firstChild = parent->lastChild = NULL; - - while(1) { - if(IN_UNDERLAY(pChild)) - prevSib = tChild = DoLeaf(pChild, parent, prevSib); - - if(pChild->firstChild) { - if(IN_UNDERLAY(pChild)) { - parent = tChild; - prevSib = NULL; - } - pChild = pChild->firstChild; - continue; - } - - while(!pChild->nextSib) { - pChild = pChild->parent; - if(pChild == pWin) return; - if(IN_UNDERLAY(pChild)) { - prevSib = tChild = MIOVERLAY_GET_WINDOW_TREE(pChild); - parent = tChild->parent; - } - } - - pChild = pChild->nextSib; - } -} - - -static Bool -HasUnderlayChildren(WindowPtr pWin) -{ - WindowPtr pChild; - - if(!(pChild = pWin->firstChild)) - return FALSE; - - while(1) { - if(IN_UNDERLAY(pChild)) - return TRUE; - - if(pChild->firstChild) { - pChild = pChild->firstChild; - continue; - } - - while(!pChild->nextSib && (pWin != pChild)) - pChild = pChild->parent; - - if(pChild == pWin) break; - - pChild = pChild->nextSib; - } - - return FALSE; -} - - -static Bool -CollectUnderlayChildrenRegions(WindowPtr pWin, RegionPtr pReg) -{ - WindowPtr pChild; - miOverlayTreePtr pTree; - Bool hasUnderlay; - - if(!(pChild = pWin->firstChild)) - return FALSE; - - hasUnderlay = FALSE; - - while(1) { - if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) { - REGION_APPEND(pScreen, pReg, &pTree->borderClip); - hasUnderlay = TRUE; - } else - if(pChild->firstChild) { - pChild = pChild->firstChild; - continue; - } - - while(!pChild->nextSib && (pWin != pChild)) - pChild = pChild->parent; - - if(pChild == pWin) break; - - pChild = pChild->nextSib; - } - - if(hasUnderlay) { - Bool overlap; - REGION_VALIDATE(pScreen, pReg, &overlap); - } - - return hasUnderlay; -} - - -static void -MarkUnderlayWindow(WindowPtr pWin) -{ - miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); - - if(pTree->valdata) return; - pTree->valdata = (miOverlayValDataPtr)xnfalloc(sizeof(miOverlayValDataRec)); - pTree->valdata->oldAbsCorner.x = pWin->drawable.x; - pTree->valdata->oldAbsCorner.y = pWin->drawable.y; - pTree->valdata->borderVisible = NullRegion; -} +
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "gcstruct.h"
+#include "regionstr.h"
+#include "privates.h"
+#include "mivalidate.h"
+#include "mioverlay.h"
+#include "migc.h"
+
+#include "globals.h"
+
+
+typedef struct {
+ RegionRec exposed;
+ RegionRec borderExposed;
+ RegionPtr borderVisible;
+ DDXPointRec oldAbsCorner;
+} miOverlayValDataRec, *miOverlayValDataPtr;
+
+typedef struct _TreeRec {
+ WindowPtr pWin;
+ struct _TreeRec *parent;
+ struct _TreeRec *firstChild;
+ struct _TreeRec *lastChild;
+ struct _TreeRec *prevSib;
+ struct _TreeRec *nextSib;
+ RegionRec borderClip;
+ RegionRec clipList;
+ unsigned visibility;
+ miOverlayValDataPtr valdata;
+} miOverlayTreeRec, *miOverlayTreePtr;
+
+typedef struct {
+ miOverlayTreePtr tree;
+} miOverlayWindowRec, *miOverlayWindowPtr;
+
+typedef struct {
+ CloseScreenProcPtr CloseScreen;
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ miOverlayTransFunc MakeTransparent;
+ miOverlayInOverlayFunc InOverlay;
+ Bool underlayMarked;
+ Bool copyUnderlay;
+} miOverlayScreenRec, *miOverlayScreenPtr;
+
+static int miOverlayWindowKeyKeyIndex;
+static DevPrivateKey miOverlayWindowKey = &miOverlayWindowKeyKeyIndex;
+static int miOverlayScreenKeyIndex;
+static DevPrivateKey miOverlayScreenKey = &miOverlayScreenKeyIndex;
+
+static void RebuildTree(WindowPtr);
+static Bool HasUnderlayChildren(WindowPtr);
+static void MarkUnderlayWindow(WindowPtr);
+static Bool CollectUnderlayChildrenRegions(WindowPtr, RegionPtr);
+
+static Bool miOverlayCloseScreen(int, ScreenPtr);
+static Bool miOverlayCreateWindow(WindowPtr);
+static Bool miOverlayDestroyWindow(WindowPtr);
+static Bool miOverlayUnrealizeWindow(WindowPtr);
+static Bool miOverlayRealizeWindow(WindowPtr);
+static void miOverlayMarkWindow(WindowPtr);
+static void miOverlayReparentWindow(WindowPtr, WindowPtr);
+static void miOverlayRestackWindow(WindowPtr, WindowPtr);
+static Bool miOverlayMarkOverlappedWindows(WindowPtr, WindowPtr, WindowPtr*);
+static void miOverlayMarkUnrealizedWindow(WindowPtr, WindowPtr, Bool);
+static int miOverlayValidateTree(WindowPtr, WindowPtr, VTKind);
+static void miOverlayHandleExposures(WindowPtr);
+static void miOverlayMoveWindow(WindowPtr, int, int, WindowPtr, VTKind);
+static void miOverlayWindowExposures(WindowPtr, RegionPtr, RegionPtr);
+static void miOverlayResizeWindow(WindowPtr, int, int, unsigned int,
+ unsigned int, WindowPtr);
+static void miOverlayClearToBackground(WindowPtr, int, int, int, int, Bool);
+
+static void miOverlaySetShape(WindowPtr);
+static void miOverlayChangeBorderWidth(WindowPtr, unsigned int);
+
+#define MIOVERLAY_GET_SCREEN_PRIVATE(pScreen) ((miOverlayScreenPtr) \
+ dixLookupPrivate(&(pScreen)->devPrivates, miOverlayScreenKey))
+#define MIOVERLAY_GET_WINDOW_PRIVATE(pWin) ((miOverlayWindowPtr) \
+ dixLookupPrivate(&(pWin)->devPrivates, miOverlayWindowKey))
+#define MIOVERLAY_GET_WINDOW_TREE(pWin) \
+ (MIOVERLAY_GET_WINDOW_PRIVATE(pWin)->tree)
+
+#define IN_UNDERLAY(w) MIOVERLAY_GET_WINDOW_TREE(w)
+#define IN_OVERLAY(w) !MIOVERLAY_GET_WINDOW_TREE(w)
+
+#define MARK_OVERLAY(w) miMarkWindow(w)
+#define MARK_UNDERLAY(w) MarkUnderlayWindow(w)
+
+#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
+ HasBorder(w) && \
+ (w)->backgroundState == ParentRelative)
+
+Bool
+miInitOverlay(
+ ScreenPtr pScreen,
+ miOverlayInOverlayFunc inOverlayFunc,
+ miOverlayTransFunc transFunc
+){
+ miOverlayScreenPtr pScreenPriv;
+
+ if(!inOverlayFunc || !transFunc) return FALSE;
+
+ if(!dixRequestPrivate(miOverlayWindowKey, sizeof(miOverlayWindowRec)))
+ return FALSE;
+
+ if(!(pScreenPriv = malloc(sizeof(miOverlayScreenRec))))
+ return FALSE;
+
+ dixSetPrivate(&pScreen->devPrivates, miOverlayScreenKey, pScreenPriv);
+
+ pScreenPriv->InOverlay = inOverlayFunc;
+ pScreenPriv->MakeTransparent = transFunc;
+ pScreenPriv->underlayMarked = FALSE;
+
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreenPriv->CreateWindow = pScreen->CreateWindow;
+ pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
+ pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow;
+ pScreenPriv->RealizeWindow = pScreen->RealizeWindow;
+
+ pScreen->CloseScreen = miOverlayCloseScreen;
+ pScreen->CreateWindow = miOverlayCreateWindow;
+ pScreen->DestroyWindow = miOverlayDestroyWindow;
+ pScreen->UnrealizeWindow = miOverlayUnrealizeWindow;
+ pScreen->RealizeWindow = miOverlayRealizeWindow;
+
+ pScreen->ReparentWindow = miOverlayReparentWindow;
+ pScreen->RestackWindow = miOverlayRestackWindow;
+ pScreen->MarkOverlappedWindows = miOverlayMarkOverlappedWindows;
+ pScreen->MarkUnrealizedWindow = miOverlayMarkUnrealizedWindow;
+ pScreen->ValidateTree = miOverlayValidateTree;
+ pScreen->HandleExposures = miOverlayHandleExposures;
+ pScreen->MoveWindow = miOverlayMoveWindow;
+ pScreen->WindowExposures = miOverlayWindowExposures;
+ pScreen->ResizeWindow = miOverlayResizeWindow;
+ pScreen->MarkWindow = miOverlayMarkWindow;
+ pScreen->ClearToBackground = miOverlayClearToBackground;
+ pScreen->SetShape = miOverlaySetShape;
+ pScreen->ChangeBorderWidth = miOverlayChangeBorderWidth;
+
+ return TRUE;
+}
+
+
+static Bool
+miOverlayCloseScreen(int i, ScreenPtr pScreen)
+{
+ miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->CreateWindow = pScreenPriv->CreateWindow;
+ pScreen->DestroyWindow = pScreenPriv->DestroyWindow;
+ pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow;
+ pScreen->RealizeWindow = pScreenPriv->RealizeWindow;
+
+ free(pScreenPriv);
+
+ return (*pScreen->CloseScreen)(i, pScreen);
+}
+
+
+static Bool
+miOverlayCreateWindow(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ miOverlayWindowPtr pWinPriv = MIOVERLAY_GET_WINDOW_PRIVATE(pWin);
+ miOverlayTreePtr pTree = NULL;
+ Bool result = TRUE;
+
+ pWinPriv->tree = NULL;
+
+ if(!pWin->parent || !((*pScreenPriv->InOverlay)(pWin))) {
+ if(!(pTree = (miOverlayTreePtr)calloc(1, sizeof(miOverlayTreeRec))))
+ return FALSE;
+ }
+
+ if(pScreenPriv->CreateWindow) {
+ pScreen->CreateWindow = pScreenPriv->CreateWindow;
+ result = (*pScreen->CreateWindow)(pWin);
+ pScreen->CreateWindow = miOverlayCreateWindow;
+ }
+
+ if (pTree) {
+ if(result) {
+ pTree->pWin = pWin;
+ pTree->visibility = VisibilityNotViewable;
+ pWinPriv->tree = pTree;
+ if(pWin->parent) {
+ REGION_NULL(pScreen, &(pTree->borderClip));
+ REGION_NULL(pScreen, &(pTree->clipList));
+ RebuildTree(pWin);
+ } else {
+ BoxRec fullBox;
+ fullBox.x1 = 0;
+ fullBox.y1 = 0;
+ fullBox.x2 = pScreen->width;
+ fullBox.y2 = pScreen->height;
+ REGION_INIT(pScreen, &(pTree->borderClip), &fullBox, 1);
+ REGION_INIT(pScreen, &(pTree->clipList), &fullBox, 1);
+ }
+ } else free(pTree);
+ }
+
+ return TRUE;
+}
+
+
+static Bool
+miOverlayDestroyWindow(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ Bool result = TRUE;
+
+ if (pTree) {
+ if(pTree->prevSib)
+ pTree->prevSib->nextSib = pTree->nextSib;
+ else if(pTree->parent)
+ pTree->parent->firstChild = pTree->nextSib;
+
+ if(pTree->nextSib)
+ pTree->nextSib->prevSib = pTree->prevSib;
+ else if(pTree->parent)
+ pTree->parent->lastChild = pTree->prevSib;
+
+ REGION_UNINIT(pScreen, &(pTree->borderClip));
+ REGION_UNINIT(pScreen, &(pTree->clipList));
+ free(pTree);
+ }
+
+ if(pScreenPriv->DestroyWindow) {
+ pScreen->DestroyWindow = pScreenPriv->DestroyWindow;
+ result = (*pScreen->DestroyWindow)(pWin);
+ pScreen->DestroyWindow = miOverlayDestroyWindow;
+ }
+
+ return result;
+}
+
+static Bool
+miOverlayUnrealizeWindow(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ Bool result = TRUE;
+
+ if(pTree) pTree->visibility = VisibilityNotViewable;
+
+ if(pScreenPriv->UnrealizeWindow) {
+ pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow;
+ result = (*pScreen->UnrealizeWindow)(pWin);
+ pScreen->UnrealizeWindow = miOverlayUnrealizeWindow;
+ }
+
+ return result;
+}
+
+
+static Bool
+miOverlayRealizeWindow(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ Bool result = TRUE;
+
+ if(pScreenPriv->RealizeWindow) {
+ pScreen->RealizeWindow = pScreenPriv->RealizeWindow;
+ result = (*pScreen->RealizeWindow)(pWin);
+ pScreen->RealizeWindow = miOverlayRealizeWindow;
+ }
+
+ /* we only need to catch the root window realization */
+
+ if(result && !pWin->parent && !((*pScreenPriv->InOverlay)(pWin)))
+ {
+ BoxRec box;
+ box.x1 = box.y1 = 0;
+ box.x2 = pWin->drawable.width;
+ box.y2 = pWin->drawable.height;
+ (*pScreenPriv->MakeTransparent)(pScreen, 1, &box);
+ }
+
+ return result;
+}
+
+
+static void
+miOverlayReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
+{
+ if(IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) {
+ /* This could probably be more optimal */
+ RebuildTree(WindowTable[pWin->drawable.pScreen->myNum]->firstChild);
+ }
+}
+
+static void
+miOverlayRestackWindow(WindowPtr pWin, WindowPtr oldNextSib)
+{
+ if(IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) {
+ /* This could probably be more optimal */
+ RebuildTree(pWin);
+ }
+}
+
+
+static Bool
+miOverlayMarkOverlappedWindows(
+ WindowPtr pWin,
+ WindowPtr pFirst,
+ WindowPtr *pLayerWin
+){
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ WindowPtr pChild, pLast;
+ Bool overMarked, underMarked, doUnderlay, markAll;
+ miOverlayTreePtr pTree = NULL, tLast, tChild;
+ BoxPtr box;
+
+ overMarked = underMarked = markAll = FALSE;
+
+ if(pLayerWin) *pLayerWin = pWin; /* hah! */
+
+ doUnderlay = (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin));
+
+ box = REGION_EXTENTS(pScreen, &pWin->borderSize);
+
+ if((pChild = pFirst)) {
+ pLast = pChild->parent->lastChild;
+ while (1) {
+ if (pChild == pWin) markAll = TRUE;
+
+ if(doUnderlay && IN_UNDERLAY(pChild))
+ pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
+
+ if(pChild->viewable) {
+ if (REGION_BROKEN (pScreen, &pChild->winSize))
+ SetWinSize (pChild);
+ if (REGION_BROKEN (pScreen, &pChild->borderSize))
+ SetBorderSize (pChild);
+
+ if (markAll ||
+ RECT_IN_REGION(pScreen, &pChild->borderSize, box))
+ {
+ MARK_OVERLAY(pChild);
+ overMarked = TRUE;
+ if(doUnderlay && IN_UNDERLAY(pChild)) {
+ MARK_UNDERLAY(pChild);
+ underMarked = TRUE;
+ }
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ }
+ while (!pChild->nextSib && (pChild != pLast)) {
+ pChild = pChild->parent;
+ if(doUnderlay && IN_UNDERLAY(pChild))
+ pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
+ }
+
+ if(pChild == pWin) markAll = FALSE;
+
+ if (pChild == pLast) break;
+
+ pChild = pChild->nextSib;
+ }
+ if(overMarked)
+ MARK_OVERLAY(pWin->parent);
+ }
+
+ if(doUnderlay && !pTree) {
+ if(!(pTree = MIOVERLAY_GET_WINDOW_TREE(pWin))) {
+ pChild = pWin->lastChild;
+ while(1) {
+ if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild)))
+ break;
+
+ if(pChild->lastChild) {
+ pChild = pChild->lastChild;
+ continue;
+ }
+
+ while(!pChild->prevSib) pChild = pChild->parent;
+
+ pChild = pChild->prevSib;
+ }
+ }
+ }
+
+ if(pTree && pTree->nextSib) {
+ tChild = pTree->parent->lastChild;
+ tLast = pTree->nextSib;
+
+ while(1) {
+ if(tChild->pWin->viewable) {
+ if (REGION_BROKEN (pScreen, &tChild->pWin->winSize))
+ SetWinSize (tChild->pWin);
+ if (REGION_BROKEN (pScreen, &tChild->pWin->borderSize))
+ SetBorderSize (tChild->pWin);
+
+ if(RECT_IN_REGION(pScreen, &(tChild->pWin->borderSize), box))
+ {
+ MARK_UNDERLAY(tChild->pWin);
+ underMarked = TRUE;
+ }
+ }
+
+ if(tChild->lastChild) {
+ tChild = tChild->lastChild;
+ continue;
+ }
+
+ while(!tChild->prevSib && (tChild != tLast))
+ tChild = tChild->parent;
+
+ if(tChild == tLast) break;
+
+ tChild = tChild->prevSib;
+ }
+ }
+
+ if(underMarked) {
+ MARK_UNDERLAY(pTree->parent->pWin);
+ MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->underlayMarked = TRUE;
+ }
+
+ return (underMarked || overMarked);
+}
+
+
+static void
+miOverlayComputeClips(
+ WindowPtr pParent,
+ RegionPtr universe,
+ VTKind kind,
+ RegionPtr exposed
+){
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+ int oldVis, newVis, dx, dy;
+ BoxRec borderSize;
+ RegionPtr borderVisible;
+ RegionRec childUniverse, childUnion;
+ miOverlayTreePtr tParent = MIOVERLAY_GET_WINDOW_TREE(pParent);
+ miOverlayTreePtr tChild;
+ Bool overlap;
+
+ borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
+ borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
+ dx = (int) pParent->drawable.x + (int) pParent->drawable.width +
+ wBorderWidth(pParent);
+ if (dx > 32767) dx = 32767;
+ borderSize.x2 = dx;
+ dy = (int) pParent->drawable.y + (int) pParent->drawable.height +
+ wBorderWidth(pParent);
+ if (dy > 32767) dy = 32767;
+ borderSize.y2 = dy;
+
+ oldVis = tParent->visibility;
+ switch (RECT_IN_REGION( pScreen, universe, &borderSize)) {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnPART:
+ newVis = VisibilityPartiallyObscured;
+ {
+ RegionPtr pBounding;
+
+ if ((pBounding = wBoundingShape (pParent))) {
+ switch (miShapedWindowIn (pScreen, universe, pBounding,
+ &borderSize,
+ pParent->drawable.x,
+ pParent->drawable.y))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnOUT:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+ tParent->visibility = newVis;
+
+ dx = pParent->drawable.x - tParent->valdata->oldAbsCorner.x;
+ dy = pParent->drawable.y - tParent->valdata->oldAbsCorner.y;
+
+ switch (kind) {
+ case VTMap:
+ case VTStack:
+ case VTUnmap:
+ break;
+ case VTMove:
+ if ((oldVis == newVis) &&
+ ((oldVis == VisibilityFullyObscured) ||
+ (oldVis == VisibilityUnobscured)))
+ {
+ tChild = tParent;
+ while (1) {
+ if (tChild->pWin->viewable) {
+ if (tChild->visibility != VisibilityFullyObscured) {
+ REGION_TRANSLATE( pScreen, &tChild->borderClip, dx, dy);
+ REGION_TRANSLATE( pScreen, &tChild->clipList, dx, dy);
+
+ tChild->pWin->drawable.serialNumber =
+ NEXT_SERIAL_NUMBER;
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (tChild->pWin, dx, dy);
+ }
+ if (tChild->valdata) {
+ REGION_NULL(pScreen, &tChild->valdata->borderExposed);
+ if (HasParentRelativeBorder(tChild->pWin)){
+ REGION_SUBTRACT(pScreen,
+ &tChild->valdata->borderExposed,
+ &tChild->borderClip,
+ &tChild->pWin->winSize);
+ }
+ REGION_NULL(pScreen, &tChild->valdata->exposed);
+ }
+ if (tChild->firstChild) {
+ tChild = tChild->firstChild;
+ continue;
+ }
+ }
+ while (!tChild->nextSib && (tChild != tParent))
+ tChild = tChild->parent;
+ if (tChild == tParent)
+ break;
+ tChild = tChild->nextSib;
+ }
+ return;
+ }
+ /* fall through */
+ default:
+ if (dx || dy) {
+ REGION_TRANSLATE( pScreen, &tParent->borderClip, dx, dy);
+ REGION_TRANSLATE( pScreen, &tParent->clipList, dx, dy);
+ }
+ break;
+ case VTBroken:
+ REGION_EMPTY (pScreen, &tParent->borderClip);
+ REGION_EMPTY (pScreen, &tParent->clipList);
+ break;
+ }
+
+ borderVisible = tParent->valdata->borderVisible;
+ REGION_NULL(pScreen, &tParent->valdata->borderExposed);
+ REGION_NULL(pScreen, &tParent->valdata->exposed);
+
+ if (HasBorder (pParent)) {
+ if (borderVisible) {
+ REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
+ REGION_DESTROY( pScreen, borderVisible);
+ } else
+ REGION_SUBTRACT( pScreen, exposed, universe, &tParent->borderClip);
+
+ if (HasParentRelativeBorder(pParent) && (dx || dy))
+ REGION_SUBTRACT( pScreen, &tParent->valdata->borderExposed,
+ universe, &pParent->winSize);
+ else
+ REGION_SUBTRACT( pScreen, &tParent->valdata->borderExposed,
+ exposed, &pParent->winSize);
+
+ REGION_COPY( pScreen, &tParent->borderClip, universe);
+ REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
+ }
+ else
+ REGION_COPY( pScreen, &tParent->borderClip, universe);
+
+ if ((tChild = tParent->firstChild) && pParent->mapped) {
+ REGION_NULL(pScreen, &childUniverse);
+ REGION_NULL(pScreen, &childUnion);
+
+ for (; tChild; tChild = tChild->nextSib) {
+ if (tChild->pWin->viewable)
+ REGION_APPEND( pScreen, &childUnion, &tChild->pWin->borderSize);
+ }
+
+ REGION_VALIDATE( pScreen, &childUnion, &overlap);
+
+ for (tChild = tParent->firstChild;
+ tChild;
+ tChild = tChild->nextSib)
+ {
+ if (tChild->pWin->viewable) {
+ if (tChild->valdata) {
+ REGION_INTERSECT( pScreen, &childUniverse, universe,
+ &tChild->pWin->borderSize);
+ miOverlayComputeClips (tChild->pWin, &childUniverse,
+ kind, exposed);
+ }
+ if (overlap)
+ REGION_SUBTRACT( pScreen, universe, universe,
+ &tChild->pWin->borderSize);
+ }
+ }
+ if (!overlap)
+ REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
+ REGION_UNINIT( pScreen, &childUnion);
+ REGION_UNINIT( pScreen, &childUniverse);
+ }
+
+ if (oldVis == VisibilityFullyObscured ||
+ oldVis == VisibilityNotViewable)
+ {
+ REGION_COPY( pScreen, &tParent->valdata->exposed, universe);
+ }
+ else if (newVis != VisibilityFullyObscured &&
+ newVis != VisibilityNotViewable)
+ {
+ REGION_SUBTRACT( pScreen, &tParent->valdata->exposed,
+ universe, &tParent->clipList);
+ }
+
+ /* HACK ALERT - copying contents of regions, instead of regions */
+ {
+ RegionRec tmp;
+
+ tmp = tParent->clipList;
+ tParent->clipList = *universe;
+ *universe = tmp;
+ }
+
+ pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pParent, dx, dy);
+}
+
+
+static void
+miOverlayMarkWindow(WindowPtr pWin)
+{
+ miOverlayTreePtr pTree = NULL;
+ WindowPtr pChild, pGrandChild;
+
+ miMarkWindow(pWin);
+
+ /* look for UnmapValdata among immediate children */
+
+ if(!(pChild = pWin->firstChild)) return;
+
+ for( ; pChild; pChild = pChild->nextSib) {
+ if(pChild->valdata == UnmapValData) {
+ if(IN_UNDERLAY(pChild)) {
+ pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
+ pTree->valdata = (miOverlayValDataPtr)UnmapValData;
+ continue;
+ } else {
+ if(!(pGrandChild = pChild->firstChild))
+ continue;
+
+ while(1) {
+ if(IN_UNDERLAY(pGrandChild)) {
+ pTree = MIOVERLAY_GET_WINDOW_TREE(pGrandChild);
+ pTree->valdata = (miOverlayValDataPtr)UnmapValData;
+ } else if(pGrandChild->firstChild) {
+ pGrandChild = pGrandChild->firstChild;
+ continue;
+ }
+
+ while(!pGrandChild->nextSib && (pGrandChild != pChild))
+ pGrandChild = pGrandChild->parent;
+
+ if(pChild == pGrandChild) break;
+
+ pGrandChild = pGrandChild->nextSib;
+ }
+ }
+ }
+ }
+
+ if(pTree) {
+ MARK_UNDERLAY(pTree->parent->pWin);
+ MIOVERLAY_GET_SCREEN_PRIVATE(
+ pWin->drawable.pScreen)->underlayMarked = TRUE;
+ }
+}
+
+static void
+miOverlayMarkUnrealizedWindow(
+ WindowPtr pChild,
+ WindowPtr pWin,
+ Bool fromConfigure
+){
+ if ((pChild != pWin) || fromConfigure) {
+ miOverlayTreePtr pTree;
+
+ REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList);
+ if (pChild->drawable.pScreen->ClipNotify)
+ (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
+ REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip);
+ if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
+ if(pTree->valdata != (miOverlayValDataPtr)UnmapValData) {
+ REGION_EMPTY(pChild->drawable.pScreen, &pTree->clipList);
+ REGION_EMPTY(pChild->drawable.pScreen, &pTree->borderClip);
+ }
+ }
+ }
+}
+
+
+static int
+miOverlayValidateTree(
+ WindowPtr pParent,
+ WindowPtr pChild, /* first child effected */
+ VTKind kind
+){
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+ miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ RegionRec totalClip, childClip, exposed;
+ miOverlayTreePtr tParent, tChild, tWin;
+ Bool overlap;
+ WindowPtr newParent;
+
+ if(!pPriv->underlayMarked)
+ goto SKIP_UNDERLAY;
+
+ if (!pChild) pChild = pParent->firstChild;
+
+ REGION_NULL(pScreen, &totalClip);
+ REGION_NULL(pScreen, &childClip);
+ REGION_NULL(pScreen, &exposed);
+
+ newParent = pParent;
+
+ while(IN_OVERLAY(newParent))
+ newParent = newParent->parent;
+
+ tParent = MIOVERLAY_GET_WINDOW_TREE(newParent);
+
+ if(IN_UNDERLAY(pChild))
+ tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
+ else
+ tChild = tParent->firstChild;
+
+ if (REGION_BROKEN (pScreen, &tParent->clipList) &&
+ !REGION_BROKEN (pScreen, &tParent->borderClip))
+ {
+ kind = VTBroken;
+ REGION_COPY (pScreen, &totalClip, &tParent->borderClip);
+ REGION_INTERSECT (pScreen, &totalClip, &totalClip,
+ &tParent->pWin->winSize);
+
+ for (tWin = tParent->firstChild; tWin != tChild; tWin = tWin->nextSib) {
+ if (tWin->pWin->viewable)
+ REGION_SUBTRACT (pScreen, &totalClip, &totalClip,
+ &tWin->pWin->borderSize);
+ }
+ REGION_EMPTY (pScreen, &tParent->clipList);
+ } else {
+ for(tWin = tChild; tWin; tWin = tWin->nextSib) {
+ if(tWin->valdata)
+ REGION_APPEND(pScreen, &totalClip, &tWin->borderClip);
+ }
+ REGION_VALIDATE(pScreen, &totalClip, &overlap);
+ }
+
+ if(kind != VTStack)
+ REGION_UNION(pScreen, &totalClip, &totalClip, &tParent->clipList);
+
+ for(tWin = tChild; tWin; tWin = tWin->nextSib) {
+ if(tWin->valdata) {
+ if(tWin->pWin->viewable) {
+ REGION_INTERSECT(pScreen, &childClip, &totalClip,
+ &tWin->pWin->borderSize);
+ miOverlayComputeClips(tWin->pWin, &childClip, kind, &exposed);
+ REGION_SUBTRACT(pScreen, &totalClip, &totalClip,
+ &tWin->pWin->borderSize);
+ } else { /* Means we are unmapping */
+ REGION_EMPTY(pScreen, &tWin->clipList);
+ REGION_EMPTY( pScreen, &tWin->borderClip);
+ tWin->valdata = NULL;
+ }
+ }
+ }
+
+ REGION_UNINIT(pScreen, &childClip);
+
+ if(!((*pPriv->InOverlay)(newParent))) {
+ REGION_NULL(pScreen, &tParent->valdata->exposed);
+ REGION_NULL(pScreen, &tParent->valdata->borderExposed);
+ }
+
+ switch (kind) {
+ case VTStack:
+ break;
+ default:
+ if(!((*pPriv->InOverlay)(newParent)))
+ REGION_SUBTRACT(pScreen, &tParent->valdata->exposed, &totalClip,
+ &tParent->clipList);
+ /* fall through */
+ case VTMap:
+ REGION_COPY( pScreen, &tParent->clipList, &totalClip);
+ if(!((*pPriv->InOverlay)(newParent)))
+ newParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ break;
+ }
+
+ REGION_UNINIT( pScreen, &totalClip);
+ REGION_UNINIT( pScreen, &exposed);
+
+SKIP_UNDERLAY:
+
+ miValidateTree(pParent, pChild, kind);
+
+ return 1;
+}
+
+
+static void
+miOverlayHandleExposures(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ WindowPtr pChild;
+ ValidatePtr val;
+ void (* WindowExposures)(WindowPtr, RegionPtr, RegionPtr);
+
+ WindowExposures = pWin->drawable.pScreen->WindowExposures;
+ if(pPriv->underlayMarked) {
+ miOverlayTreePtr pTree;
+ miOverlayValDataPtr mival;
+
+ pChild = pWin;
+ while(IN_OVERLAY(pChild))
+ pChild = pChild->parent;
+
+ pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
+
+ while (1) {
+ if((mival = pTree->valdata)) {
+ if(!((*pPriv->InOverlay)(pTree->pWin))) {
+ if (REGION_NOTEMPTY(pScreen, &mival->borderExposed)) {
+ miPaintWindow(pTree->pWin, &mival->borderExposed,
+ PW_BORDER);
+ }
+ REGION_UNINIT(pScreen, &mival->borderExposed);
+
+ (*WindowExposures)(pTree->pWin,&mival->exposed,NullRegion);
+ REGION_UNINIT(pScreen, &mival->exposed);
+ }
+ free(mival);
+ pTree->valdata = NULL;
+ if (pTree->firstChild) {
+ pTree = pTree->firstChild;
+ continue;
+ }
+ }
+ while (!pTree->nextSib && (pTree->pWin != pChild))
+ pTree = pTree->parent;
+ if (pTree->pWin == pChild)
+ break;
+ pTree = pTree->nextSib;
+ }
+ pPriv->underlayMarked = FALSE;
+ }
+
+ pChild = pWin;
+ while (1) {
+ if ( (val = pChild->valdata) ) {
+ if(!((*pPriv->InOverlay)(pChild))) {
+ REGION_UNION(pScreen, &val->after.exposed, &val->after.exposed,
+ &val->after.borderExposed);
+
+ if (REGION_NOTEMPTY(pScreen, &val->after.exposed)) {
+ (*(MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent))(
+ pScreen,
+ REGION_NUM_RECTS(&val->after.exposed),
+ REGION_RECTS(&val->after.exposed));
+ }
+ } else {
+ if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) {
+ miPaintWindow(pChild, &val->after.borderExposed,
+ PW_BORDER);
+ }
+ (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
+ }
+ REGION_UNINIT(pScreen, &val->after.borderExposed);
+ REGION_UNINIT(pScreen, &val->after.exposed);
+ free(val);
+ pChild->valdata = NULL;
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+
+static void
+miOverlayMoveWindow(
+ WindowPtr pWin,
+ int x,
+ int y,
+ WindowPtr pNextSib,
+ VTKind kind
+){
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ WindowPtr pParent, windowToValidate;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ short bw;
+ RegionRec overReg, underReg;
+ DDXPointRec oldpt;
+
+ if (!(pParent = pWin->parent))
+ return ;
+ bw = wBorderWidth (pWin);
+
+ oldpt.x = pWin->drawable.x;
+ oldpt.y = pWin->drawable.y;
+ if (WasViewable) {
+ REGION_NULL(pScreen, &overReg);
+ REGION_NULL(pScreen, &underReg);
+ if(pTree) {
+ REGION_COPY(pScreen, &overReg, &pWin->borderClip);
+ REGION_COPY(pScreen, &underReg, &pTree->borderClip);
+ } else {
+ REGION_COPY(pScreen, &overReg, &pWin->borderClip);
+ CollectUnderlayChildrenRegions(pWin, &underReg);
+ }
+ (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
+ }
+ pWin->origin.x = x + (int)bw;
+ pWin->origin.y = y + (int)bw;
+ x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
+ y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
+
+ SetWinSize (pWin);
+ SetBorderSize (pWin);
+
+ (*pScreen->PositionWindow)(pWin, x, y);
+
+ windowToValidate = MoveWindowInStack(pWin, pNextSib);
+
+ ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
+
+ if (WasViewable) {
+ miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ (*pScreen->MarkOverlappedWindows) (pWin, windowToValidate, NULL);
+
+
+ (*pScreen->ValidateTree)(pWin->parent, NullWindow, kind);
+ if(REGION_NOTEMPTY(pScreen, &underReg)) {
+ pPriv->copyUnderlay = TRUE;
+ (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, &underReg);
+ }
+ REGION_UNINIT(pScreen, &underReg);
+ if(REGION_NOTEMPTY(pScreen, &overReg)) {
+ pPriv->copyUnderlay = FALSE;
+ (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, &overReg);
+ }
+ REGION_UNINIT(pScreen, &overReg);
+ (*pScreen->HandleExposures)(pWin->parent);
+
+ if (pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin->parent, NullWindow, kind);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+}
+
+#ifndef RECTLIMIT
+#define RECTLIMIT 25
+#endif
+
+static void
+miOverlayWindowExposures(
+ WindowPtr pWin,
+ RegionPtr prgn,
+ RegionPtr other_exposed
+){
+ RegionPtr exposures = prgn;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ if ((prgn && !REGION_NIL(prgn)) ||
+ (exposures && !REGION_NIL(exposures)) || other_exposed)
+ {
+ RegionRec expRec;
+ int clientInterested;
+
+ clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) &
+ ExposureMask;
+ if (other_exposed) {
+ if (exposures) {
+ REGION_UNION(pScreen, other_exposed, exposures, other_exposed);
+ if (exposures != prgn)
+ REGION_DESTROY(pScreen, exposures);
+ }
+ exposures = other_exposed;
+ }
+ if (clientInterested && exposures &&
+ (REGION_NUM_RECTS(exposures) > RECTLIMIT))
+ {
+ miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ BoxRec box;
+
+ box = *REGION_EXTENTS(pScreen, exposures);
+ if (exposures == prgn) {
+ exposures = &expRec;
+ REGION_INIT(pScreen, exposures, &box, 1);
+ REGION_RESET(pScreen, prgn, &box);
+ } else {
+ REGION_RESET(pScreen, exposures, &box);
+ REGION_UNION(pScreen, prgn, prgn, exposures);
+ }
+ /* This is the only reason why we are replacing mi's version
+ of this file */
+
+ if(!((*pPriv->InOverlay)(pWin))) {
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ REGION_INTERSECT(pScreen, prgn, prgn, &pTree->clipList);
+ } else
+ REGION_INTERSECT(pScreen, prgn, prgn, &pWin->clipList);
+ }
+ if (prgn && !REGION_NIL(prgn))
+ miPaintWindow(pWin, prgn, PW_BACKGROUND);
+ if (clientInterested && exposures && !REGION_NIL(exposures))
+ miSendExposures(pWin, exposures,
+ pWin->drawable.x, pWin->drawable.y);
+ if (exposures == &expRec) {
+ REGION_UNINIT(pScreen, exposures);
+ }
+ else if (exposures && exposures != prgn && exposures != other_exposed)
+ REGION_DESTROY(pScreen, exposures);
+ if (prgn)
+ REGION_EMPTY(pScreen, prgn);
+ }
+ else if (exposures && exposures != prgn)
+ REGION_DESTROY(pScreen, exposures);
+}
+
+
+typedef struct {
+ RegionPtr over;
+ RegionPtr under;
+} miOverlayTwoRegions;
+
+static int
+miOverlayRecomputeExposures (
+ WindowPtr pWin,
+ pointer value
+){
+ ScreenPtr pScreen;
+ miOverlayTwoRegions *pValid = (miOverlayTwoRegions*)value;
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+
+ /* This prevents warning about pScreen not being used. */
+ pWin->drawable.pScreen = pScreen = pWin->drawable.pScreen;
+
+ if (pWin->valdata) {
+ /*
+ * compute exposed regions of this window
+ */
+ REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
+ &pWin->clipList, pValid->over);
+ /*
+ * compute exposed regions of the border
+ */
+ REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
+ &pWin->borderClip, &pWin->winSize);
+ REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
+ &pWin->valdata->after.borderExposed, pValid->over);
+ }
+
+ if(pTree && pTree->valdata) {
+ REGION_SUBTRACT(pScreen, &pTree->valdata->exposed,
+ &pTree->clipList, pValid->under);
+ REGION_SUBTRACT(pScreen, &pTree->valdata->borderExposed,
+ &pTree->borderClip, &pWin->winSize);
+ REGION_SUBTRACT(pScreen, &pTree->valdata->borderExposed,
+ &pTree->valdata->borderExposed, pValid->under);
+ } else if (!pWin->valdata)
+ return WT_NOMATCH;
+
+ return WT_WALKCHILDREN;
+}
+
+static void
+miOverlayResizeWindow(
+ WindowPtr pWin,
+ int x, int y,
+ unsigned int w, unsigned int h,
+ WindowPtr pSib
+){
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ WindowPtr pParent;
+ miOverlayTreePtr tChild, pTree;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ unsigned short width = pWin->drawable.width;
+ unsigned short height = pWin->drawable.height;
+ short oldx = pWin->drawable.x;
+ short oldy = pWin->drawable.y;
+ int bw = wBorderWidth (pWin);
+ short dw, dh;
+ DDXPointRec oldpt;
+ RegionPtr oldRegion = NULL, oldRegion2 = NULL;
+ WindowPtr pFirstChange;
+ WindowPtr pChild;
+ RegionPtr gravitate[StaticGravity + 1];
+ RegionPtr gravitate2[StaticGravity + 1];
+ unsigned g;
+ int nx, ny; /* destination x,y */
+ int newx, newy; /* new inner window position */
+ RegionPtr pRegion = NULL;
+ RegionPtr destClip, destClip2;
+ RegionPtr oldWinClip = NULL, oldWinClip2 = NULL;
+ RegionPtr borderVisible = NullRegion;
+ RegionPtr borderVisible2 = NullRegion;
+ Bool shrunk = FALSE; /* shrunk in an inner dimension */
+ Bool moved = FALSE; /* window position changed */
+ Bool doUnderlay;
+
+ /* if this is a root window, can't be resized */
+ if (!(pParent = pWin->parent))
+ return ;
+
+ pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ doUnderlay = ((pTree) || HasUnderlayChildren(pWin));
+ newx = pParent->drawable.x + x + bw;
+ newy = pParent->drawable.y + y + bw;
+ if (WasViewable)
+ {
+ /*
+ * save the visible region of the window
+ */
+ oldRegion = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, oldRegion, &pWin->winSize);
+ if(doUnderlay) {
+ oldRegion2 = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, oldRegion2, &pWin->winSize);
+ }
+
+ /*
+ * categorize child windows into regions to be moved
+ */
+ for (g = 0; g <= StaticGravity; g++)
+ gravitate[g] = gravitate2[g] = NULL;
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
+ g = pChild->winGravity;
+ if (g != UnmapGravity) {
+ if (!gravitate[g])
+ gravitate[g] = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_UNION(pScreen, gravitate[g],
+ gravitate[g], &pChild->borderClip);
+
+ if(doUnderlay) {
+ if (!gravitate2[g])
+ gravitate2[g] = REGION_CREATE(pScreen, NullBox, 0);
+
+ if((tChild = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
+ REGION_UNION(pScreen, gravitate2[g],
+ gravitate2[g], &tChild->borderClip);
+ } else
+ CollectUnderlayChildrenRegions(pChild, gravitate2[g]);
+ }
+ } else {
+ UnmapWindow(pChild, TRUE);
+ }
+ }
+ (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
+
+
+ oldWinClip = oldWinClip2 = NULL;
+ if (pWin->bitGravity != ForgetGravity) {
+ oldWinClip = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, oldWinClip, &pWin->clipList);
+ if(pTree) {
+ oldWinClip2 = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, oldWinClip2, &pTree->clipList);
+ }
+ }
+ /*
+ * if the window is changing size, borderExposed
+ * can't be computed correctly without some help.
+ */
+ if (pWin->drawable.height > h || pWin->drawable.width > w)
+ shrunk = TRUE;
+
+ if (newx != oldx || newy != oldy)
+ moved = TRUE;
+
+ if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
+ HasBorder (pWin))
+ {
+ borderVisible = REGION_CREATE(pScreen, NullBox, 1);
+ if(pTree)
+ borderVisible2 = REGION_CREATE(pScreen, NullBox, 1);
+ /* for tiled borders, we punt and draw the whole thing */
+ if (pWin->borderIsPixel || !moved)
+ {
+ if (shrunk || moved)
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip,
+ &pWin->winSize);
+ else
+ REGION_COPY(pScreen, borderVisible,
+ &pWin->borderClip);
+ if(pTree) {
+ if (shrunk || moved)
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pTree->borderClip,
+ &pWin->winSize);
+ else
+ REGION_COPY(pScreen, borderVisible,
+ &pTree->borderClip);
+ }
+ }
+ }
+ }
+ pWin->origin.x = x + bw;
+ pWin->origin.y = y + bw;
+ pWin->drawable.height = h;
+ pWin->drawable.width = w;
+
+ x = pWin->drawable.x = newx;
+ y = pWin->drawable.y = newy;
+
+ SetWinSize (pWin);
+ SetBorderSize (pWin);
+
+ dw = (int)w - (int)width;
+ dh = (int)h - (int)height;
+ ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
+
+ /* let the hardware adjust background and border pixmaps, if any */
+ (*pScreen->PositionWindow)(pWin, x, y);
+
+ pFirstChange = MoveWindowInStack(pWin, pSib);
+
+ if (WasViewable) {
+ pRegion = REGION_CREATE(pScreen, NullBox, 1);
+
+ (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, NULL);
+
+ pWin->valdata->before.resized = TRUE;
+ pWin->valdata->before.borderVisible = borderVisible;
+ if(pTree)
+ pTree->valdata->borderVisible = borderVisible2;
+
+
+ (*pScreen->ValidateTree)(pWin->parent, pFirstChange, VTOther);
+ /*
+ * the entire window is trashed unless bitGravity
+ * recovers portions of it
+ */
+ REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList);
+ if(pTree)
+ REGION_COPY(pScreen, &pTree->valdata->exposed, &pTree->clipList);
+ }
+
+ GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
+
+ if (WasViewable) {
+ miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ miOverlayTwoRegions TwoRegions;
+
+ /* avoid the border */
+ if (HasBorder (pWin)) {
+ int offx, offy, dx, dy;
+
+ /* kruft to avoid double translates for each gravity */
+ offx = 0;
+ offy = 0;
+ for (g = 0; g <= StaticGravity; g++) {
+ if (!gravitate[g] && !gravitate2[g])
+ continue;
+
+ /* align winSize to gravitate[g].
+ * winSize is in new coordinates,
+ * gravitate[g] is still in old coordinates */
+ GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
+
+ dx = (oldx - nx) - offx;
+ dy = (oldy - ny) - offy;
+ if (dx || dy) {
+ REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy);
+ offx += dx;
+ offy += dy;
+ }
+ if(gravitate[g])
+ REGION_INTERSECT(pScreen, gravitate[g], gravitate[g],
+ &pWin->winSize);
+ if(gravitate2[g])
+ REGION_INTERSECT(pScreen, gravitate2[g], gravitate2[g],
+ &pWin->winSize);
+ }
+ /* get winSize back where it belongs */
+ if (offx || offy)
+ REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy);
+ }
+ /*
+ * add screen bits to the appropriate bucket
+ */
+
+ if (oldWinClip2)
+ {
+ REGION_COPY(pScreen, pRegion, oldWinClip2);
+ REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy);
+ REGION_INTERSECT(pScreen, oldWinClip2, pRegion, &pTree->clipList);
+
+ for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
+ if (gravitate2[g])
+ REGION_SUBTRACT(pScreen, oldWinClip2, oldWinClip2,
+ gravitate2[g]);
+ }
+ REGION_TRANSLATE(pScreen, oldWinClip2, oldx - nx, oldy - ny);
+ g = pWin->bitGravity;
+ if (!gravitate2[g])
+ gravitate2[g] = oldWinClip2;
+ else {
+ REGION_UNION(pScreen,gravitate2[g],gravitate2[g],oldWinClip2);
+ REGION_DESTROY(pScreen, oldWinClip2);
+ }
+ }
+
+ if (oldWinClip)
+ {
+ /*
+ * clip to new clipList
+ */
+ REGION_COPY(pScreen, pRegion, oldWinClip);
+ REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy);
+ REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList);
+ /*
+ * don't step on any gravity bits which will be copied after this
+ * region. Note -- this assumes that the regions will be copied
+ * in gravity order.
+ */
+ for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
+ if (gravitate[g])
+ REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip,
+ gravitate[g]);
+ }
+ REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny);
+ g = pWin->bitGravity;
+ if (!gravitate[g])
+ gravitate[g] = oldWinClip;
+ else {
+ REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip);
+ REGION_DESTROY(pScreen, oldWinClip);
+ }
+ }
+
+ /*
+ * move the bits on the screen
+ */
+
+ destClip = destClip2 = NULL;
+
+ for (g = 0; g <= StaticGravity; g++) {
+ if (!gravitate[g] && !gravitate2[g])
+ continue;
+
+ GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
+
+ oldpt.x = oldx + (x - nx);
+ oldpt.y = oldy + (y - ny);
+
+ /* Note that gravitate[g] is *translated* by CopyWindow */
+
+ /* only copy the remaining useful bits */
+
+ if(gravitate[g])
+ REGION_INTERSECT(pScreen, gravitate[g],
+ gravitate[g], oldRegion);
+ if(gravitate2[g])
+ REGION_INTERSECT(pScreen, gravitate2[g],
+ gravitate2[g], oldRegion2);
+
+ /* clip to not overwrite already copied areas */
+
+ if (destClip && gravitate[g]) {
+ REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y);
+ REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip);
+ REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y);
+ }
+ if (destClip2 && gravitate2[g]) {
+ REGION_TRANSLATE(pScreen, destClip2, oldpt.x - x, oldpt.y - y);
+ REGION_SUBTRACT(pScreen,gravitate2[g],gravitate2[g],destClip2);
+ REGION_TRANSLATE(pScreen, destClip2, x - oldpt.x, y - oldpt.y);
+ }
+
+ /* and move those bits */
+
+ if (oldpt.x != x || oldpt.y != y) {
+ if(gravitate2[g]) {
+ pPriv->copyUnderlay = TRUE;
+ (*pWin->drawable.pScreen->CopyWindow)(
+ pWin, oldpt, gravitate2[g]);
+ }
+ if(gravitate[g]) {
+ pPriv->copyUnderlay = FALSE;
+ (*pWin->drawable.pScreen->CopyWindow)(
+ pWin, oldpt, gravitate[g]);
+ }
+ }
+
+ /* remove any overwritten bits from the remaining useful bits */
+
+ if(gravitate[g])
+ REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]);
+ if(gravitate2[g])
+ REGION_SUBTRACT(pScreen, oldRegion2, oldRegion2, gravitate2[g]);
+
+ /*
+ * recompute exposed regions of child windows
+ */
+
+
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
+ if (pChild->winGravity != g)
+ continue;
+
+ TwoRegions.over = gravitate[g];
+ TwoRegions.under = gravitate2[g];
+
+ TraverseTree (pChild, miOverlayRecomputeExposures,
+ (pointer)(&TwoRegions));
+ }
+
+ /*
+ * remove the successfully copied regions of the
+ * window from its exposed region
+ */
+
+ if (g == pWin->bitGravity) {
+ if(gravitate[g])
+ REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
+ &pWin->valdata->after.exposed, gravitate[g]);
+ if(gravitate2[g] && pTree)
+ REGION_SUBTRACT(pScreen, &pTree->valdata->exposed,
+ &pTree->valdata->exposed, gravitate2[g]);
+ }
+ if(gravitate[g]) {
+ if (!destClip)
+ destClip = gravitate[g];
+ else {
+ REGION_UNION(pScreen, destClip, destClip, gravitate[g]);
+ REGION_DESTROY(pScreen, gravitate[g]);
+ }
+ }
+ if(gravitate2[g]) {
+ if (!destClip2)
+ destClip2 = gravitate2[g];
+ else {
+ REGION_UNION(pScreen, destClip2, destClip2, gravitate2[g]);
+ REGION_DESTROY(pScreen, gravitate2[g]);
+ }
+ }
+ }
+
+ REGION_DESTROY(pScreen, pRegion);
+ REGION_DESTROY(pScreen, oldRegion);
+ if(doUnderlay)
+ REGION_DESTROY(pScreen, oldRegion2);
+ if (destClip)
+ REGION_DESTROY(pScreen, destClip);
+ if (destClip2)
+ REGION_DESTROY(pScreen, destClip2);
+ (*pScreen->HandleExposures)(pWin->parent);
+ if (pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin->parent, pFirstChange, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+}
+
+
+static void
+miOverlaySetShape(WindowPtr pWin)
+{
+ Bool WasViewable = (Bool)(pWin->viewable);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ if (WasViewable) {
+ (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
+
+ if (HasBorder (pWin)) {
+ RegionPtr borderVisible;
+
+ borderVisible = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ pWin->valdata->before.resized = TRUE;
+ if(IN_UNDERLAY(pWin)) {
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ RegionPtr borderVisible2;
+
+ borderVisible2 = REGION_CREATE(pScreen, NULL, 1);
+ REGION_SUBTRACT(pScreen, borderVisible2,
+ &pTree->borderClip, &pWin->winSize);
+ pTree->valdata->borderVisible = borderVisible2;
+ }
+ }
+ }
+
+ SetWinSize (pWin);
+ SetBorderSize (pWin);
+
+ ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
+
+ if (WasViewable) {
+ (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
+
+
+ (*pScreen->ValidateTree)(pWin->parent, NullWindow, VTOther);
+ }
+
+ if (WasViewable) {
+ (*pScreen->HandleExposures)(pWin->parent);
+ if (pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin->parent, NullWindow, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+ CheckCursorConfinement(pWin);
+}
+
+
+
+static void
+miOverlayChangeBorderWidth(
+ WindowPtr pWin,
+ unsigned int width
+){
+ int oldwidth;
+ ScreenPtr pScreen;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ Bool HadBorder;
+
+ oldwidth = wBorderWidth (pWin);
+ if (oldwidth == width)
+ return;
+ HadBorder = HasBorder(pWin);
+ pScreen = pWin->drawable.pScreen;
+ if (WasViewable && (width < oldwidth))
+ (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
+
+ pWin->borderWidth = width;
+ SetBorderSize (pWin);
+
+ if (WasViewable) {
+ if (width > oldwidth) {
+ (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
+
+ if (HadBorder) {
+ RegionPtr borderVisible;
+ borderVisible = REGION_CREATE(pScreen, NULL, 1);
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ if(IN_UNDERLAY(pWin)) {
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ RegionPtr borderVisible2;
+
+ borderVisible2 = REGION_CREATE(pScreen, NULL, 1);
+ REGION_SUBTRACT(pScreen, borderVisible2,
+ &pTree->borderClip, &pWin->winSize);
+ pTree->valdata->borderVisible = borderVisible2;
+ }
+ }
+ }
+ (*pScreen->ValidateTree)(pWin->parent, pWin, VTOther);
+ (*pScreen->HandleExposures)(pWin->parent);
+
+ if (pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin->parent, pWin, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+}
+
+/* We need this as an addition since the xf86 common code doesn't
+ know about the second tree which is static to this file. */
+
+void
+miOverlaySetRootClip(ScreenPtr pScreen, Bool enable)
+{
+ WindowPtr pRoot = WindowTable[pScreen->myNum];
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pRoot);
+
+ MARK_UNDERLAY(pRoot);
+
+ if(enable) {
+ BoxRec box;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+
+ REGION_RESET(pScreen, &pTree->borderClip, &box);
+ } else
+ REGION_EMPTY(pScreen, &pTree->borderClip);
+
+ REGION_BREAK(pScreen, &pTree->clipList);
+}
+
+static void
+miOverlayClearToBackground(
+ WindowPtr pWin,
+ int x, int y,
+ int w, int h,
+ Bool generateExposures
+)
+{
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ BoxRec box;
+ RegionRec reg;
+ RegionPtr pBSReg = NullRegion;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
+ RegionPtr clipList;
+ BoxPtr extents;
+ int x1, y1, x2, y2;
+
+ x1 = pWin->drawable.x + x;
+ y1 = pWin->drawable.y + y;
+ if (w)
+ x2 = x1 + (int) w;
+ else
+ x2 = x1 + (int) pWin->drawable.width - (int) x;
+ if (h)
+ y2 = y1 + h;
+ else
+ y2 = y1 + (int) pWin->drawable.height - (int) y;
+
+ clipList = ((*pScreenPriv->InOverlay)(pWin)) ? &pWin->clipList :
+ &pTree->clipList;
+
+ extents = REGION_EXTENTS(pScreen, clipList);
+
+ if (x1 < extents->x1) x1 = extents->x1;
+ if (x2 > extents->x2) x2 = extents->x2;
+ if (y1 < extents->y1) y1 = extents->y1;
+ if (y2 > extents->y2) y2 = extents->y2;
+
+ if (x2 <= x1 || y2 <= y1)
+ x2 = x1 = y2 = y1 = 0;
+
+ box.x1 = x1; box.x2 = x2;
+ box.y1 = y1; box.y2 = y2;
+
+ REGION_INIT(pScreen, ®, &box, 1);
+
+ REGION_INTERSECT(pScreen, ®, ®, clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, ®, pBSReg);
+ else if (pWin->backgroundState != None)
+ miPaintWindow(pWin, ®, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, ®);
+ if (pBSReg)
+ REGION_DESTROY(pScreen, pBSReg);
+}
+
+
+/****************************************************************/
+
+/* not used */
+Bool
+miOverlayGetPrivateClips(
+ WindowPtr pWin,
+ RegionPtr *borderClip,
+ RegionPtr *clipList
+){
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+
+ if(pTree) {
+ *borderClip = &(pTree->borderClip);
+ *clipList = &(pTree->clipList);
+ return TRUE;
+ }
+
+ *borderClip = *clipList = NULL;
+
+ return FALSE;
+}
+
+void
+miOverlaySetTransFunction (
+ ScreenPtr pScreen,
+ miOverlayTransFunc transFunc
+){
+ MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc;
+}
+
+Bool
+miOverlayCopyUnderlay(ScreenPtr pScreen)
+{
+ return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay;
+}
+
+void
+miOverlayComputeCompositeClip(GCPtr pGC, WindowPtr pWin)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+ RegionPtr pregWin;
+ Bool freeTmpClip, freeCompClip;
+
+ if(!pTree) {
+ miComputeCompositeClip(pGC, &pWin->drawable);
+ return;
+ }
+
+ if (pGC->subWindowMode == IncludeInferiors) {
+ pregWin = REGION_CREATE(pScreen, NullBox, 1);
+ freeTmpClip = TRUE;
+ if (pWin->parent || (screenIsSaved != SCREEN_SAVER_ON) ||
+ !HasSaverWindow (pScreen->myNum))
+ {
+ REGION_INTERSECT(pScreen,pregWin,&pTree->borderClip,&pWin->winSize);
+ }
+ } else {
+ pregWin = &pTree->clipList;
+ freeTmpClip = FALSE;
+ }
+ freeCompClip = pGC->freeCompClip;
+ if (pGC->clientClipType == CT_NONE) {
+ if (freeCompClip)
+ REGION_DESTROY(pScreen, pGC->pCompositeClip);
+ pGC->pCompositeClip = pregWin;
+ pGC->freeCompClip = freeTmpClip;
+ } else {
+ REGION_TRANSLATE(pScreen, pGC->clientClip,
+ pWin->drawable.x + pGC->clipOrg.x,
+ pWin->drawable.y + pGC->clipOrg.y);
+
+ if (freeCompClip) {
+ REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
+ pregWin, pGC->clientClip);
+ if (freeTmpClip)
+ REGION_DESTROY(pScreen, pregWin);
+ } else if (freeTmpClip) {
+ REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip);
+ pGC->pCompositeClip = pregWin;
+ } else {
+ pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
+ REGION_INTERSECT(pScreen, pGC->pCompositeClip,
+ pregWin, pGC->clientClip);
+ }
+ pGC->freeCompClip = TRUE;
+ REGION_TRANSLATE(pScreen, pGC->clientClip,
+ -(pWin->drawable.x + pGC->clipOrg.x),
+ -(pWin->drawable.y + pGC->clipOrg.y));
+ }
+}
+
+Bool
+miOverlayCollectUnderlayRegions(
+ WindowPtr pWin,
+ RegionPtr *region
+){
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+
+ if(pTree) {
+ *region = &pTree->borderClip;
+ return FALSE;
+ }
+
+ *region = REGION_CREATE(pWin->drawable.pScreen, NullBox, 0);
+
+ CollectUnderlayChildrenRegions(pWin, *region);
+
+ return TRUE;
+}
+
+
+static miOverlayTreePtr
+DoLeaf(
+ WindowPtr pWin,
+ miOverlayTreePtr parent,
+ miOverlayTreePtr prevSib
+){
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+
+ pTree->parent = parent;
+ pTree->firstChild = NULL;
+ pTree->lastChild = NULL;
+ pTree->prevSib = prevSib;
+ pTree->nextSib = NULL;
+
+ if(prevSib)
+ prevSib->nextSib = pTree;
+
+ if(!parent->firstChild)
+ parent->firstChild = parent->lastChild = pTree;
+ else if(parent->lastChild == prevSib)
+ parent->lastChild = pTree;
+
+ return pTree;
+}
+
+static void
+RebuildTree(WindowPtr pWin)
+{
+ miOverlayTreePtr parent, prevSib, tChild;
+ WindowPtr pChild;
+
+ prevSib = tChild = NULL;
+
+ pWin = pWin->parent;
+
+ while(IN_OVERLAY(pWin))
+ pWin = pWin->parent;
+
+ parent = MIOVERLAY_GET_WINDOW_TREE(pWin);
+
+ pChild = pWin->firstChild;
+ parent->firstChild = parent->lastChild = NULL;
+
+ while(1) {
+ if(IN_UNDERLAY(pChild))
+ prevSib = tChild = DoLeaf(pChild, parent, prevSib);
+
+ if(pChild->firstChild) {
+ if(IN_UNDERLAY(pChild)) {
+ parent = tChild;
+ prevSib = NULL;
+ }
+ pChild = pChild->firstChild;
+ continue;
+ }
+
+ while(!pChild->nextSib) {
+ pChild = pChild->parent;
+ if(pChild == pWin) return;
+ if(IN_UNDERLAY(pChild)) {
+ prevSib = tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
+ parent = tChild->parent;
+ }
+ }
+
+ pChild = pChild->nextSib;
+ }
+}
+
+
+static Bool
+HasUnderlayChildren(WindowPtr pWin)
+{
+ WindowPtr pChild;
+
+ if(!(pChild = pWin->firstChild))
+ return FALSE;
+
+ while(1) {
+ if(IN_UNDERLAY(pChild))
+ return TRUE;
+
+ if(pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+
+ while(!pChild->nextSib && (pWin != pChild))
+ pChild = pChild->parent;
+
+ if(pChild == pWin) break;
+
+ pChild = pChild->nextSib;
+ }
+
+ return FALSE;
+}
+
+
+static Bool
+CollectUnderlayChildrenRegions(WindowPtr pWin, RegionPtr pReg)
+{
+ WindowPtr pChild;
+ miOverlayTreePtr pTree;
+ Bool hasUnderlay;
+
+ if(!(pChild = pWin->firstChild))
+ return FALSE;
+
+ hasUnderlay = FALSE;
+
+ while(1) {
+ if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
+ REGION_APPEND(pScreen, pReg, &pTree->borderClip);
+ hasUnderlay = TRUE;
+ } else
+ if(pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+
+ while(!pChild->nextSib && (pWin != pChild))
+ pChild = pChild->parent;
+
+ if(pChild == pWin) break;
+
+ pChild = pChild->nextSib;
+ }
+
+ if(hasUnderlay) {
+ Bool overlap;
+ REGION_VALIDATE(pScreen, pReg, &overlap);
+ }
+
+ return hasUnderlay;
+}
+
+
+static void
+MarkUnderlayWindow(WindowPtr pWin)
+{
+ miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
+
+ if(pTree->valdata) return;
+ pTree->valdata = (miOverlayValDataPtr)xnfalloc(sizeof(miOverlayValDataRec));
+ pTree->valdata->oldAbsCorner.x = pWin->drawable.x;
+ pTree->valdata->oldAbsCorner.y = pWin->drawable.y;
+ pTree->valdata->borderVisible = NullRegion;
+}
diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c index 1b33f82d5..069a38bd8 100644 --- a/xorg-server/mi/mipointer.c +++ b/xorg-server/mi/mipointer.c @@ -1,592 +1,580 @@ -/* - -Copyright 1989, 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 <X11/X.h> -# include <X11/Xmd.h> -# include <X11/Xproto.h> -# include "misc.h" -# include "windowstr.h" -# include "pixmapstr.h" -# include "mi.h" -# include "scrnintstr.h" -# include "mipointrst.h" -# include "cursorstr.h" -# include "dixstruct.h" -# include "inputstr.h" - -static int miPointerScreenKeyIndex; -DevPrivateKey miPointerScreenKey = &miPointerScreenKeyIndex; - -#define GetScreenPrivate(s) ((miPointerScreenPtr) \ - dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) -#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) - -static int miPointerPrivKeyIndex; -static DevPrivateKey miPointerPrivKey = &miPointerPrivKeyIndex; - -#define MIPOINTER(dev) \ - ((!IsMaster(dev) && !dev->u.master) ? \ - (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ - (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) - -static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - BoxPtr pBox); -static void miPointerPointerNonInterestBox(DeviceIntPtr pDev, - ScreenPtr pScreen, BoxPtr pBox); -static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, BoxPtr pHotBox, - BoxPtr pTopLeftBox); -static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, - Bool generateEvent); -static Bool miPointerCloseScreen(int index, ScreenPtr pScreen); -static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y); -static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); -static void miPointerDeviceCleanup(DeviceIntPtr pDev, - ScreenPtr pScreen); - -static EventList* events; /* for WarpPointer MotionNotifies */ - -Bool -miPointerInitialize (ScreenPtr pScreen, - miPointerSpriteFuncPtr spriteFuncs, - miPointerScreenFuncPtr screenFuncs, - Bool waitForUpdate) -{ - miPointerScreenPtr pScreenPriv; - - pScreenPriv = xalloc (sizeof (miPointerScreenRec)); - if (!pScreenPriv) - return FALSE; - pScreenPriv->spriteFuncs = spriteFuncs; - pScreenPriv->screenFuncs = screenFuncs; - /* - * check for uninitialized methods - */ - if (!screenFuncs->EnqueueEvent) - screenFuncs->EnqueueEvent = mieqEnqueue; - if (!screenFuncs->NewEventScreen) - screenFuncs->NewEventScreen = mieqSwitchScreen; - pScreenPriv->waitForUpdate = waitForUpdate; - pScreenPriv->showTransparent = FALSE; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = miPointerCloseScreen; - dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); - /* - * set up screen cursor method table - */ - pScreen->ConstrainCursor = miPointerConstrainCursor; - pScreen->CursorLimits = miPointerCursorLimits; - pScreen->DisplayCursor = miPointerDisplayCursor; - pScreen->RealizeCursor = miPointerRealizeCursor; - pScreen->UnrealizeCursor = miPointerUnrealizeCursor; - pScreen->SetCursorPosition = miPointerSetCursorPosition; - pScreen->RecolorCursor = miRecolorCursor; - pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox; - pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; - pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; - - events = NULL; - return TRUE; -} - -static Bool -miPointerCloseScreen (int index, ScreenPtr pScreen) -{ -#if 0 - miPointerPtr pPointer; - DeviceIntPtr pDev; -#endif - - SetupScreen(pScreen); - -#if 0 - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pPointer = MIPOINTER(pDev); - - if (pScreen == pPointer->pScreen) - pPointer->pScreen = 0; - if (pScreen == pPointer->pSpriteScreen) - pPointer->pSpriteScreen = 0; - } - } - - if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen) - MIPOINTER(inputInfo.pointer)->pScreen = 0; - if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen) - MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0; -#endif - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - xfree ((pointer) pScreenPriv); - FreeEventList(events, GetMaximumEventsNum()); - events = NULL; - return (*pScreen->CloseScreen) (index, pScreen); -} - -/* - * DIX/DDX interface routines - */ - -static Bool -miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - SetupScreen(pScreen); - return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); -} - -static Bool -miPointerUnrealizeCursor (DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor) -{ - SetupScreen(pScreen); - return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); -} - -static Bool -miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - miPointerPtr pPointer; - - /* return for keyboards */ - if ((IsMaster(pDev) && !DevHasCursor(pDev)) || - (!IsMaster(pDev) && pDev->u.master && !DevHasCursor(pDev->u.master))) - return FALSE; - - pPointer = MIPOINTER(pDev); - - pPointer->pCursor = pCursor; - pPointer->pScreen = pScreen; - miPointerUpdateSprite(pDev); - return TRUE; -} - -static void -miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) -{ - miPointerPtr pPointer; - - pPointer = MIPOINTER(pDev); - - pPointer->limits = *pBox; - pPointer->confined = PointerConfinedToScreen(pDev); -} - -/*ARGSUSED*/ -static void -miPointerPointerNonInterestBox (DeviceIntPtr pDev, - ScreenPtr pScreen, - BoxPtr pBox) -{ - /* until DIX uses this, this will remain a stub */ -} - -/*ARGSUSED*/ -static void -miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, - BoxPtr pHotBox, BoxPtr pTopLeftBox) -{ - *pTopLeftBox = *pHotBox; -} - -static Bool GenerateEvent; - -static Bool -miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, Bool generateEvent) -{ - SetupScreen (pScreen); - - GenerateEvent = generateEvent; - /* device dependent - must pend signal and call miPointerWarpCursor */ - (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); - if (!generateEvent) - miPointerUpdateSprite(pDev); - return TRUE; -} - -/* Set up sprite information for the device. - This function will be called once for each device after it is initialized - in the DIX. - */ -static Bool -miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miPointerPtr pPointer; - SetupScreen (pScreen); - - pPointer = xalloc(sizeof(miPointerRec)); - if (!pPointer) - return FALSE; - - pPointer->pScreen = NULL; - pPointer->pSpriteScreen = NULL; - pPointer->pCursor = NULL; - pPointer->pSpriteCursor = NULL; - pPointer->limits.x1 = 0; - pPointer->limits.x2 = 32767; - pPointer->limits.y1 = 0; - pPointer->limits.y2 = 32767; - pPointer->confined = FALSE; - pPointer->x = 0; - pPointer->y = 0; - - if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) - { - xfree(pPointer); - return FALSE; - } - - dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); - return TRUE; -} - -/* Clean up after device. - This function will be called once before the device is freed in the DIX - */ -static void -miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - SetupScreen(pScreen); - - if (!IsMaster(pDev) && pDev->u.master) - return; - - (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); - xfree(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); - dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); -} - - -/* Once signals are ignored, the WarpCursor function can call this */ - -void -miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - miPointerPtr pPointer; - BOOL changedScreen = FALSE; - - SetupScreen (pScreen); - pPointer = MIPOINTER(pDev); - - if (pPointer->pScreen != pScreen) - { - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); - changedScreen = TRUE; - } - - if (GenerateEvent) - { - miPointerMove (pDev, pScreen, x, y); - } - else - { - /* everything from miPointerMove except the event and history */ - - if (!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) - { - pPointer->devx = x; - pPointer->devy = y; - if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); - } - pPointer->x = x; - pPointer->y = y; - pPointer->pScreen = pScreen; - } - - /* Don't call USFS if we use Xinerama, otherwise the root window is - * updated to the second screen, and we never receive any events. - * (FDO bug #18668) */ - if (changedScreen -#ifdef PANORAMIX - && noPanoramiXExtension -#endif - ) - UpdateSpriteForScreen (pDev, pScreen) ; -} - -/* - * Pointer/CursorDisplay interface routines - */ - -/* - * miPointerUpdateSprite - * - * Syncronize the sprite with the cursor - called from ProcessInputEvents - */ - -void -miPointerUpdateSprite (DeviceIntPtr pDev) -{ - ScreenPtr pScreen; - miPointerScreenPtr pScreenPriv; - CursorPtr pCursor; - int x, y, devx, devy; - miPointerPtr pPointer; - - if (!pDev || !pDev->coreEvents) - return; - - pPointer = MIPOINTER(pDev); - - if (!pPointer) - return; - - pScreen = pPointer->pScreen; - if (!pScreen) - return; - - x = pPointer->x; - y = pPointer->y; - devx = pPointer->devx; - devy = pPointer->devy; - - pScreenPriv = GetScreenPrivate (pScreen); - /* - * if the cursor has switched screens, disable the sprite - * on the old screen - */ - if (pScreen != pPointer->pSpriteScreen) - { - if (pPointer->pSpriteScreen) - { - miPointerScreenPtr pOldPriv; - - pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); - if (pPointer->pCursor) - { - (*pOldPriv->spriteFuncs->SetCursor) - (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); - } - (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); - } - (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); - (*pScreenPriv->spriteFuncs->SetCursor) - (pDev, pScreen, pPointer->pCursor, x, y); - pPointer->devx = x; - pPointer->devy = y; - pPointer->pSpriteCursor = pPointer->pCursor; - pPointer->pSpriteScreen = pScreen; - } - /* - * if the cursor has changed, display the new one - */ - else if (pPointer->pCursor != pPointer->pSpriteCursor) - { - pCursor = pPointer->pCursor; - if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) - pCursor = NullCursor; - (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); - - pPointer->devx = x; - pPointer->devy = y; - pPointer->pSpriteCursor = pPointer->pCursor; - } - else if (x != devx || y != devy) - { - pPointer->devx = x; - pPointer->devy = y; - if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); - } -} - -void -miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) -{ - miPointerScreenPtr pScreenPriv; - ScreenPtr pScreen; - miPointerPtr pPointer; - - pPointer = MIPOINTER(pDev); - - pScreen = screenInfo.screens[screen_no]; - pScreenPriv = GetScreenPrivate (pScreen); - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); - NewCurrentScreen (pDev, pScreen, x, y); - - pPointer->limits.x2 = pScreen->width; - pPointer->limits.y2 = pScreen->height; -} - -ScreenPtr -miPointerCurrentScreen (void) -{ - return miPointerGetScreen(inputInfo.pointer); -} - -ScreenPtr -miPointerGetScreen(DeviceIntPtr pDev) -{ - miPointerPtr pPointer = MIPOINTER(pDev); - return (pPointer) ? pPointer->pScreen : NULL; -} - -/* Move the pointer on the current screen, and update the sprite. */ -static void -miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y) -{ - miPointerPtr pPointer; - SetupScreen(pScreen); - - pPointer = MIPOINTER(pDev); - - /* Hack: We mustn't call into ->MoveCursor for anything but the - * VCP, as this may cause a non-HW rendered cursor to be rendered during - * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT. - */ - if ((pDev == inputInfo.pointer || (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer)) - && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) - { - pPointer->devx = x; - pPointer->devy = y; - if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); - } - - pPointer->x = x; - pPointer->y = y; - pPointer->pScreen = pScreen; -} - -void -miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y) -{ - miPointerScreenPtr pScreenPriv; - ScreenPtr pScreen; - ScreenPtr newScreen; - - miPointerPtr pPointer; - - if (!pDev || !pDev->coreEvents) - return; - - pPointer = MIPOINTER(pDev); - pScreen = pPointer->pScreen; - if (!pScreen) - return; /* called before ready */ - - if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) - { - pScreenPriv = GetScreenPrivate (pScreen); - if (!pPointer->confined) - { - newScreen = pScreen; - (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); - if (newScreen != pScreen) - { - pScreen = newScreen; - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, - FALSE); - pScreenPriv = GetScreenPrivate (pScreen); - /* Smash the confine to the new screen */ - pPointer->limits.x2 = pScreen->width; - pPointer->limits.y2 = pScreen->height; - } - } - } - /* Constrain the sprite to the current limits. */ - if (*x < pPointer->limits.x1) - *x = pPointer->limits.x1; - if (*x >= pPointer->limits.x2) - *x = pPointer->limits.x2 - 1; - if (*y < pPointer->limits.y1) - *y = pPointer->limits.y1; - if (*y >= pPointer->limits.y2) - *y = pPointer->limits.y2 - 1; - - if (pPointer->x == *x && pPointer->y == *y && - pPointer->pScreen == pScreen) - return; - - miPointerMoved(pDev, pScreen, *x, *y); -} - -void -miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) -{ - *x = MIPOINTER(pDev)->x; - *y = MIPOINTER(pDev)->y; -} - -#ifdef XQUARTZ -#include <pthread.h> -void darwinEvents_lock(void); -void darwinEvents_unlock(void); -#endif - -void -miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - int i, nevents; - int valuators[2]; - - miPointerMoved(pDev, pScreen, x, y); - - /* generate motion notify */ - valuators[0] = x; - valuators[1] = y; - - if (!events) - { - events = InitEventList(GetMaximumEventsNum()); - - if (!events) - { - FatalError("Could not allocate event store.\n"); - return; - } - } - - nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_SCREEN | POINTER_ABSOLUTE, 0, 2, valuators); - - OsBlockSignals(); -#ifdef XQUARTZ - darwinEvents_lock(); -#endif - for (i = 0; i < nevents; i++) - mieqEnqueue(pDev, (InternalEvent*)events[i].event); -#ifdef XQUARTZ - darwinEvents_unlock(); -#endif - OsReleaseSignals(); -} +/*
+
+Copyright 1989, 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 <X11/X.h>
+# include <X11/Xmd.h>
+# include <X11/Xproto.h>
+# include "misc.h"
+# include "windowstr.h"
+# include "pixmapstr.h"
+# include "mi.h"
+# include "scrnintstr.h"
+# include "mipointrst.h"
+# include "cursorstr.h"
+# include "dixstruct.h"
+# include "inputstr.h"
+
+static int miPointerScreenKeyIndex;
+DevPrivateKey miPointerScreenKey = &miPointerScreenKeyIndex;
+
+#define GetScreenPrivate(s) ((miPointerScreenPtr) \
+ dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
+#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
+
+static int miPointerPrivKeyIndex;
+static DevPrivateKey miPointerPrivKey = &miPointerPrivKeyIndex;
+
+#define MIPOINTER(dev) \
+ ((!IsMaster(dev) && !dev->u.master) ? \
+ (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
+ (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
+
+static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor);
+static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor);
+static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor);
+static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ BoxPtr pBox);
+static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor, BoxPtr pHotBox,
+ BoxPtr pTopLeftBox);
+static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y,
+ Bool generateEvent);
+static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
+static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y);
+static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
+static void miPointerDeviceCleanup(DeviceIntPtr pDev,
+ ScreenPtr pScreen);
+
+static EventList* events; /* for WarpPointer MotionNotifies */
+
+Bool
+miPointerInitialize (ScreenPtr pScreen,
+ miPointerSpriteFuncPtr spriteFuncs,
+ miPointerScreenFuncPtr screenFuncs,
+ Bool waitForUpdate)
+{
+ miPointerScreenPtr pScreenPriv;
+
+ pScreenPriv = malloc(sizeof (miPointerScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+ pScreenPriv->spriteFuncs = spriteFuncs;
+ pScreenPriv->screenFuncs = screenFuncs;
+ /*
+ * check for uninitialized methods
+ */
+ if (!screenFuncs->EnqueueEvent)
+ screenFuncs->EnqueueEvent = mieqEnqueue;
+ if (!screenFuncs->NewEventScreen)
+ screenFuncs->NewEventScreen = mieqSwitchScreen;
+ pScreenPriv->waitForUpdate = waitForUpdate;
+ pScreenPriv->showTransparent = FALSE;
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = miPointerCloseScreen;
+ dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
+ /*
+ * set up screen cursor method table
+ */
+ pScreen->ConstrainCursor = miPointerConstrainCursor;
+ pScreen->CursorLimits = miPointerCursorLimits;
+ pScreen->DisplayCursor = miPointerDisplayCursor;
+ pScreen->RealizeCursor = miPointerRealizeCursor;
+ pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
+ pScreen->SetCursorPosition = miPointerSetCursorPosition;
+ pScreen->RecolorCursor = miRecolorCursor;
+ pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
+ pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
+
+ events = NULL;
+ return TRUE;
+}
+
+static Bool
+miPointerCloseScreen (int index, ScreenPtr pScreen)
+{
+#if 0
+ miPointerPtr pPointer;
+ DeviceIntPtr pDev;
+#endif
+
+ SetupScreen(pScreen);
+
+#if 0
+ for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pPointer = MIPOINTER(pDev);
+
+ if (pScreen == pPointer->pScreen)
+ pPointer->pScreen = 0;
+ if (pScreen == pPointer->pSpriteScreen)
+ pPointer->pSpriteScreen = 0;
+ }
+ }
+
+ if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
+ MIPOINTER(inputInfo.pointer)->pScreen = 0;
+ if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
+ MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
+#endif
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ free((pointer) pScreenPriv);
+ FreeEventList(events, GetMaximumEventsNum());
+ events = NULL;
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+/*
+ * DIX/DDX interface routines
+ */
+
+static Bool
+miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
+{
+ SetupScreen(pScreen);
+ return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
+}
+
+static Bool
+miPointerUnrealizeCursor (DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+ SetupScreen(pScreen);
+ return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
+}
+
+static Bool
+miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
+{
+ miPointerPtr pPointer;
+
+ /* return for keyboards */
+ if ((IsMaster(pDev) && !DevHasCursor(pDev)) ||
+ (!IsMaster(pDev) && pDev->u.master && !DevHasCursor(pDev->u.master)))
+ return FALSE;
+
+ pPointer = MIPOINTER(pDev);
+
+ pPointer->pCursor = pCursor;
+ pPointer->pScreen = pScreen;
+ miPointerUpdateSprite(pDev);
+ return TRUE;
+}
+
+static void
+miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
+{
+ miPointerPtr pPointer;
+
+ pPointer = MIPOINTER(pDev);
+
+ pPointer->limits = *pBox;
+ pPointer->confined = PointerConfinedToScreen(pDev);
+}
+
+/*ARGSUSED*/
+static void
+miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
+ BoxPtr pHotBox, BoxPtr pTopLeftBox)
+{
+ *pTopLeftBox = *pHotBox;
+}
+
+static Bool GenerateEvent;
+
+static Bool
+miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y, Bool generateEvent)
+{
+ SetupScreen (pScreen);
+
+ GenerateEvent = generateEvent;
+ /* device dependent - must pend signal and call miPointerWarpCursor */
+ (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
+ if (!generateEvent)
+ miPointerUpdateSprite(pDev);
+ return TRUE;
+}
+
+/* Set up sprite information for the device.
+ This function will be called once for each device after it is initialized
+ in the DIX.
+ */
+static Bool
+miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miPointerPtr pPointer;
+ SetupScreen (pScreen);
+
+ pPointer = malloc(sizeof(miPointerRec));
+ if (!pPointer)
+ return FALSE;
+
+ pPointer->pScreen = NULL;
+ pPointer->pSpriteScreen = NULL;
+ pPointer->pCursor = NULL;
+ pPointer->pSpriteCursor = NULL;
+ pPointer->limits.x1 = 0;
+ pPointer->limits.x2 = 32767;
+ pPointer->limits.y1 = 0;
+ pPointer->limits.y2 = 32767;
+ pPointer->confined = FALSE;
+ pPointer->x = 0;
+ pPointer->y = 0;
+
+ if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
+ {
+ free(pPointer);
+ return FALSE;
+ }
+
+ dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
+ return TRUE;
+}
+
+/* Clean up after device.
+ This function will be called once before the device is freed in the DIX
+ */
+static void
+miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ SetupScreen(pScreen);
+
+ if (!IsMaster(pDev) && pDev->u.master)
+ return;
+
+ (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
+ free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
+ dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
+}
+
+
+/* Once signals are ignored, the WarpCursor function can call this */
+
+void
+miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+ miPointerPtr pPointer;
+ BOOL changedScreen = FALSE;
+
+ SetupScreen (pScreen);
+ pPointer = MIPOINTER(pDev);
+
+ if (pPointer->pScreen != pScreen)
+ {
+ (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
+ changedScreen = TRUE;
+ }
+
+ if (GenerateEvent)
+ {
+ miPointerMove (pDev, pScreen, x, y);
+ }
+ else
+ {
+ /* everything from miPointerMove except the event and history */
+
+ if (!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
+ {
+ pPointer->devx = x;
+ pPointer->devy = y;
+ if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
+ (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
+ }
+ pPointer->x = x;
+ pPointer->y = y;
+ pPointer->pScreen = pScreen;
+ }
+
+ /* Don't call USFS if we use Xinerama, otherwise the root window is
+ * updated to the second screen, and we never receive any events.
+ * (FDO bug #18668) */
+ if (changedScreen
+#ifdef PANORAMIX
+ && noPanoramiXExtension
+#endif
+ )
+ UpdateSpriteForScreen (pDev, pScreen) ;
+}
+
+/*
+ * Pointer/CursorDisplay interface routines
+ */
+
+/*
+ * miPointerUpdateSprite
+ *
+ * Syncronize the sprite with the cursor - called from ProcessInputEvents
+ */
+
+void
+miPointerUpdateSprite (DeviceIntPtr pDev)
+{
+ ScreenPtr pScreen;
+ miPointerScreenPtr pScreenPriv;
+ CursorPtr pCursor;
+ int x, y, devx, devy;
+ miPointerPtr pPointer;
+
+ if (!pDev || !pDev->coreEvents)
+ return;
+
+ pPointer = MIPOINTER(pDev);
+
+ if (!pPointer)
+ return;
+
+ pScreen = pPointer->pScreen;
+ if (!pScreen)
+ return;
+
+ x = pPointer->x;
+ y = pPointer->y;
+ devx = pPointer->devx;
+ devy = pPointer->devy;
+
+ pScreenPriv = GetScreenPrivate (pScreen);
+ /*
+ * if the cursor has switched screens, disable the sprite
+ * on the old screen
+ */
+ if (pScreen != pPointer->pSpriteScreen)
+ {
+ if (pPointer->pSpriteScreen)
+ {
+ miPointerScreenPtr pOldPriv;
+
+ pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
+ if (pPointer->pCursor)
+ {
+ (*pOldPriv->spriteFuncs->SetCursor)
+ (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
+ }
+ (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
+ }
+ (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
+ (*pScreenPriv->spriteFuncs->SetCursor)
+ (pDev, pScreen, pPointer->pCursor, x, y);
+ pPointer->devx = x;
+ pPointer->devy = y;
+ pPointer->pSpriteCursor = pPointer->pCursor;
+ pPointer->pSpriteScreen = pScreen;
+ }
+ /*
+ * if the cursor has changed, display the new one
+ */
+ else if (pPointer->pCursor != pPointer->pSpriteCursor)
+ {
+ pCursor = pPointer->pCursor;
+ if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
+ pCursor = NullCursor;
+ (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
+
+ pPointer->devx = x;
+ pPointer->devy = y;
+ pPointer->pSpriteCursor = pPointer->pCursor;
+ }
+ else if (x != devx || y != devy)
+ {
+ pPointer->devx = x;
+ pPointer->devy = y;
+ if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
+ (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
+ }
+}
+
+void
+miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
+{
+ miPointerScreenPtr pScreenPriv;
+ ScreenPtr pScreen;
+ miPointerPtr pPointer;
+
+ pPointer = MIPOINTER(pDev);
+
+ pScreen = screenInfo.screens[screen_no];
+ pScreenPriv = GetScreenPrivate (pScreen);
+ (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
+ NewCurrentScreen (pDev, pScreen, x, y);
+
+ pPointer->limits.x2 = pScreen->width;
+ pPointer->limits.y2 = pScreen->height;
+}
+
+ScreenPtr
+miPointerCurrentScreen (void)
+{
+ return miPointerGetScreen(inputInfo.pointer);
+}
+
+ScreenPtr
+miPointerGetScreen(DeviceIntPtr pDev)
+{
+ miPointerPtr pPointer = MIPOINTER(pDev);
+ return (pPointer) ? pPointer->pScreen : NULL;
+}
+
+/* Move the pointer on the current screen, and update the sprite. */
+static void
+miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y)
+{
+ miPointerPtr pPointer;
+ SetupScreen(pScreen);
+
+ pPointer = MIPOINTER(pDev);
+
+ /* Hack: We mustn't call into ->MoveCursor for anything but the
+ * VCP, as this may cause a non-HW rendered cursor to be rendered during
+ * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
+ */
+ if ((pDev == inputInfo.pointer || (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
+ && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
+ {
+ pPointer->devx = x;
+ pPointer->devy = y;
+ if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
+ (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
+ }
+
+ pPointer->x = x;
+ pPointer->y = y;
+ pPointer->pScreen = pScreen;
+}
+
+void
+miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
+{
+ miPointerScreenPtr pScreenPriv;
+ ScreenPtr pScreen;
+ ScreenPtr newScreen;
+
+ miPointerPtr pPointer;
+
+ if (!pDev || !pDev->coreEvents)
+ return;
+
+ pPointer = MIPOINTER(pDev);
+ pScreen = pPointer->pScreen;
+ if (!pScreen)
+ return; /* called before ready */
+
+ if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
+ {
+ pScreenPriv = GetScreenPrivate (pScreen);
+ if (!pPointer->confined)
+ {
+ newScreen = pScreen;
+ (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
+ if (newScreen != pScreen)
+ {
+ pScreen = newScreen;
+ (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
+ FALSE);
+ pScreenPriv = GetScreenPrivate (pScreen);
+ /* Smash the confine to the new screen */
+ pPointer->limits.x2 = pScreen->width;
+ pPointer->limits.y2 = pScreen->height;
+ }
+ }
+ }
+ /* Constrain the sprite to the current limits. */
+ if (*x < pPointer->limits.x1)
+ *x = pPointer->limits.x1;
+ if (*x >= pPointer->limits.x2)
+ *x = pPointer->limits.x2 - 1;
+ if (*y < pPointer->limits.y1)
+ *y = pPointer->limits.y1;
+ if (*y >= pPointer->limits.y2)
+ *y = pPointer->limits.y2 - 1;
+
+ if (pPointer->x == *x && pPointer->y == *y &&
+ pPointer->pScreen == pScreen)
+ return;
+
+ miPointerMoved(pDev, pScreen, *x, *y);
+}
+
+void
+miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
+{
+ *x = MIPOINTER(pDev)->x;
+ *y = MIPOINTER(pDev)->y;
+}
+
+#ifdef XQUARTZ
+#include <pthread.h>
+void darwinEvents_lock(void);
+void darwinEvents_unlock(void);
+#endif
+
+void
+miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+ int i, nevents;
+ int valuators[2];
+
+ miPointerMoved(pDev, pScreen, x, y);
+
+ /* generate motion notify */
+ valuators[0] = x;
+ valuators[1] = y;
+
+ if (!events)
+ {
+ events = InitEventList(GetMaximumEventsNum());
+
+ if (!events)
+ {
+ FatalError("Could not allocate event store.\n");
+ return;
+ }
+ }
+
+ nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_SCREEN | POINTER_ABSOLUTE, 0, 2, valuators);
+
+ OsBlockSignals();
+#ifdef XQUARTZ
+ darwinEvents_lock();
+#endif
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(pDev, (InternalEvent*)events[i].event);
+#ifdef XQUARTZ
+ darwinEvents_unlock();
+#endif
+ OsReleaseSignals();
+}
diff --git a/xorg-server/mi/mipolycon.c b/xorg-server/mi/mipolycon.c index 79384881d..170b2aa1a 100644 --- a/xorg-server/mi/mipolycon.c +++ b/xorg-server/mi/mipolycon.c @@ -1,247 +1,247 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 "gcstruct.h" -#include "pixmap.h" -#include "mi.h" -#include "miscanfill.h" - -static int getPolyYBounds(DDXPointPtr pts, int n, int *by, int *ty); - -/* - * convexpoly.c - * - * Written by Brian Kelleher; Dec. 1985. - * - * Fill a convex polygon. If the given polygon - * is not convex, then the result is undefined. - * The algorithm is to order the edges from smallest - * y to largest by partitioning the array into a left - * edge list and a right edge list. The algorithm used - * to traverse each edge is an extension of Bresenham's - * line algorithm with y as the major axis. - * For a derivation of the algorithm, see the author of - * this code. - */ -Bool -miFillConvexPoly( - DrawablePtr dst, - GCPtr pgc, - int count, /* number of points */ - DDXPointPtr ptsIn /* the points */ - ) -{ - int xl = 0, xr = 0; /* x vals of left and right edges */ - int dl = 0, dr = 0; /* decision variables */ - int ml = 0, m1l = 0;/* left edge slope and slope+1 */ - int mr = 0, m1r = 0; /* right edge slope and slope+1 */ - int incr1l = 0, incr2l = 0; /* left edge error increments */ - int incr1r = 0, incr2r = 0; /* right edge error increments */ - int dy; /* delta y */ - int y; /* current scanline */ - int left, right; /* indices to first endpoints */ - int i; /* loop counter */ - int nextleft, nextright; /* indices to second endpoints */ - DDXPointPtr ptsOut, FirstPoint; /* output buffer */ - int *width, *FirstWidth; /* output buffer */ - int imin; /* index of smallest vertex (in y) */ - int ymin; /* y-extents of polygon */ - int ymax; - - /* - * find leftx, bottomy, rightx, topy, and the index - * of bottomy. Also translate the points. - */ - imin = getPolyYBounds(ptsIn, count, &ymin, &ymax); - - dy = ymax - ymin + 1; - if ((count < 3) || (dy < 0)) - return(TRUE); - ptsOut = FirstPoint = xalloc(sizeof(DDXPointRec)*dy); - width = FirstWidth = xalloc(sizeof(int) * dy); - if(!FirstPoint || !FirstWidth) - { - if (FirstWidth) xfree(FirstWidth); - if (FirstPoint) xfree(FirstPoint); - return(FALSE); - } - - nextleft = nextright = imin; - y = ptsIn[nextleft].y; - - /* - * loop through all edges of the polygon - */ - do { - /* - * add a left edge if we need to - */ - if (ptsIn[nextleft].y == y) { - left = nextleft; - - /* - * find the next edge, considering the end - * conditions of the array. - */ - nextleft++; - if (nextleft >= count) - nextleft = 0; - - /* - * now compute all of the random information - * needed to run the iterative algorithm. - */ - BRESINITPGON(ptsIn[nextleft].y-ptsIn[left].y, - ptsIn[left].x,ptsIn[nextleft].x, - xl, dl, ml, m1l, incr1l, incr2l); - } - - /* - * add a right edge if we need to - */ - if (ptsIn[nextright].y == y) { - right = nextright; - - /* - * find the next edge, considering the end - * conditions of the array. - */ - nextright--; - if (nextright < 0) - nextright = count-1; - - /* - * now compute all of the random information - * needed to run the iterative algorithm. - */ - BRESINITPGON(ptsIn[nextright].y-ptsIn[right].y, - ptsIn[right].x,ptsIn[nextright].x, - xr, dr, mr, m1r, incr1r, incr2r); - } - - /* - * generate scans to fill while we still have - * a right edge as well as a left edge. - */ - i = min(ptsIn[nextleft].y, ptsIn[nextright].y) - y; - /* in case we're called with non-convex polygon */ - if(i < 0) - { - xfree(FirstWidth); - xfree(FirstPoint); - return(TRUE); - } - while (i-- > 0) - { - ptsOut->y = y; - - /* - * reverse the edges if necessary - */ - if (xl < xr) - { - *(width++) = xr - xl; - (ptsOut++)->x = xl; - } - else - { - *(width++) = xl - xr; - (ptsOut++)->x = xr; - } - y++; - - /* increment down the edges */ - BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l); - BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r); - } - } while (y != ymax); - - /* - * Finally, fill the <remaining> spans - */ - (*pgc->ops->FillSpans)(dst, pgc, - ptsOut-FirstPoint,FirstPoint,FirstWidth, - 1); - xfree(FirstWidth); - xfree(FirstPoint); - return(TRUE); -} - - -/* - * Find the index of the point with the smallest y. - */ -static int -getPolyYBounds(DDXPointPtr pts, int n, int *by, int *ty) -{ - DDXPointPtr ptMin; - int ymin, ymax; - DDXPointPtr ptsStart = pts; - - ptMin = pts; - ymin = ymax = (pts++)->y; - - while (--n > 0) { - if (pts->y < ymin) - { - ptMin = pts; - ymin = pts->y; - } - if(pts->y > ymax) - ymax = pts->y; - - pts++; - } - - *by = ymin; - *ty = ymax; - return(ptMin-ptsStart); -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 "gcstruct.h"
+#include "pixmap.h"
+#include "mi.h"
+#include "miscanfill.h"
+
+static int getPolyYBounds(DDXPointPtr pts, int n, int *by, int *ty);
+
+/*
+ * convexpoly.c
+ *
+ * Written by Brian Kelleher; Dec. 1985.
+ *
+ * Fill a convex polygon. If the given polygon
+ * is not convex, then the result is undefined.
+ * The algorithm is to order the edges from smallest
+ * y to largest by partitioning the array into a left
+ * edge list and a right edge list. The algorithm used
+ * to traverse each edge is an extension of Bresenham's
+ * line algorithm with y as the major axis.
+ * For a derivation of the algorithm, see the author of
+ * this code.
+ */
+Bool
+miFillConvexPoly(
+ DrawablePtr dst,
+ GCPtr pgc,
+ int count, /* number of points */
+ DDXPointPtr ptsIn /* the points */
+ )
+{
+ int xl = 0, xr = 0; /* x vals of left and right edges */
+ int dl = 0, dr = 0; /* decision variables */
+ int ml = 0, m1l = 0;/* left edge slope and slope+1 */
+ int mr = 0, m1r = 0; /* right edge slope and slope+1 */
+ int incr1l = 0, incr2l = 0; /* left edge error increments */
+ int incr1r = 0, incr2r = 0; /* right edge error increments */
+ int dy; /* delta y */
+ int y; /* current scanline */
+ int left, right; /* indices to first endpoints */
+ int i; /* loop counter */
+ int nextleft, nextright; /* indices to second endpoints */
+ DDXPointPtr ptsOut, FirstPoint; /* output buffer */
+ int *width, *FirstWidth; /* output buffer */
+ int imin; /* index of smallest vertex (in y) */
+ int ymin; /* y-extents of polygon */
+ int ymax;
+
+ /*
+ * find leftx, bottomy, rightx, topy, and the index
+ * of bottomy. Also translate the points.
+ */
+ imin = getPolyYBounds(ptsIn, count, &ymin, &ymax);
+
+ dy = ymax - ymin + 1;
+ if ((count < 3) || (dy < 0))
+ return(TRUE);
+ ptsOut = FirstPoint = malloc(sizeof(DDXPointRec)*dy);
+ width = FirstWidth = malloc(sizeof(int) * dy);
+ if(!FirstPoint || !FirstWidth)
+ {
+ if (FirstWidth) free(FirstWidth);
+ if (FirstPoint) free(FirstPoint);
+ return(FALSE);
+ }
+
+ nextleft = nextright = imin;
+ y = ptsIn[nextleft].y;
+
+ /*
+ * loop through all edges of the polygon
+ */
+ do {
+ /*
+ * add a left edge if we need to
+ */
+ if (ptsIn[nextleft].y == y) {
+ left = nextleft;
+
+ /*
+ * find the next edge, considering the end
+ * conditions of the array.
+ */
+ nextleft++;
+ if (nextleft >= count)
+ nextleft = 0;
+
+ /*
+ * now compute all of the random information
+ * needed to run the iterative algorithm.
+ */
+ BRESINITPGON(ptsIn[nextleft].y-ptsIn[left].y,
+ ptsIn[left].x,ptsIn[nextleft].x,
+ xl, dl, ml, m1l, incr1l, incr2l);
+ }
+
+ /*
+ * add a right edge if we need to
+ */
+ if (ptsIn[nextright].y == y) {
+ right = nextright;
+
+ /*
+ * find the next edge, considering the end
+ * conditions of the array.
+ */
+ nextright--;
+ if (nextright < 0)
+ nextright = count-1;
+
+ /*
+ * now compute all of the random information
+ * needed to run the iterative algorithm.
+ */
+ BRESINITPGON(ptsIn[nextright].y-ptsIn[right].y,
+ ptsIn[right].x,ptsIn[nextright].x,
+ xr, dr, mr, m1r, incr1r, incr2r);
+ }
+
+ /*
+ * generate scans to fill while we still have
+ * a right edge as well as a left edge.
+ */
+ i = min(ptsIn[nextleft].y, ptsIn[nextright].y) - y;
+ /* in case we're called with non-convex polygon */
+ if(i < 0)
+ {
+ free(FirstWidth);
+ free(FirstPoint);
+ return(TRUE);
+ }
+ while (i-- > 0)
+ {
+ ptsOut->y = y;
+
+ /*
+ * reverse the edges if necessary
+ */
+ if (xl < xr)
+ {
+ *(width++) = xr - xl;
+ (ptsOut++)->x = xl;
+ }
+ else
+ {
+ *(width++) = xl - xr;
+ (ptsOut++)->x = xr;
+ }
+ y++;
+
+ /* increment down the edges */
+ BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
+ BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
+ }
+ } while (y != ymax);
+
+ /*
+ * Finally, fill the <remaining> spans
+ */
+ (*pgc->ops->FillSpans)(dst, pgc,
+ ptsOut-FirstPoint,FirstPoint,FirstWidth,
+ 1);
+ free(FirstWidth);
+ free(FirstPoint);
+ return(TRUE);
+}
+
+
+/*
+ * Find the index of the point with the smallest y.
+ */
+static int
+getPolyYBounds(DDXPointPtr pts, int n, int *by, int *ty)
+{
+ DDXPointPtr ptMin;
+ int ymin, ymax;
+ DDXPointPtr ptsStart = pts;
+
+ ptMin = pts;
+ ymin = ymax = (pts++)->y;
+
+ while (--n > 0) {
+ if (pts->y < ymin)
+ {
+ ptMin = pts;
+ ymin = pts->y;
+ }
+ if(pts->y > ymax)
+ ymax = pts->y;
+
+ pts++;
+ }
+
+ *by = ymin;
+ *ty = ymax;
+ return(ptMin-ptsStart);
+}
diff --git a/xorg-server/mi/mipolygen.c b/xorg-server/mi/mipolygen.c index 4744583c3..3dbf68960 100644 --- a/xorg-server/mi/mipolygen.c +++ b/xorg-server/mi/mipolygen.c @@ -1,230 +1,230 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <X11/X.h> -#include "gcstruct.h" -#include "miscanfill.h" -#include "mipoly.h" -#include "pixmap.h" -#include "mi.h" - -/* - * - * Written by Brian Kelleher; Oct. 1985 - * - * Routine to fill a polygon. Two fill rules are - * supported: frWINDING and frEVENODD. - * - * See fillpoly.h for a complete description of the algorithm. - */ - -Bool -miFillGeneralPoly( - DrawablePtr dst, - GCPtr pgc, - int count, /* number of points */ - DDXPointPtr ptsIn /* the points */ - ) -{ - EdgeTableEntry *pAET; /* the Active Edge Table */ - int y; /* the current scanline */ - int nPts = 0; /* number of pts in buffer */ - EdgeTableEntry *pWETE; /* Winding Edge Table */ - ScanLineList *pSLL; /* Current ScanLineList */ - DDXPointPtr ptsOut; /* ptr to output buffers */ - int *width; - DDXPointRec FirstPoint[NUMPTSTOBUFFER]; /* the output buffers */ - int FirstWidth[NUMPTSTOBUFFER]; - EdgeTableEntry *pPrevAET; /* previous AET entry */ - EdgeTable ET; /* Edge Table header node */ - EdgeTableEntry AET; /* Active ET header node */ - EdgeTableEntry *pETEs; /* Edge Table Entries buff */ - ScanLineListBlock SLLBlock; /* header for ScanLineList */ - int fixWAET = 0; - - if (count < 3) - return(TRUE); - - if(!(pETEs = xalloc(sizeof(EdgeTableEntry) * count))) - return(FALSE); - ptsOut = FirstPoint; - width = FirstWidth; - if (!miCreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock)) - { - xfree(pETEs); - return(FALSE); - } - pSLL = ET.scanlines.next; - - if (pgc->fillRule == EvenOddRule) - { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; y++) - { - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL && y == pSLL->scanline) - { - miloadAET(&AET, pSLL->edgelist); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - - /* - * for each active edge - */ - while (pAET) - { - ptsOut->x = pAET->bres.minor; - ptsOut++->y = y; - *width++ = pAET->next->bres.minor - pAET->bres.minor; - nPts++; - - /* - * send out the buffer when its full - */ - if (nPts == NUMPTSTOBUFFER) - { - (*pgc->ops->FillSpans)(dst, pgc, - nPts, FirstPoint, FirstWidth, - 1); - ptsOut = FirstPoint; - width = FirstWidth; - nPts = 0; - } - EVALUATEEDGEEVENODD(pAET, pPrevAET, y) - EVALUATEEDGEEVENODD(pAET, pPrevAET, y); - } - miInsertionSort(&AET); - } - } - else /* default to WindingNumber */ - { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; y++) - { - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL && y == pSLL->scanline) - { - miloadAET(&AET, pSLL->edgelist); - micomputeWAET(&AET); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - pWETE = pAET; - - /* - * for each active edge - */ - while (pAET) - { - /* - * if the next edge in the active edge table is - * also the next edge in the winding active edge - * table. - */ - if (pWETE == pAET) - { - ptsOut->x = pAET->bres.minor; - ptsOut++->y = y; - *width++ = pAET->nextWETE->bres.minor - pAET->bres.minor; - nPts++; - - /* - * send out the buffer - */ - if (nPts == NUMPTSTOBUFFER) - { - (*pgc->ops->FillSpans)(dst, pgc, nPts, FirstPoint, - FirstWidth, 1); - ptsOut = FirstPoint; - width = FirstWidth; - nPts = 0; - } - - pWETE = pWETE->nextWETE; - while (pWETE != pAET) - EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); - pWETE = pWETE->nextWETE; - } - EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); - } - - /* - * reevaluate the Winding active edge table if we - * just had to resort it or if we just exited an edge. - */ - if (miInsertionSort(&AET) || fixWAET) - { - micomputeWAET(&AET); - fixWAET = 0; - } - } - } - - /* - * Get any spans that we missed by buffering - */ - (*pgc->ops->FillSpans)(dst, pgc, nPts, FirstPoint, FirstWidth, 1); - xfree(pETEs); - miFreeStorage(SLLBlock.next); - return(TRUE); -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <X11/X.h>
+#include "gcstruct.h"
+#include "miscanfill.h"
+#include "mipoly.h"
+#include "pixmap.h"
+#include "mi.h"
+
+/*
+ *
+ * Written by Brian Kelleher; Oct. 1985
+ *
+ * Routine to fill a polygon. Two fill rules are
+ * supported: frWINDING and frEVENODD.
+ *
+ * See fillpoly.h for a complete description of the algorithm.
+ */
+
+Bool
+miFillGeneralPoly(
+ DrawablePtr dst,
+ GCPtr pgc,
+ int count, /* number of points */
+ DDXPointPtr ptsIn /* the points */
+ )
+{
+ EdgeTableEntry *pAET; /* the Active Edge Table */
+ int y; /* the current scanline */
+ int nPts = 0; /* number of pts in buffer */
+ EdgeTableEntry *pWETE; /* Winding Edge Table */
+ ScanLineList *pSLL; /* Current ScanLineList */
+ DDXPointPtr ptsOut; /* ptr to output buffers */
+ int *width;
+ DDXPointRec FirstPoint[NUMPTSTOBUFFER]; /* the output buffers */
+ int FirstWidth[NUMPTSTOBUFFER];
+ EdgeTableEntry *pPrevAET; /* previous AET entry */
+ EdgeTable ET; /* Edge Table header node */
+ EdgeTableEntry AET; /* Active ET header node */
+ EdgeTableEntry *pETEs; /* Edge Table Entries buff */
+ ScanLineListBlock SLLBlock; /* header for ScanLineList */
+ int fixWAET = 0;
+
+ if (count < 3)
+ return(TRUE);
+
+ if(!(pETEs = malloc(sizeof(EdgeTableEntry) * count)))
+ return(FALSE);
+ ptsOut = FirstPoint;
+ width = FirstWidth;
+ if (!miCreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock))
+ {
+ free(pETEs);
+ return(FALSE);
+ }
+ pSLL = ET.scanlines.next;
+
+ if (pgc->fillRule == EvenOddRule)
+ {
+ /*
+ * for each scanline
+ */
+ for (y = ET.ymin; y < ET.ymax; y++)
+ {
+ /*
+ * Add a new edge to the active edge table when we
+ * get to the next edge.
+ */
+ if (pSLL && y == pSLL->scanline)
+ {
+ miloadAET(&AET, pSLL->edgelist);
+ pSLL = pSLL->next;
+ }
+ pPrevAET = &AET;
+ pAET = AET.next;
+
+ /*
+ * for each active edge
+ */
+ while (pAET)
+ {
+ ptsOut->x = pAET->bres.minor;
+ ptsOut++->y = y;
+ *width++ = pAET->next->bres.minor - pAET->bres.minor;
+ nPts++;
+
+ /*
+ * send out the buffer when its full
+ */
+ if (nPts == NUMPTSTOBUFFER)
+ {
+ (*pgc->ops->FillSpans)(dst, pgc,
+ nPts, FirstPoint, FirstWidth,
+ 1);
+ ptsOut = FirstPoint;
+ width = FirstWidth;
+ nPts = 0;
+ }
+ EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
+ EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
+ }
+ miInsertionSort(&AET);
+ }
+ }
+ else /* default to WindingNumber */
+ {
+ /*
+ * for each scanline
+ */
+ for (y = ET.ymin; y < ET.ymax; y++)
+ {
+ /*
+ * Add a new edge to the active edge table when we
+ * get to the next edge.
+ */
+ if (pSLL && y == pSLL->scanline)
+ {
+ miloadAET(&AET, pSLL->edgelist);
+ micomputeWAET(&AET);
+ pSLL = pSLL->next;
+ }
+ pPrevAET = &AET;
+ pAET = AET.next;
+ pWETE = pAET;
+
+ /*
+ * for each active edge
+ */
+ while (pAET)
+ {
+ /*
+ * if the next edge in the active edge table is
+ * also the next edge in the winding active edge
+ * table.
+ */
+ if (pWETE == pAET)
+ {
+ ptsOut->x = pAET->bres.minor;
+ ptsOut++->y = y;
+ *width++ = pAET->nextWETE->bres.minor - pAET->bres.minor;
+ nPts++;
+
+ /*
+ * send out the buffer
+ */
+ if (nPts == NUMPTSTOBUFFER)
+ {
+ (*pgc->ops->FillSpans)(dst, pgc, nPts, FirstPoint,
+ FirstWidth, 1);
+ ptsOut = FirstPoint;
+ width = FirstWidth;
+ nPts = 0;
+ }
+
+ pWETE = pWETE->nextWETE;
+ while (pWETE != pAET)
+ EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
+ pWETE = pWETE->nextWETE;
+ }
+ EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
+ }
+
+ /*
+ * reevaluate the Winding active edge table if we
+ * just had to resort it or if we just exited an edge.
+ */
+ if (miInsertionSort(&AET) || fixWAET)
+ {
+ micomputeWAET(&AET);
+ fixWAET = 0;
+ }
+ }
+ }
+
+ /*
+ * Get any spans that we missed by buffering
+ */
+ (*pgc->ops->FillSpans)(dst, pgc, nPts, FirstPoint, FirstWidth, 1);
+ free(pETEs);
+ miFreeStorage(SLLBlock.next);
+ return(TRUE);
+}
diff --git a/xorg-server/mi/mipolypnt.c b/xorg-server/mi/mipolypnt.c index 12771ee4e..29d3e29e1 100644 --- a/xorg-server/mi/mipolypnt.c +++ b/xorg-server/mi/mipolypnt.c @@ -1,125 +1,125 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <X11/X.h> -#include <X11/Xprotostr.h> -#include "pixmapstr.h" -#include "gcstruct.h" -#include "windowstr.h" -#include "mi.h" - -void -miPolyPoint( - DrawablePtr pDrawable, - GCPtr pGC, - int mode, /* Origin or Previous */ - int npt, - xPoint *pptInit - ) -{ - - int xorg; - int yorg; - int nptTmp; - XID fsOld, fsNew; - int *pwidthInit, *pwidth; - int i; - xPoint *ppt; - - if(!(pwidthInit = xalloc(npt * sizeof(int)))) - return; - - /* make pointlist origin relative */ - if (mode == CoordModePrevious) - { - ppt = pptInit; - nptTmp = npt; - nptTmp--; - while(nptTmp--) - { - ppt++; - ppt->x += (ppt-1)->x; - ppt->y += (ppt-1)->y; - } - } - - if(pGC->miTranslate) - { - ppt = pptInit; - nptTmp = npt; - xorg = pDrawable->x; - yorg = pDrawable->y; - while(nptTmp--) - { - ppt->x += xorg; - ppt++->y += yorg; - } - } - - fsOld = pGC->fillStyle; - fsNew = FillSolid; - if(pGC->fillStyle != FillSolid) - { - DoChangeGC(pGC, GCFillStyle, &fsNew, 0); - ValidateGC(pDrawable, pGC); - } - pwidth = pwidthInit; - for(i = 0; i < npt; i++) - *pwidth++ = 1; - (*pGC->ops->FillSpans)(pDrawable, pGC, npt, pptInit, pwidthInit, FALSE); - - if(fsOld != FillSolid) - { - DoChangeGC(pGC, GCFillStyle, &fsOld, 0); - ValidateGC(pDrawable, pGC); - } - xfree(pwidthInit); -} - +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <X11/X.h>
+#include <X11/Xprotostr.h>
+#include "pixmapstr.h"
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "mi.h"
+
+void
+miPolyPoint(
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ int mode, /* Origin or Previous */
+ int npt,
+ xPoint *pptInit
+ )
+{
+
+ int xorg;
+ int yorg;
+ int nptTmp;
+ ChangeGCVal fsOld, fsNew;
+ int *pwidthInit, *pwidth;
+ int i;
+ xPoint *ppt;
+
+ if(!(pwidthInit = malloc(npt * sizeof(int))))
+ return;
+
+ /* make pointlist origin relative */
+ if (mode == CoordModePrevious)
+ {
+ ppt = pptInit;
+ nptTmp = npt;
+ nptTmp--;
+ while(nptTmp--)
+ {
+ ppt++;
+ ppt->x += (ppt-1)->x;
+ ppt->y += (ppt-1)->y;
+ }
+ }
+
+ if(pGC->miTranslate)
+ {
+ ppt = pptInit;
+ nptTmp = npt;
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+ while(nptTmp--)
+ {
+ ppt->x += xorg;
+ ppt++->y += yorg;
+ }
+ }
+
+ fsOld.val = pGC->fillStyle;
+ fsNew.val = FillSolid;
+ if(pGC->fillStyle != FillSolid)
+ {
+ ChangeGC(NullClient, pGC, GCFillStyle, &fsNew);
+ ValidateGC(pDrawable, pGC);
+ }
+ pwidth = pwidthInit;
+ for(i = 0; i < npt; i++)
+ *pwidth++ = 1;
+ (*pGC->ops->FillSpans)(pDrawable, pGC, npt, pptInit, pwidthInit, FALSE);
+
+ if(fsOld.val != FillSolid)
+ {
+ ChangeGC(NullClient, pGC, GCFillStyle, &fsOld);
+ ValidateGC(pDrawable, pGC);
+ }
+ free(pwidthInit);
+}
+
diff --git a/xorg-server/mi/mipolyrect.c b/xorg-server/mi/mipolyrect.c index 033c7a7c8..8b8810793 100644 --- a/xorg-server/mi/mipolyrect.c +++ b/xorg-server/mi/mipolyrect.c @@ -1,187 +1,187 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <X11/X.h> -#include <X11/Xprotostr.h> -#include "regionstr.h" -#include "gcstruct.h" -#include "pixmap.h" -#include "mi.h" - -void -miPolyRectangle(DrawablePtr pDraw, GCPtr pGC, int nrects, xRectangle *pRects) -{ - int i; - xRectangle *pR = pRects; - DDXPointRec rect[5]; - int bound_tmp; - -#define MINBOUND(dst,eqn) bound_tmp = eqn; \ - if (bound_tmp < -32768) \ - bound_tmp = -32768; \ - dst = bound_tmp; - -#define MAXBOUND(dst,eqn) bound_tmp = eqn; \ - if (bound_tmp > 32767) \ - bound_tmp = 32767; \ - dst = bound_tmp; - -#define MAXUBOUND(dst,eqn) bound_tmp = eqn; \ - if (bound_tmp > 65535) \ - bound_tmp = 65535; \ - dst = bound_tmp; - - if (pGC->lineStyle == LineSolid && pGC->joinStyle == JoinMiter && - pGC->lineWidth != 0) - { - xRectangle *tmp, *t; - int ntmp; - int offset1, offset2, offset3; - int x, y, width, height; - - ntmp = (nrects << 2); - offset2 = pGC->lineWidth; - offset1 = offset2 >> 1; - offset3 = offset2 - offset1; - tmp = xalloc(ntmp * sizeof (xRectangle)); - if (!tmp) - return; - t = tmp; - for (i = 0; i < nrects; i++) - { - x = pR->x; - y = pR->y; - width = pR->width; - height = pR->height; - pR++; - if (width == 0 && height == 0) - { - rect[0].x = x; - rect[0].y = y; - rect[1].x = x; - rect[1].y = y; - (*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 2, rect); - } - else if (height < offset2 || width < offset1) - { - if (height == 0) - { - t->x = x; - t->width = width; - } - else - { - MINBOUND (t->x, x - offset1) - MAXUBOUND (t->width, width + offset2) - } - if (width == 0) - { - t->y = y; - t->height = height; - } - else - { - MINBOUND (t->y, y - offset1) - MAXUBOUND (t->height, height + offset2) - } - t++; - } - else - { - MINBOUND(t->x, x - offset1) - MINBOUND(t->y, y - offset1) - MAXUBOUND(t->width, width + offset2) - t->height = offset2; - t++; - MINBOUND(t->x, x - offset1) - MAXBOUND(t->y, y + offset3); - t->width = offset2; - t->height = height - offset2; - t++; - MAXBOUND(t->x, x + width - offset1); - MAXBOUND(t->y, y + offset3) - t->width = offset2; - t->height = height - offset2; - t++; - MINBOUND(t->x, x - offset1) - MAXBOUND(t->y, y + height - offset1) - MAXUBOUND(t->width, width + offset2) - t->height = offset2; - t++; - } - } - (*pGC->ops->PolyFillRect) (pDraw, pGC, t - tmp, tmp); - xfree ((pointer) tmp); - } - else - { - - for (i=0; i<nrects; i++) - { - rect[0].x = pR->x; - rect[0].y = pR->y; - - MAXBOUND(rect[1].x, pR->x + (int) pR->width) - rect[1].y = rect[0].y; - - rect[2].x = rect[1].x; - MAXBOUND(rect[2].y, pR->y + (int) pR->height); - - rect[3].x = rect[0].x; - rect[3].y = rect[2].y; - - rect[4].x = rect[0].x; - rect[4].y = rect[0].y; - - (*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 5, rect); - pR++; - } - } -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <X11/X.h>
+#include <X11/Xprotostr.h>
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "pixmap.h"
+#include "mi.h"
+
+void
+miPolyRectangle(DrawablePtr pDraw, GCPtr pGC, int nrects, xRectangle *pRects)
+{
+ int i;
+ xRectangle *pR = pRects;
+ DDXPointRec rect[5];
+ int bound_tmp;
+
+#define MINBOUND(dst,eqn) bound_tmp = eqn; \
+ if (bound_tmp < -32768) \
+ bound_tmp = -32768; \
+ dst = bound_tmp;
+
+#define MAXBOUND(dst,eqn) bound_tmp = eqn; \
+ if (bound_tmp > 32767) \
+ bound_tmp = 32767; \
+ dst = bound_tmp;
+
+#define MAXUBOUND(dst,eqn) bound_tmp = eqn; \
+ if (bound_tmp > 65535) \
+ bound_tmp = 65535; \
+ dst = bound_tmp;
+
+ if (pGC->lineStyle == LineSolid && pGC->joinStyle == JoinMiter &&
+ pGC->lineWidth != 0)
+ {
+ xRectangle *tmp, *t;
+ int ntmp;
+ int offset1, offset2, offset3;
+ int x, y, width, height;
+
+ ntmp = (nrects << 2);
+ offset2 = pGC->lineWidth;
+ offset1 = offset2 >> 1;
+ offset3 = offset2 - offset1;
+ tmp = malloc(ntmp * sizeof (xRectangle));
+ if (!tmp)
+ return;
+ t = tmp;
+ for (i = 0; i < nrects; i++)
+ {
+ x = pR->x;
+ y = pR->y;
+ width = pR->width;
+ height = pR->height;
+ pR++;
+ if (width == 0 && height == 0)
+ {
+ rect[0].x = x;
+ rect[0].y = y;
+ rect[1].x = x;
+ rect[1].y = y;
+ (*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 2, rect);
+ }
+ else if (height < offset2 || width < offset1)
+ {
+ if (height == 0)
+ {
+ t->x = x;
+ t->width = width;
+ }
+ else
+ {
+ MINBOUND (t->x, x - offset1)
+ MAXUBOUND (t->width, width + offset2)
+ }
+ if (width == 0)
+ {
+ t->y = y;
+ t->height = height;
+ }
+ else
+ {
+ MINBOUND (t->y, y - offset1)
+ MAXUBOUND (t->height, height + offset2)
+ }
+ t++;
+ }
+ else
+ {
+ MINBOUND(t->x, x - offset1)
+ MINBOUND(t->y, y - offset1)
+ MAXUBOUND(t->width, width + offset2)
+ t->height = offset2;
+ t++;
+ MINBOUND(t->x, x - offset1)
+ MAXBOUND(t->y, y + offset3);
+ t->width = offset2;
+ t->height = height - offset2;
+ t++;
+ MAXBOUND(t->x, x + width - offset1);
+ MAXBOUND(t->y, y + offset3)
+ t->width = offset2;
+ t->height = height - offset2;
+ t++;
+ MINBOUND(t->x, x - offset1)
+ MAXBOUND(t->y, y + height - offset1)
+ MAXUBOUND(t->width, width + offset2)
+ t->height = offset2;
+ t++;
+ }
+ }
+ (*pGC->ops->PolyFillRect) (pDraw, pGC, t - tmp, tmp);
+ free((pointer) tmp);
+ }
+ else
+ {
+
+ for (i=0; i<nrects; i++)
+ {
+ rect[0].x = pR->x;
+ rect[0].y = pR->y;
+
+ MAXBOUND(rect[1].x, pR->x + (int) pR->width)
+ rect[1].y = rect[0].y;
+
+ rect[2].x = rect[1].x;
+ MAXBOUND(rect[2].y, pR->y + (int) pR->height);
+
+ rect[3].x = rect[0].x;
+ rect[3].y = rect[2].y;
+
+ rect[4].x = rect[0].x;
+ rect[4].y = rect[0].y;
+
+ (*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 5, rect);
+ pR++;
+ }
+ }
+}
diff --git a/xorg-server/mi/mipolyutil.c b/xorg-server/mi/mipolyutil.c index 15561b73d..fe0d9e5bf 100644 --- a/xorg-server/mi/mipolyutil.c +++ b/xorg-server/mi/mipolyutil.c @@ -1,385 +1,385 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 "regionstr.h" -#include "gc.h" -#include "miscanfill.h" -#include "mipoly.h" -#include "misc.h" /* MAXINT */ - -/* - * fillUtils.c - * - * Written by Brian Kelleher; Oct. 1985 - * - * This module contains all of the utility functions - * needed to scan convert a polygon. - * - */ - -/* - * InsertEdgeInET - * - * Insert the given edge into the edge table. - * First we must find the correct bucket in the - * Edge table, then find the right slot in the - * bucket. Finally, we can insert it. - * - */ -static Bool -miInsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline, - ScanLineListBlock **SLLBlock, int *iSLLBlock) -{ - EdgeTableEntry *start, *prev; - ScanLineList *pSLL, *pPrevSLL; - ScanLineListBlock *tmpSLLBlock; - - /* - * find the right bucket to put the edge into - */ - pPrevSLL = &ET->scanlines; - pSLL = pPrevSLL->next; - while (pSLL && (pSLL->scanline < scanline)) - { - pPrevSLL = pSLL; - pSLL = pSLL->next; - } - - /* - * reassign pSLL (pointer to ScanLineList) if necessary - */ - if ((!pSLL) || (pSLL->scanline > scanline)) - { - if (*iSLLBlock > SLLSPERBLOCK-1) - { - tmpSLLBlock = xalloc(sizeof(ScanLineListBlock)); - if (!tmpSLLBlock) - return FALSE; - (*SLLBlock)->next = tmpSLLBlock; - tmpSLLBlock->next = NULL; - *SLLBlock = tmpSLLBlock; - *iSLLBlock = 0; - } - pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]); - - pSLL->next = pPrevSLL->next; - pSLL->edgelist = NULL; - pPrevSLL->next = pSLL; - } - pSLL->scanline = scanline; - - /* - * now insert the edge in the right bucket - */ - prev = NULL; - start = pSLL->edgelist; - while (start && (start->bres.minor < ETE->bres.minor)) - { - prev = start; - start = start->next; - } - ETE->next = start; - - if (prev) - prev->next = ETE; - else - pSLL->edgelist = ETE; - return TRUE; -} - -/* - * CreateEdgeTable - * - * This routine creates the edge table for - * scan converting polygons. - * The Edge Table (ET) looks like: - * - * EdgeTable - * -------- - * | ymax | ScanLineLists - * |scanline|-->------------>-------------->... - * -------- |scanline| |scanline| - * |edgelist| |edgelist| - * --------- --------- - * | | - * | | - * V V - * list of ETEs list of ETEs - * - * where ETE is an EdgeTableEntry data structure, - * and there is one ScanLineList per scanline at - * which an edge is initially entered. - * - */ - -Bool -miCreateETandAET(int count, DDXPointPtr pts, EdgeTable *ET, EdgeTableEntry *AET, - EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock) -{ - DDXPointPtr top, bottom; - DDXPointPtr PrevPt, CurrPt; - int iSLLBlock = 0; - - int dy; - - if (count < 2) return TRUE; - - /* - * initialize the Active Edge Table - */ - AET->next = NULL; - AET->back = NULL; - AET->nextWETE = NULL; - AET->bres.minor = MININT; - - /* - * initialize the Edge Table. - */ - ET->scanlines.next = NULL; - ET->ymax = MININT; - ET->ymin = MAXINT; - pSLLBlock->next = NULL; - - PrevPt = &pts[count-1]; - - /* - * for each vertex in the array of points. - * In this loop we are dealing with two vertices at - * a time -- these make up one edge of the polygon. - */ - while (count--) - { - CurrPt = pts++; - - /* - * find out which point is above and which is below. - */ - if (PrevPt->y > CurrPt->y) - { - bottom = PrevPt, top = CurrPt; - pETEs->ClockWise = 0; - } - else - { - bottom = CurrPt, top = PrevPt; - pETEs->ClockWise = 1; - } - - /* - * don't add horizontal edges to the Edge table. - */ - if (bottom->y != top->y) - { - pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */ - - /* - * initialize integer edge algorithm - */ - dy = bottom->y - top->y; - BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres); - - if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock)) - { - miFreeStorage(pSLLBlock->next); - return FALSE; - } - - ET->ymax = max(ET->ymax, PrevPt->y); - ET->ymin = min(ET->ymin, PrevPt->y); - pETEs++; - } - - PrevPt = CurrPt; - } - return TRUE; -} - -/* - * loadAET - * - * This routine moves EdgeTableEntries from the - * EdgeTable into the Active Edge Table, - * leaving them sorted by smaller x coordinate. - * - */ - -void -miloadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs) -{ - EdgeTableEntry *pPrevAET; - EdgeTableEntry *tmp; - - pPrevAET = AET; - AET = AET->next; - while (ETEs) - { - while (AET && (AET->bres.minor < ETEs->bres.minor)) - { - pPrevAET = AET; - AET = AET->next; - } - tmp = ETEs->next; - ETEs->next = AET; - if (AET) - AET->back = ETEs; - ETEs->back = pPrevAET; - pPrevAET->next = ETEs; - pPrevAET = ETEs; - - ETEs = tmp; - } -} - -/* - * computeWAET - * - * This routine links the AET by the - * nextWETE (winding EdgeTableEntry) link for - * use by the winding number rule. The final - * Active Edge Table (AET) might look something - * like: - * - * AET - * ---------- --------- --------- - * |ymax | |ymax | |ymax | - * | ... | |... | |... | - * |next |->|next |->|next |->... - * |nextWETE| |nextWETE| |nextWETE| - * --------- --------- ^-------- - * | | | - * V-------------------> V---> ... - * - */ -void -micomputeWAET(EdgeTableEntry *AET) -{ - EdgeTableEntry *pWETE; - int inside = 1; - int isInside = 0; - - AET->nextWETE = NULL; - pWETE = AET; - AET = AET->next; - while (AET) - { - if (AET->ClockWise) - isInside++; - else - isInside--; - - if ((!inside && !isInside) || - ( inside && isInside)) - { - pWETE->nextWETE = AET; - pWETE = AET; - inside = !inside; - } - AET = AET->next; - } - pWETE->nextWETE = NULL; -} - -/* - * InsertionSort - * - * Just a simple insertion sort using - * pointers and back pointers to sort the Active - * Edge Table. - * - */ - -int -miInsertionSort(EdgeTableEntry *AET) -{ - EdgeTableEntry *pETEchase; - EdgeTableEntry *pETEinsert; - EdgeTableEntry *pETEchaseBackTMP; - int changed = 0; - - AET = AET->next; - while (AET) - { - pETEinsert = AET; - pETEchase = AET; - while (pETEchase->back->bres.minor > AET->bres.minor) - pETEchase = pETEchase->back; - - AET = AET->next; - if (pETEchase != pETEinsert) - { - pETEchaseBackTMP = pETEchase->back; - pETEinsert->back->next = AET; - if (AET) - AET->back = pETEinsert->back; - pETEinsert->next = pETEchase; - pETEchase->back->next = pETEinsert; - pETEchase->back = pETEinsert; - pETEinsert->back = pETEchaseBackTMP; - changed = 1; - } - } - return(changed); -} - -/* - * Clean up our act. - */ -void -miFreeStorage(ScanLineListBlock *pSLLBlock) -{ - ScanLineListBlock *tmpSLLBlock; - - while (pSLLBlock) - { - tmpSLLBlock = pSLLBlock->next; - xfree(pSLLBlock); - pSLLBlock = tmpSLLBlock; - } -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 "regionstr.h"
+#include "gc.h"
+#include "miscanfill.h"
+#include "mipoly.h"
+#include "misc.h" /* MAXINT */
+
+/*
+ * fillUtils.c
+ *
+ * Written by Brian Kelleher; Oct. 1985
+ *
+ * This module contains all of the utility functions
+ * needed to scan convert a polygon.
+ *
+ */
+
+/*
+ * InsertEdgeInET
+ *
+ * Insert the given edge into the edge table.
+ * First we must find the correct bucket in the
+ * Edge table, then find the right slot in the
+ * bucket. Finally, we can insert it.
+ *
+ */
+static Bool
+miInsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline,
+ ScanLineListBlock **SLLBlock, int *iSLLBlock)
+{
+ EdgeTableEntry *start, *prev;
+ ScanLineList *pSLL, *pPrevSLL;
+ ScanLineListBlock *tmpSLLBlock;
+
+ /*
+ * find the right bucket to put the edge into
+ */
+ pPrevSLL = &ET->scanlines;
+ pSLL = pPrevSLL->next;
+ while (pSLL && (pSLL->scanline < scanline))
+ {
+ pPrevSLL = pSLL;
+ pSLL = pSLL->next;
+ }
+
+ /*
+ * reassign pSLL (pointer to ScanLineList) if necessary
+ */
+ if ((!pSLL) || (pSLL->scanline > scanline))
+ {
+ if (*iSLLBlock > SLLSPERBLOCK-1)
+ {
+ tmpSLLBlock = malloc(sizeof(ScanLineListBlock));
+ if (!tmpSLLBlock)
+ return FALSE;
+ (*SLLBlock)->next = tmpSLLBlock;
+ tmpSLLBlock->next = NULL;
+ *SLLBlock = tmpSLLBlock;
+ *iSLLBlock = 0;
+ }
+ pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
+
+ pSLL->next = pPrevSLL->next;
+ pSLL->edgelist = NULL;
+ pPrevSLL->next = pSLL;
+ }
+ pSLL->scanline = scanline;
+
+ /*
+ * now insert the edge in the right bucket
+ */
+ prev = NULL;
+ start = pSLL->edgelist;
+ while (start && (start->bres.minor < ETE->bres.minor))
+ {
+ prev = start;
+ start = start->next;
+ }
+ ETE->next = start;
+
+ if (prev)
+ prev->next = ETE;
+ else
+ pSLL->edgelist = ETE;
+ return TRUE;
+}
+
+/*
+ * CreateEdgeTable
+ *
+ * This routine creates the edge table for
+ * scan converting polygons.
+ * The Edge Table (ET) looks like:
+ *
+ * EdgeTable
+ * --------
+ * | ymax | ScanLineLists
+ * |scanline|-->------------>-------------->...
+ * -------- |scanline| |scanline|
+ * |edgelist| |edgelist|
+ * --------- ---------
+ * | |
+ * | |
+ * V V
+ * list of ETEs list of ETEs
+ *
+ * where ETE is an EdgeTableEntry data structure,
+ * and there is one ScanLineList per scanline at
+ * which an edge is initially entered.
+ *
+ */
+
+Bool
+miCreateETandAET(int count, DDXPointPtr pts, EdgeTable *ET, EdgeTableEntry *AET,
+ EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
+{
+ DDXPointPtr top, bottom;
+ DDXPointPtr PrevPt, CurrPt;
+ int iSLLBlock = 0;
+
+ int dy;
+
+ if (count < 2) return TRUE;
+
+ /*
+ * initialize the Active Edge Table
+ */
+ AET->next = NULL;
+ AET->back = NULL;
+ AET->nextWETE = NULL;
+ AET->bres.minor = MININT;
+
+ /*
+ * initialize the Edge Table.
+ */
+ ET->scanlines.next = NULL;
+ ET->ymax = MININT;
+ ET->ymin = MAXINT;
+ pSLLBlock->next = NULL;
+
+ PrevPt = &pts[count-1];
+
+ /*
+ * for each vertex in the array of points.
+ * In this loop we are dealing with two vertices at
+ * a time -- these make up one edge of the polygon.
+ */
+ while (count--)
+ {
+ CurrPt = pts++;
+
+ /*
+ * find out which point is above and which is below.
+ */
+ if (PrevPt->y > CurrPt->y)
+ {
+ bottom = PrevPt, top = CurrPt;
+ pETEs->ClockWise = 0;
+ }
+ else
+ {
+ bottom = CurrPt, top = PrevPt;
+ pETEs->ClockWise = 1;
+ }
+
+ /*
+ * don't add horizontal edges to the Edge table.
+ */
+ if (bottom->y != top->y)
+ {
+ pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */
+
+ /*
+ * initialize integer edge algorithm
+ */
+ dy = bottom->y - top->y;
+ BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
+
+ if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock))
+ {
+ miFreeStorage(pSLLBlock->next);
+ return FALSE;
+ }
+
+ ET->ymax = max(ET->ymax, PrevPt->y);
+ ET->ymin = min(ET->ymin, PrevPt->y);
+ pETEs++;
+ }
+
+ PrevPt = CurrPt;
+ }
+ return TRUE;
+}
+
+/*
+ * loadAET
+ *
+ * This routine moves EdgeTableEntries from the
+ * EdgeTable into the Active Edge Table,
+ * leaving them sorted by smaller x coordinate.
+ *
+ */
+
+void
+miloadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
+{
+ EdgeTableEntry *pPrevAET;
+ EdgeTableEntry *tmp;
+
+ pPrevAET = AET;
+ AET = AET->next;
+ while (ETEs)
+ {
+ while (AET && (AET->bres.minor < ETEs->bres.minor))
+ {
+ pPrevAET = AET;
+ AET = AET->next;
+ }
+ tmp = ETEs->next;
+ ETEs->next = AET;
+ if (AET)
+ AET->back = ETEs;
+ ETEs->back = pPrevAET;
+ pPrevAET->next = ETEs;
+ pPrevAET = ETEs;
+
+ ETEs = tmp;
+ }
+}
+
+/*
+ * computeWAET
+ *
+ * This routine links the AET by the
+ * nextWETE (winding EdgeTableEntry) link for
+ * use by the winding number rule. The final
+ * Active Edge Table (AET) might look something
+ * like:
+ *
+ * AET
+ * ---------- --------- ---------
+ * |ymax | |ymax | |ymax |
+ * | ... | |... | |... |
+ * |next |->|next |->|next |->...
+ * |nextWETE| |nextWETE| |nextWETE|
+ * --------- --------- ^--------
+ * | | |
+ * V-------------------> V---> ...
+ *
+ */
+void
+micomputeWAET(EdgeTableEntry *AET)
+{
+ EdgeTableEntry *pWETE;
+ int inside = 1;
+ int isInside = 0;
+
+ AET->nextWETE = NULL;
+ pWETE = AET;
+ AET = AET->next;
+ while (AET)
+ {
+ if (AET->ClockWise)
+ isInside++;
+ else
+ isInside--;
+
+ if ((!inside && !isInside) ||
+ ( inside && isInside))
+ {
+ pWETE->nextWETE = AET;
+ pWETE = AET;
+ inside = !inside;
+ }
+ AET = AET->next;
+ }
+ pWETE->nextWETE = NULL;
+}
+
+/*
+ * InsertionSort
+ *
+ * Just a simple insertion sort using
+ * pointers and back pointers to sort the Active
+ * Edge Table.
+ *
+ */
+
+int
+miInsertionSort(EdgeTableEntry *AET)
+{
+ EdgeTableEntry *pETEchase;
+ EdgeTableEntry *pETEinsert;
+ EdgeTableEntry *pETEchaseBackTMP;
+ int changed = 0;
+
+ AET = AET->next;
+ while (AET)
+ {
+ pETEinsert = AET;
+ pETEchase = AET;
+ while (pETEchase->back->bres.minor > AET->bres.minor)
+ pETEchase = pETEchase->back;
+
+ AET = AET->next;
+ if (pETEchase != pETEinsert)
+ {
+ pETEchaseBackTMP = pETEchase->back;
+ pETEinsert->back->next = AET;
+ if (AET)
+ AET->back = pETEinsert->back;
+ pETEinsert->next = pETEchase;
+ pETEchase->back->next = pETEinsert;
+ pETEchase->back = pETEinsert;
+ pETEinsert->back = pETEchaseBackTMP;
+ changed = 1;
+ }
+ }
+ return(changed);
+}
+
+/*
+ * Clean up our act.
+ */
+void
+miFreeStorage(ScanLineListBlock *pSLLBlock)
+{
+ ScanLineListBlock *tmpSLLBlock;
+
+ while (pSLLBlock)
+ {
+ tmpSLLBlock = pSLLBlock->next;
+ free(pSLLBlock);
+ pSLLBlock = tmpSLLBlock;
+ }
+}
diff --git a/xorg-server/mi/mipushpxl.c b/xorg-server/mi/mipushpxl.c index 3844519d8..9c3d9b342 100644 --- a/xorg-server/mi/mipushpxl.c +++ b/xorg-server/mi/mipushpxl.c @@ -1,271 +1,271 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <X11/X.h> -#include "gcstruct.h" -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "regionstr.h" -#include "mi.h" -#include "servermd.h" - -#define NPT 128 - -/* These were stolen from mfb. They don't really belong here. */ -#define LONG2CHARSSAMEORDER(x) ((MiBits)(x)) -#define LONG2CHARSDIFFORDER( x ) ( ( ( ( x ) & (MiBits)0x000000FF ) << 0x18 ) \ - | ( ( ( x ) & (MiBits)0x0000FF00 ) << 0x08 ) \ - | ( ( ( x ) & (MiBits)0x00FF0000 ) >> 0x08 ) \ - | ( ( ( x ) & (MiBits)0xFF000000 ) >> 0x18 ) ) - - -#define PGSZB 4 -#define PPW (PGSZB<<3) /* assuming 8 bits per byte */ -#define PGSZ PPW -#define PLST (PPW-1) -#define PIM PLST -#define PWSH 5 - -/* miPushPixels -- squeegees the fill style of pGC through pBitMap - * into pDrawable. pBitMap is a stencil (dx by dy of it is used, it may - * be bigger) which is placed on the drawable at xOrg, yOrg. Where a 1 bit - * is set in the bitmap, the fill style is put onto the drawable using - * the GC's logical function. The drawable is not changed where the bitmap - * has a zero bit or outside the area covered by the stencil. - -WARNING: - this code works if the 1-bit deep pixmap format returned by GetSpans -is the same as the format defined by the mfb code (i.e. 32-bit padding -per scanline, scanline unit = 32 bits; later, this might mean -bitsizeof(int) padding and sacnline unit == bitsizeof(int).) - - */ - -/* - * in order to have both (MSB_FIRST and LSB_FIRST) versions of this - * in the server, we need to rename one of them - */ -void -miPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable, - int dx, int dy, int xOrg, int yOrg) -{ - int h, dxDivPPW, ibEnd; - MiBits *pwLineStart; - MiBits *pw, *pwEnd; - MiBits msk; - int ib, w; - int ipt; /* index into above arrays */ - Bool fInBox; - DDXPointRec pt[NPT], ptThisLine; - int width[NPT]; -#if 1 - MiBits startmask; - if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER) - if (screenInfo.bitmapBitOrder == LSBFirst) - startmask = (MiBits)(-1) ^ - LONG2CHARSSAMEORDER((MiBits)(-1) << 1); - else - startmask = (MiBits)(-1) ^ - LONG2CHARSSAMEORDER((MiBits)(-1) >> 1); - else - if (screenInfo.bitmapBitOrder == LSBFirst) - startmask = (MiBits)(-1) ^ - LONG2CHARSDIFFORDER((MiBits)(-1) << 1); - else - startmask = (MiBits)(-1) ^ - LONG2CHARSDIFFORDER((MiBits)(-1) >> 1); -#endif - - pwLineStart = xalloc(BitmapBytePad(dx)); - if (!pwLineStart) - return; - ipt = 0; - dxDivPPW = dx/PPW; - - for(h = 0, ptThisLine.x = 0, ptThisLine.y = 0; - h < dy; - h++, ptThisLine.y++) - { - - (*pBitMap->drawable.pScreen->GetSpans)((DrawablePtr)pBitMap, dx, - &ptThisLine, &dx, 1, (char *)pwLineStart); - - pw = pwLineStart; - /* Process all words which are fully in the pixmap */ - - fInBox = FALSE; - pwEnd = pwLineStart + dxDivPPW; - while(pw < pwEnd) - { - w = *pw; -#if 1 - msk = startmask; -#else - msk = (MiBits)(-1) ^ SCRRIGHT((MiBits)(-1), 1); -#endif - for(ib = 0; ib < PPW; ib++) - { - if(w & msk) - { - if(!fInBox) - { - pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg; - pt[ipt].y = h + yOrg; - /* start new box */ - fInBox = TRUE; - } - } - else - { - if(fInBox) - { - width[ipt] = ((pw - pwLineStart) << PWSH) + - ib + xOrg - pt[ipt].x; - if (++ipt >= NPT) - { - (*pGC->ops->FillSpans)(pDrawable, pGC, - NPT, pt, width, TRUE); - ipt = 0; - } - /* end box */ - fInBox = FALSE; - } - } -#if 1 - /* This is not quite right, but it'll do for now */ - if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER) - if (screenInfo.bitmapBitOrder == LSBFirst) - msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1); - else - msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1); - else - if (screenInfo.bitmapBitOrder == LSBFirst) - msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1); - else - msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1); -#else - msk = SCRRIGHT(msk, 1); -#endif - } - pw++; - } - ibEnd = dx & PIM; - if(ibEnd) - { - /* Process final partial word on line */ - w = *pw; -#if 1 - msk = startmask; -#else - msk = (MiBits)(-1) ^ SCRRIGHT((MiBits)(-1), 1); -#endif - for(ib = 0; ib < ibEnd; ib++) - { - if(w & msk) - { - if(!fInBox) - { - /* start new box */ - pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg; - pt[ipt].y = h + yOrg; - fInBox = TRUE; - } - } - else - { - if(fInBox) - { - /* end box */ - width[ipt] = ((pw - pwLineStart) << PWSH) + - ib + xOrg - pt[ipt].x; - if (++ipt >= NPT) - { - (*pGC->ops->FillSpans)(pDrawable, - pGC, NPT, pt, width, TRUE); - ipt = 0; - } - fInBox = FALSE; - } - } -#if 1 - /* This is not quite right, but it'll do for now */ - if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER) - if (screenInfo.bitmapBitOrder == LSBFirst) - msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1); - else - msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1); - else - if (screenInfo.bitmapBitOrder == LSBFirst) - msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1); - else - msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1); -#else - msk = SCRRIGHT(msk, 1); -#endif - } - } - /* If scanline ended with last bit set, end the box */ - if(fInBox) - { - width[ipt] = dx + xOrg - pt[ipt].x; - if (++ipt >= NPT) - { - (*pGC->ops->FillSpans)(pDrawable, pGC, NPT, pt, width, TRUE); - ipt = 0; - } - } - } - xfree(pwLineStart); - /* Flush any remaining spans */ - if (ipt) - { - (*pGC->ops->FillSpans)(pDrawable, pGC, ipt, pt, width, TRUE); - } -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <X11/X.h>
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "regionstr.h"
+#include "mi.h"
+#include "servermd.h"
+
+#define NPT 128
+
+/* These were stolen from mfb. They don't really belong here. */
+#define LONG2CHARSSAMEORDER(x) ((MiBits)(x))
+#define LONG2CHARSDIFFORDER( x ) ( ( ( ( x ) & (MiBits)0x000000FF ) << 0x18 ) \
+ | ( ( ( x ) & (MiBits)0x0000FF00 ) << 0x08 ) \
+ | ( ( ( x ) & (MiBits)0x00FF0000 ) >> 0x08 ) \
+ | ( ( ( x ) & (MiBits)0xFF000000 ) >> 0x18 ) )
+
+
+#define PGSZB 4
+#define PPW (PGSZB<<3) /* assuming 8 bits per byte */
+#define PGSZ PPW
+#define PLST (PPW-1)
+#define PIM PLST
+#define PWSH 5
+
+/* miPushPixels -- squeegees the fill style of pGC through pBitMap
+ * into pDrawable. pBitMap is a stencil (dx by dy of it is used, it may
+ * be bigger) which is placed on the drawable at xOrg, yOrg. Where a 1 bit
+ * is set in the bitmap, the fill style is put onto the drawable using
+ * the GC's logical function. The drawable is not changed where the bitmap
+ * has a zero bit or outside the area covered by the stencil.
+
+WARNING:
+ this code works if the 1-bit deep pixmap format returned by GetSpans
+is the same as the format defined by the mfb code (i.e. 32-bit padding
+per scanline, scanline unit = 32 bits; later, this might mean
+bitsizeof(int) padding and sacnline unit == bitsizeof(int).)
+
+ */
+
+/*
+ * in order to have both (MSB_FIRST and LSB_FIRST) versions of this
+ * in the server, we need to rename one of them
+ */
+void
+miPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable,
+ int dx, int dy, int xOrg, int yOrg)
+{
+ int h, dxDivPPW, ibEnd;
+ MiBits *pwLineStart;
+ MiBits *pw, *pwEnd;
+ MiBits msk;
+ int ib, w;
+ int ipt; /* index into above arrays */
+ Bool fInBox;
+ DDXPointRec pt[NPT], ptThisLine;
+ int width[NPT];
+#if 1
+ MiBits startmask;
+ if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
+ if (screenInfo.bitmapBitOrder == LSBFirst)
+ startmask = (MiBits)(-1) ^
+ LONG2CHARSSAMEORDER((MiBits)(-1) << 1);
+ else
+ startmask = (MiBits)(-1) ^
+ LONG2CHARSSAMEORDER((MiBits)(-1) >> 1);
+ else
+ if (screenInfo.bitmapBitOrder == LSBFirst)
+ startmask = (MiBits)(-1) ^
+ LONG2CHARSDIFFORDER((MiBits)(-1) << 1);
+ else
+ startmask = (MiBits)(-1) ^
+ LONG2CHARSDIFFORDER((MiBits)(-1) >> 1);
+#endif
+
+ pwLineStart = malloc(BitmapBytePad(dx));
+ if (!pwLineStart)
+ return;
+ ipt = 0;
+ dxDivPPW = dx/PPW;
+
+ for(h = 0, ptThisLine.x = 0, ptThisLine.y = 0;
+ h < dy;
+ h++, ptThisLine.y++)
+ {
+
+ (*pBitMap->drawable.pScreen->GetSpans)((DrawablePtr)pBitMap, dx,
+ &ptThisLine, &dx, 1, (char *)pwLineStart);
+
+ pw = pwLineStart;
+ /* Process all words which are fully in the pixmap */
+
+ fInBox = FALSE;
+ pwEnd = pwLineStart + dxDivPPW;
+ while(pw < pwEnd)
+ {
+ w = *pw;
+#if 1
+ msk = startmask;
+#else
+ msk = (MiBits)(-1) ^ SCRRIGHT((MiBits)(-1), 1);
+#endif
+ for(ib = 0; ib < PPW; ib++)
+ {
+ if(w & msk)
+ {
+ if(!fInBox)
+ {
+ pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg;
+ pt[ipt].y = h + yOrg;
+ /* start new box */
+ fInBox = TRUE;
+ }
+ }
+ else
+ {
+ if(fInBox)
+ {
+ width[ipt] = ((pw - pwLineStart) << PWSH) +
+ ib + xOrg - pt[ipt].x;
+ if (++ipt >= NPT)
+ {
+ (*pGC->ops->FillSpans)(pDrawable, pGC,
+ NPT, pt, width, TRUE);
+ ipt = 0;
+ }
+ /* end box */
+ fInBox = FALSE;
+ }
+ }
+#if 1
+ /* This is not quite right, but it'll do for now */
+ if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
+ if (screenInfo.bitmapBitOrder == LSBFirst)
+ msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1);
+ else
+ msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1);
+ else
+ if (screenInfo.bitmapBitOrder == LSBFirst)
+ msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1);
+ else
+ msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1);
+#else
+ msk = SCRRIGHT(msk, 1);
+#endif
+ }
+ pw++;
+ }
+ ibEnd = dx & PIM;
+ if(ibEnd)
+ {
+ /* Process final partial word on line */
+ w = *pw;
+#if 1
+ msk = startmask;
+#else
+ msk = (MiBits)(-1) ^ SCRRIGHT((MiBits)(-1), 1);
+#endif
+ for(ib = 0; ib < ibEnd; ib++)
+ {
+ if(w & msk)
+ {
+ if(!fInBox)
+ {
+ /* start new box */
+ pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg;
+ pt[ipt].y = h + yOrg;
+ fInBox = TRUE;
+ }
+ }
+ else
+ {
+ if(fInBox)
+ {
+ /* end box */
+ width[ipt] = ((pw - pwLineStart) << PWSH) +
+ ib + xOrg - pt[ipt].x;
+ if (++ipt >= NPT)
+ {
+ (*pGC->ops->FillSpans)(pDrawable,
+ pGC, NPT, pt, width, TRUE);
+ ipt = 0;
+ }
+ fInBox = FALSE;
+ }
+ }
+#if 1
+ /* This is not quite right, but it'll do for now */
+ if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
+ if (screenInfo.bitmapBitOrder == LSBFirst)
+ msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1);
+ else
+ msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1);
+ else
+ if (screenInfo.bitmapBitOrder == LSBFirst)
+ msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1);
+ else
+ msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1);
+#else
+ msk = SCRRIGHT(msk, 1);
+#endif
+ }
+ }
+ /* If scanline ended with last bit set, end the box */
+ if(fInBox)
+ {
+ width[ipt] = dx + xOrg - pt[ipt].x;
+ if (++ipt >= NPT)
+ {
+ (*pGC->ops->FillSpans)(pDrawable, pGC, NPT, pt, width, TRUE);
+ ipt = 0;
+ }
+ }
+ }
+ free(pwLineStart);
+ /* Flush any remaining spans */
+ if (ipt)
+ {
+ (*pGC->ops->FillSpans)(pDrawable, pGC, ipt, pt, width, TRUE);
+ }
+}
diff --git a/xorg-server/mi/miregion.c b/xorg-server/mi/miregion.c index c48befc6f..ff58c0372 100644 --- a/xorg-server/mi/miregion.c +++ b/xorg-server/mi/miregion.c @@ -1,1845 +1,1845 @@ -/*********************************************************** - -Copyright 1987, 1988, 1989, 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. - - -Copyright 1987, 1988, 1989 by -Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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. - -******************************************************************/ - -/* The panoramix components contained the following notice */ -/***************************************************************** - -Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software. - -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 -DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, -BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation -shall not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization from Digital -Equipment Corporation. - -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "regionstr.h" -#include <X11/Xprotostr.h> -#include <X11/Xfuncproto.h> -#include "gc.h" -#include "mi.h" -#include "mispans.h" -#include <pixman.h> - -#undef assert -#ifdef REGION_DEBUG -#define assert(expr) { \ - CARD32 *foo = NULL; \ - if (!(expr)) { \ - ErrorF("Assertion failed file %s, line %d: %s\n", \ - __FILE__, __LINE__, #expr); \ - *foo = 0xdeadbeef; /* to get a backtrace */ \ - } \ - } -#else -#define assert(expr) -#endif - -#define good(reg) assert(miValidRegion(reg)) - -/* - * The functions in this file implement the Region abstraction used extensively - * throughout the X11 sample server. A Region is simply a set of disjoint - * (non-overlapping) rectangles, plus an "extent" rectangle which is the - * smallest single rectangle that contains all the non-overlapping rectangles. - * - * A Region is implemented as a "y-x-banded" array of rectangles. This array - * imposes two degrees of order. First, all rectangles are sorted by top side - * y coordinate first (y1), and then by left side x coordinate (x1). - * - * Furthermore, the rectangles are grouped into "bands". Each rectangle in a - * band has the same top y coordinate (y1), and each has the same bottom y - * coordinate (y2). Thus all rectangles in a band differ only in their left - * and right side (x1 and x2). Bands are implicit in the array of rectangles: - * there is no separate list of band start pointers. - * - * The y-x band representation does not minimize rectangles. In particular, - * if a rectangle vertically crosses a band (the rectangle has scanlines in - * the y1 to y2 area spanned by the band), then the rectangle may be broken - * down into two or more smaller rectangles stacked one atop the other. - * - * ----------- ----------- - * | | | | band 0 - * | | -------- ----------- -------- - * | | | | in y-x banded | | | | band 1 - * | | | | form is | | | | - * ----------- | | ----------- -------- - * | | | | band 2 - * -------- -------- - * - * An added constraint on the rectangles is that they must cover as much - * horizontal area as possible: no two rectangles within a band are allowed - * to touch. - * - * Whenever possible, bands will be merged together to cover a greater vertical - * distance (and thus reduce the number of rectangles). Two bands can be merged - * only if the bottom of one touches the top of the other and they have - * rectangles in the same places (of the same width, of course). - * - * Adam de Boor wrote most of the original region code. Joel McCormack - * substantially modified or rewrote most of the core arithmetic routines, - * and added miRegionValidate in order to support several speed improvements - * to miValidateTree. Bob Scheifler changed the representation to be more - * compact when empty or a single rectangle, and did a bunch of gratuitous - * reformatting. - */ - -/* true iff two Boxes overlap */ -#define EXTENTCHECK(r1,r2) \ - (!( ((r1)->x2 <= (r2)->x1) || \ - ((r1)->x1 >= (r2)->x2) || \ - ((r1)->y2 <= (r2)->y1) || \ - ((r1)->y1 >= (r2)->y2) ) ) - -/* true iff (x,y) is in Box */ -#define INBOX(r,x,y) \ - ( ((r)->x2 > x) && \ - ((r)->x1 <= x) && \ - ((r)->y2 > y) && \ - ((r)->y1 <= y) ) - -/* true iff Box r1 contains Box r2 */ -#define SUBSUMES(r1,r2) \ - ( ((r1)->x1 <= (r2)->x1) && \ - ((r1)->x2 >= (r2)->x2) && \ - ((r1)->y1 <= (r2)->y1) && \ - ((r1)->y2 >= (r2)->y2) ) - -#define xallocData(n) xalloc(REGION_SZOF(n)) -#define xfreeData(reg) if ((reg)->data && (reg)->data->size) xfree((reg)->data) - -#define RECTALLOC_BAIL(pReg,n,bail) \ -if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ - if (!miRectAlloc(pReg, n)) { goto bail; } - -#define RECTALLOC(pReg,n) \ -if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ - if (!miRectAlloc(pReg, n)) { return FALSE; } - -#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \ -{ \ - pNextRect->x1 = nx1; \ - pNextRect->y1 = ny1; \ - pNextRect->x2 = nx2; \ - pNextRect->y2 = ny2; \ - pNextRect++; \ -} - -#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \ -{ \ - if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\ - { \ - if (!miRectAlloc(pReg, 1)) \ - return FALSE; \ - pNextRect = REGION_TOP(pReg); \ - } \ - ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \ - pReg->data->numRects++; \ - assert(pReg->data->numRects<=pReg->data->size); \ -} - - -#define DOWNSIZE(reg,numRects) \ -if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ -{ \ - RegDataPtr NewData; \ - NewData = (RegDataPtr)xrealloc((reg)->data, REGION_SZOF(numRects)); \ - if (NewData) \ - { \ - NewData->size = (numRects); \ - (reg)->data = NewData; \ - } \ -} - - -BoxRec miEmptyBox = {0, 0, 0, 0}; -RegDataRec miEmptyData = {0, 0}; - -RegDataRec miBrokenData = {0, 0}; -static RegionRec miBrokenRegion = { { 0, 0, 0, 0 }, &miBrokenData }; - -void -InitRegions (void) -{ - pixman_region_set_static_pointers (&miEmptyBox, &miEmptyData, &miBrokenData); -} - -/***************************************************************** - * RegionCreate(rect, size) - * This routine does a simple malloc to make a structure of - * REGION of "size" number of rectangles. - *****************************************************************/ - -RegionPtr -miRegionCreate(BoxPtr rect, int size) -{ - RegionPtr pReg; - - pReg = (RegionPtr)xalloc(sizeof(RegionRec)); - if (!pReg) - return &miBrokenRegion; - - miRegionInit (pReg, rect, size); - - return(pReg); -} - -void -miRegionDestroy(RegionPtr pReg) -{ - pixman_region_fini (pReg); - if (pReg != &miBrokenRegion) - xfree(pReg); -} - -void -miPrintRegion(RegionPtr rgn) -{ - int num, size; - int i; - BoxPtr rects; - - num = REGION_NUM_RECTS(rgn); - size = REGION_SIZE(rgn); - rects = REGION_RECTS(rgn); - ErrorF("[mi] num: %d size: %d\n", num, size); - ErrorF("[mi] extents: %d %d %d %d\n", - rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2); - for (i = 0; i < num; i++) - ErrorF("[mi] %d %d %d %d \n", - rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); - ErrorF("[mi] \n"); -} - -Bool -miRegionEqual(RegionPtr reg1, RegionPtr reg2) -{ - return pixman_region_equal (reg1, reg2); -} - -#ifdef DEBUG -Bool -miValidRegion(RegionPtr reg) -{ - int i, numRects; - - if ((reg->extents.x1 > reg->extents.x2) || - (reg->extents.y1 > reg->extents.y2)) - return FALSE; - numRects = REGION_NUM_RECTS(reg); - if (!numRects) - return ((reg->extents.x1 == reg->extents.x2) && - (reg->extents.y1 == reg->extents.y2) && - (reg->data->size || (reg->data == &miEmptyData))); - else if (numRects == 1) - return (!reg->data); - else - { - BoxPtr pboxP, pboxN; - BoxRec box; - - pboxP = REGION_RECTS(reg); - box = *pboxP; - box.y2 = pboxP[numRects-1].y2; - pboxN = pboxP + 1; - for (i = numRects; --i > 0; pboxP++, pboxN++) - { - if ((pboxN->x1 >= pboxN->x2) || - (pboxN->y1 >= pboxN->y2)) - return FALSE; - if (pboxN->x1 < box.x1) - box.x1 = pboxN->x1; - if (pboxN->x2 > box.x2) - box.x2 = pboxN->x2; - if ((pboxN->y1 < pboxP->y1) || - ((pboxN->y1 == pboxP->y1) && - ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2)))) - return FALSE; - } - return ((box.x1 == reg->extents.x1) && - (box.x2 == reg->extents.x2) && - (box.y1 == reg->extents.y1) && - (box.y2 == reg->extents.y2)); - } -} -#endif /* DEBUG */ - -/***************************************************************** - * RegionInit(pReg, rect, size) - * Outer region rect is statically allocated. - *****************************************************************/ - -void -miRegionInit(RegionPtr pReg, BoxPtr rect, int size) -{ - if (rect) - pixman_region_init_with_extents (pReg, rect); - else - pixman_region_init (pReg); -} - -void -miRegionUninit(RegionPtr pReg) -{ - pixman_region_fini (pReg); -} - -Bool -miRegionBreak (RegionPtr pReg) -{ - xfreeData (pReg); - pReg->extents = miEmptyBox; - pReg->data = &miBrokenData; - return FALSE; -} - -Bool -miRectAlloc(RegionPtr pRgn, int n) -{ - RegDataPtr data; - - if (!pRgn->data) - { - n++; - pRgn->data = xallocData(n); - if (!pRgn->data) - return miRegionBreak (pRgn); - pRgn->data->numRects = 1; - *REGION_BOXPTR(pRgn) = pRgn->extents; - } - else if (!pRgn->data->size) - { - pRgn->data = xallocData(n); - if (!pRgn->data) - return miRegionBreak (pRgn); - pRgn->data->numRects = 0; - } - else - { - if (n == 1) - { - n = pRgn->data->numRects; - if (n > 500) /* XXX pick numbers out of a hat */ - n = 250; - } - n += pRgn->data->numRects; - data = (RegDataPtr)xrealloc(pRgn->data, REGION_SZOF(n)); - if (!data) - return miRegionBreak (pRgn); - pRgn->data = data; - } - pRgn->data->size = n; - return TRUE; -} - -Bool -miRegionCopy(RegionPtr dst, RegionPtr src) -{ - return pixman_region_copy (dst, src); -} - -/*====================================================================== - * Generic Region Operator - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miCoalesce -- - * Attempt to merge the boxes in the current band with those in the - * previous one. We are guaranteed that the current band extends to - * the end of the rects array. Used only by miRegionOp. - * - * Results: - * The new index for the previous band. - * - * Side Effects: - * If coalescing takes place: - * - rectangles in the previous band will have their y2 fields - * altered. - * - pReg->data->numRects will be decreased. - * - *----------------------------------------------------------------------- - */ -_X_INLINE static int -miCoalesce ( - RegionPtr pReg, /* Region to coalesce */ - int prevStart, /* Index of start of previous band */ - int curStart) /* Index of start of current band */ -{ - BoxPtr pPrevBox; /* Current box in previous band */ - BoxPtr pCurBox; /* Current box in current band */ - int numRects; /* Number rectangles in both bands */ - int y2; /* Bottom of current band */ - /* - * Figure out how many rectangles are in the band. - */ - numRects = curStart - prevStart; - assert(numRects == pReg->data->numRects - curStart); - - if (!numRects) return curStart; - - /* - * The bands may only be coalesced if the bottom of the previous - * matches the top scanline of the current. - */ - pPrevBox = REGION_BOX(pReg, prevStart); - pCurBox = REGION_BOX(pReg, curStart); - if (pPrevBox->y2 != pCurBox->y1) return curStart; - - /* - * Make sure the bands have boxes in the same places. This - * assumes that boxes have been added in such a way that they - * cover the most area possible. I.e. two boxes in a band must - * have some horizontal space between them. - */ - y2 = pCurBox->y2; - - do { - if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) { - return (curStart); - } - pPrevBox++; - pCurBox++; - numRects--; - } while (numRects); - - /* - * The bands may be merged, so set the bottom y of each box - * in the previous band to the bottom y of the current band. - */ - numRects = curStart - prevStart; - pReg->data->numRects -= numRects; - do { - pPrevBox--; - pPrevBox->y2 = y2; - numRects--; - } while (numRects); - return prevStart; -} - - -/* Quicky macro to avoid trivial reject procedure calls to miCoalesce */ - -#define Coalesce(newReg, prevBand, curBand) \ - if (curBand - prevBand == newReg->data->numRects - curBand) { \ - prevBand = miCoalesce(newReg, prevBand, curBand); \ - } else { \ - prevBand = curBand; \ - } - -/*- - *----------------------------------------------------------------------- - * miAppendNonO -- - * Handle a non-overlapping band for the union and subtract operations. - * Just adds the (top/bottom-clipped) rectangles into the region. - * Doesn't have to check for subsumption or anything. - * - * Results: - * None. - * - * Side Effects: - * pReg->data->numRects is incremented and the rectangles overwritten - * with the rectangles we're passed. - * - *----------------------------------------------------------------------- - */ - -_X_INLINE static Bool -miAppendNonO ( - RegionPtr pReg, - BoxPtr r, - BoxPtr rEnd, - int y1, - int y2) -{ - BoxPtr pNextRect; - int newRects; - - newRects = rEnd - r; - - assert(y1 < y2); - assert(newRects != 0); - - /* Make sure we have enough space for all rectangles to be added */ - RECTALLOC(pReg, newRects); - pNextRect = REGION_TOP(pReg); - pReg->data->numRects += newRects; - do { - assert(r->x1 < r->x2); - ADDRECT(pNextRect, r->x1, y1, r->x2, y2); - r++; - } while (r != rEnd); - - return TRUE; -} - -#define FindBand(r, rBandEnd, rEnd, ry1) \ -{ \ - ry1 = r->y1; \ - rBandEnd = r+1; \ - while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \ - rBandEnd++; \ - } \ -} - -#define AppendRegions(newReg, r, rEnd) \ -{ \ - int newRects; \ - if ((newRects = rEnd - r)) { \ - RECTALLOC(newReg, newRects); \ - memmove((char *)REGION_TOP(newReg),(char *)r, \ - newRects * sizeof(BoxRec)); \ - newReg->data->numRects += newRects; \ - } \ -} - -/*- - *----------------------------------------------------------------------- - * miRegionOp -- - * Apply an operation to two regions. Called by miUnion, miInverse, - * miSubtract, miIntersect.... Both regions MUST have at least one - * rectangle, and cannot be the same object. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * The new region is overwritten. - * pOverlap set to TRUE if overlapFunc ever returns TRUE. - * - * Notes: - * The idea behind this function is to view the two regions as sets. - * Together they cover a rectangle of area that this function divides - * into horizontal bands where points are covered only by one region - * or by both. For the first case, the nonOverlapFunc is called with - * each the band and the band's upper and lower extents. For the - * second, the overlapFunc is called to process the entire band. It - * is responsible for clipping the rectangles in the band, though - * this function provides the boundaries. - * At the end of each band, the new region is coalesced, if possible, - * to reduce the number of rectangles in the region. - * - *----------------------------------------------------------------------- - */ - -typedef Bool (*OverlapProcPtr)( - RegionPtr pReg, - BoxPtr r1, - BoxPtr r1End, - BoxPtr r2, - BoxPtr r2End, - short y1, - short y2, - Bool *pOverlap); - -static Bool -miRegionOp( - RegionPtr newReg, /* Place to store result */ - RegionPtr reg1, /* First region in operation */ - RegionPtr reg2, /* 2d region in operation */ - OverlapProcPtr overlapFunc, /* Function to call for over- - * lapping bands */ - Bool appendNon1, /* Append non-overlapping bands */ - /* in region 1 ? */ - Bool appendNon2, /* Append non-overlapping bands */ - /* in region 2 ? */ - Bool *pOverlap) -{ - BoxPtr r1; /* Pointer into first region */ - BoxPtr r2; /* Pointer into 2d region */ - BoxPtr r1End; /* End of 1st region */ - BoxPtr r2End; /* End of 2d region */ - short ybot; /* Bottom of intersection */ - short ytop; /* Top of intersection */ - RegDataPtr oldData; /* Old data for newReg */ - int prevBand; /* Index of start of - * previous band in newReg */ - int curBand; /* Index of start of current - * band in newReg */ - BoxPtr r1BandEnd; /* End of current band in r1 */ - BoxPtr r2BandEnd; /* End of current band in r2 */ - short top; /* Top of non-overlapping band */ - short bot; /* Bottom of non-overlapping band*/ - int r1y1; /* Temps for r1->y1 and r2->y1 */ - int r2y1; - int newSize; - int numRects; - - /* - * Break any region computed from a broken region - */ - if (REGION_NAR (reg1) || REGION_NAR(reg2)) - return miRegionBreak (newReg); - - /* - * Initialization: - * set r1, r2, r1End and r2End appropriately, save the rectangles - * of the destination region until the end in case it's one of - * the two source regions, then mark the "new" region empty, allocating - * another array of rectangles for it to use. - */ - - r1 = REGION_RECTS(reg1); - newSize = REGION_NUM_RECTS(reg1); - r1End = r1 + newSize; - numRects = REGION_NUM_RECTS(reg2); - r2 = REGION_RECTS(reg2); - r2End = r2 + numRects; - assert(r1 != r1End); - assert(r2 != r2End); - - oldData = NULL; - if (((newReg == reg1) && (newSize > 1)) || - ((newReg == reg2) && (numRects > 1))) - { - oldData = newReg->data; - newReg->data = &miEmptyData; - } - /* guess at new size */ - if (numRects > newSize) - newSize = numRects; - newSize <<= 1; - if (!newReg->data) - newReg->data = &miEmptyData; - else if (newReg->data->size) - newReg->data->numRects = 0; - if (newSize > newReg->data->size) - if (!miRectAlloc(newReg, newSize)) - return FALSE; - - /* - * Initialize ybot. - * In the upcoming loop, ybot and ytop serve different functions depending - * on whether the band being handled is an overlapping or non-overlapping - * band. - * In the case of a non-overlapping band (only one of the regions - * has points in the band), ybot is the bottom of the most recent - * intersection and thus clips the top of the rectangles in that band. - * ytop is the top of the next intersection between the two regions and - * serves to clip the bottom of the rectangles in the current band. - * For an overlapping band (where the two regions intersect), ytop clips - * the top of the rectangles of both regions and ybot clips the bottoms. - */ - - ybot = min(r1->y1, r2->y1); - - /* - * prevBand serves to mark the start of the previous band so rectangles - * can be coalesced into larger rectangles. qv. miCoalesce, above. - * In the beginning, there is no previous band, so prevBand == curBand - * (curBand is set later on, of course, but the first band will always - * start at index 0). prevBand and curBand must be indices because of - * the possible expansion, and resultant moving, of the new region's - * array of rectangles. - */ - prevBand = 0; - - do { - /* - * This algorithm proceeds one source-band (as opposed to a - * destination band, which is determined by where the two regions - * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the - * rectangle after the last one in the current band for their - * respective regions. - */ - assert(r1 != r1End); - assert(r2 != r2End); - - FindBand(r1, r1BandEnd, r1End, r1y1); - FindBand(r2, r2BandEnd, r2End, r2y1); - - /* - * First handle the band that doesn't intersect, if any. - * - * Note that attention is restricted to one band in the - * non-intersecting region at once, so if a region has n - * bands between the current position and the next place it overlaps - * the other, this entire loop will be passed through n times. - */ - if (r1y1 < r2y1) { - if (appendNon1) { - top = max(r1y1, ybot); - bot = min(r1->y2, r2y1); - if (top != bot) { - curBand = newReg->data->numRects; - miAppendNonO(newReg, r1, r1BandEnd, top, bot); - Coalesce(newReg, prevBand, curBand); - } - } - ytop = r2y1; - } else if (r2y1 < r1y1) { - if (appendNon2) { - top = max(r2y1, ybot); - bot = min(r2->y2, r1y1); - if (top != bot) { - curBand = newReg->data->numRects; - miAppendNonO(newReg, r2, r2BandEnd, top, bot); - Coalesce(newReg, prevBand, curBand); - } - } - ytop = r1y1; - } else { - ytop = r1y1; - } - - /* - * Now see if we've hit an intersecting band. The two bands only - * intersect if ybot > ytop - */ - ybot = min(r1->y2, r2->y2); - if (ybot > ytop) { - curBand = newReg->data->numRects; - (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot, - pOverlap); - Coalesce(newReg, prevBand, curBand); - } - - /* - * If we've finished with a band (y2 == ybot) we skip forward - * in the region to the next band. - */ - if (r1->y2 == ybot) r1 = r1BandEnd; - if (r2->y2 == ybot) r2 = r2BandEnd; - - } while (r1 != r1End && r2 != r2End); - - /* - * Deal with whichever region (if any) still has rectangles left. - * - * We only need to worry about banding and coalescing for the very first - * band left. After that, we can just group all remaining boxes, - * regardless of how many bands, into one final append to the list. - */ - - if ((r1 != r1End) && appendNon1) { - /* Do first nonOverlap1Func call, which may be able to coalesce */ - FindBand(r1, r1BandEnd, r1End, r1y1); - curBand = newReg->data->numRects; - miAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2); - Coalesce(newReg, prevBand, curBand); - /* Just append the rest of the boxes */ - AppendRegions(newReg, r1BandEnd, r1End); - - } else if ((r2 != r2End) && appendNon2) { - /* Do first nonOverlap2Func call, which may be able to coalesce */ - FindBand(r2, r2BandEnd, r2End, r2y1); - curBand = newReg->data->numRects; - miAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2); - Coalesce(newReg, prevBand, curBand); - /* Append rest of boxes */ - AppendRegions(newReg, r2BandEnd, r2End); - } - - if (oldData) - xfree(oldData); - - if (!(numRects = newReg->data->numRects)) - { - xfreeData(newReg); - newReg->data = &miEmptyData; - } - else if (numRects == 1) - { - newReg->extents = *REGION_BOXPTR(newReg); - xfreeData(newReg); - newReg->data = NULL; - } - else - { - DOWNSIZE(newReg, numRects); - } - - return TRUE; -} - -/*- - *----------------------------------------------------------------------- - * miSetExtents -- - * Reset the extents of a region to what they should be. Called by - * miSubtract and miIntersect as they can't figure it out along the - * way or do so easily, as miUnion can. - * - * Results: - * None. - * - * Side Effects: - * The region's 'extents' structure is overwritten. - * - *----------------------------------------------------------------------- - */ -static void -miSetExtents (RegionPtr pReg) -{ - BoxPtr pBox, pBoxEnd; - - if (!pReg->data) - return; - if (!pReg->data->size) - { - pReg->extents.x2 = pReg->extents.x1; - pReg->extents.y2 = pReg->extents.y1; - return; - } - - pBox = REGION_BOXPTR(pReg); - pBoxEnd = REGION_END(pReg); - - /* - * Since pBox is the first rectangle in the region, it must have the - * smallest y1 and since pBoxEnd is the last rectangle in the region, - * it must have the largest y2, because of banding. Initialize x1 and - * x2 from pBox and pBoxEnd, resp., as good things to initialize them - * to... - */ - pReg->extents.x1 = pBox->x1; - pReg->extents.y1 = pBox->y1; - pReg->extents.x2 = pBoxEnd->x2; - pReg->extents.y2 = pBoxEnd->y2; - - assert(pReg->extents.y1 < pReg->extents.y2); - while (pBox <= pBoxEnd) { - if (pBox->x1 < pReg->extents.x1) - pReg->extents.x1 = pBox->x1; - if (pBox->x2 > pReg->extents.x2) - pReg->extents.x2 = pBox->x2; - pBox++; - }; - - assert(pReg->extents.x1 < pReg->extents.x2); -} - -/*====================================================================== - * Region Intersection - *====================================================================*/ -/*- - *----------------------------------------------------------------------- - * miIntersectO -- - * Handle an overlapping band for miIntersect. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * Rectangles may be added to the region. - * - *----------------------------------------------------------------------- - */ -/*ARGSUSED*/ -Bool -miIntersect( - RegionPtr newReg, /* destination Region */ - RegionPtr reg1, - RegionPtr reg2 /* source regions */ - ) -{ - return pixman_region_intersect (newReg, reg1, reg2); -} - -#define MERGERECT(r) \ -{ \ - if (r->x1 <= x2) { \ - /* Merge with current rectangle */ \ - if (r->x1 < x2) *pOverlap = TRUE; \ - if (x2 < r->x2) x2 = r->x2; \ - } else { \ - /* Add current rectangle, start new one */ \ - NEWRECT(pReg, pNextRect, x1, y1, x2, y2); \ - x1 = r->x1; \ - x2 = r->x2; \ - } \ - r++; \ -} - -/*====================================================================== - * Region Union - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miUnionO -- - * Handle an overlapping band for the union operation. Picks the - * left-most rectangle each time and merges it into the region. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * pReg is overwritten. - * pOverlap is set to TRUE if any boxes overlap. - * - *----------------------------------------------------------------------- - */ -static Bool -miUnionO ( - RegionPtr pReg, - BoxPtr r1, - BoxPtr r1End, - BoxPtr r2, - BoxPtr r2End, - short y1, - short y2, - Bool *pOverlap) -{ - BoxPtr pNextRect; - int x1; /* left and right side of current union */ - int x2; - - assert (y1 < y2); - assert(r1 != r1End && r2 != r2End); - - pNextRect = REGION_TOP(pReg); - - /* Start off current rectangle */ - if (r1->x1 < r2->x1) - { - x1 = r1->x1; - x2 = r1->x2; - r1++; - } - else - { - x1 = r2->x1; - x2 = r2->x2; - r2++; - } - while (r1 != r1End && r2 != r2End) - { - if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2); - } - - /* Finish off whoever (if any) is left */ - if (r1 != r1End) - { - do - { - MERGERECT(r1); - } while (r1 != r1End); - } - else if (r2 != r2End) - { - do - { - MERGERECT(r2); - } while (r2 != r2End); - } - - /* Add current rectangle */ - NEWRECT(pReg, pNextRect, x1, y1, x2, y2); - - return TRUE; -} - -Bool -miUnion( - RegionPtr newReg, /* destination Region */ - RegionPtr reg1, - RegionPtr reg2 /* source regions */ - ) -{ - return pixman_region_union (newReg, reg1, reg2); -} - -/*====================================================================== - * Batch Rectangle Union - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miRegionAppend -- - * - * "Append" the rgn rectangles onto the end of dstrgn, maintaining - * knowledge of YX-banding when it's easy. Otherwise, dstrgn just - * becomes a non-y-x-banded random collection of rectangles, and not - * yet a true region. After a sequence of appends, the caller must - * call miRegionValidate to ensure that a valid region is constructed. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * dstrgn is modified if rgn has rectangles. - * - */ -Bool -miRegionAppend(RegionPtr dstrgn, RegionPtr rgn) -{ - int numRects, dnumRects, size; - BoxPtr new, old; - Bool prepend; - - if (REGION_NAR(rgn)) - return miRegionBreak (dstrgn); - - if (!rgn->data && (dstrgn->data == &miEmptyData)) - { - dstrgn->extents = rgn->extents; - dstrgn->data = NULL; - return TRUE; - } - - numRects = REGION_NUM_RECTS(rgn); - if (!numRects) - return TRUE; - prepend = FALSE; - size = numRects; - dnumRects = REGION_NUM_RECTS(dstrgn); - if (!dnumRects && (size < 200)) - size = 200; /* XXX pick numbers out of a hat */ - RECTALLOC(dstrgn, size); - old = REGION_RECTS(rgn); - if (!dnumRects) - dstrgn->extents = rgn->extents; - else if (dstrgn->extents.x2 > dstrgn->extents.x1) - { - BoxPtr first, last; - - first = old; - last = REGION_BOXPTR(dstrgn) + (dnumRects - 1); - if ((first->y1 > last->y2) || - ((first->y1 == last->y1) && (first->y2 == last->y2) && - (first->x1 > last->x2))) - { - if (rgn->extents.x1 < dstrgn->extents.x1) - dstrgn->extents.x1 = rgn->extents.x1; - if (rgn->extents.x2 > dstrgn->extents.x2) - dstrgn->extents.x2 = rgn->extents.x2; - dstrgn->extents.y2 = rgn->extents.y2; - } - else - { - first = REGION_BOXPTR(dstrgn); - last = old + (numRects - 1); - if ((first->y1 > last->y2) || - ((first->y1 == last->y1) && (first->y2 == last->y2) && - (first->x1 > last->x2))) - { - prepend = TRUE; - if (rgn->extents.x1 < dstrgn->extents.x1) - dstrgn->extents.x1 = rgn->extents.x1; - if (rgn->extents.x2 > dstrgn->extents.x2) - dstrgn->extents.x2 = rgn->extents.x2; - dstrgn->extents.y1 = rgn->extents.y1; - } - else - dstrgn->extents.x2 = dstrgn->extents.x1; - } - } - if (prepend) - { - new = REGION_BOX(dstrgn, numRects); - if (dnumRects == 1) - *new = *REGION_BOXPTR(dstrgn); - else - memmove((char *)new,(char *)REGION_BOXPTR(dstrgn), - dnumRects * sizeof(BoxRec)); - new = REGION_BOXPTR(dstrgn); - } - else - new = REGION_BOXPTR(dstrgn) + dnumRects; - if (numRects == 1) - *new = *old; - else - memmove((char *)new, (char *)old, numRects * sizeof(BoxRec)); - dstrgn->data->numRects += numRects; - return TRUE; -} - - -#define ExchangeRects(a, b) \ -{ \ - BoxRec t; \ - t = rects[a]; \ - rects[a] = rects[b]; \ - rects[b] = t; \ -} - -static void -QuickSortRects( - BoxRec rects[], - int numRects) -{ - int y1; - int x1; - int i, j; - BoxPtr r; - - /* Always called with numRects > 1 */ - - do - { - if (numRects == 2) - { - if (rects[0].y1 > rects[1].y1 || - (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1)) - ExchangeRects(0, 1); - return; - } - - /* Choose partition element, stick in location 0 */ - ExchangeRects(0, numRects >> 1); - y1 = rects[0].y1; - x1 = rects[0].x1; - - /* Partition array */ - i = 0; - j = numRects; - do - { - r = &(rects[i]); - do - { - r++; - i++; - } while (i != numRects && - (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1))); - r = &(rects[j]); - do - { - r--; - j--; - } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1)); - if (i < j) - ExchangeRects(i, j); - } while (i < j); - - /* Move partition element back to middle */ - ExchangeRects(0, j); - - /* Recurse */ - if (numRects-j-1 > 1) - QuickSortRects(&rects[j+1], numRects-j-1); - numRects = j; - } while (numRects > 1); -} - -/*- - *----------------------------------------------------------------------- - * miRegionValidate -- - * - * Take a ``region'' which is a non-y-x-banded random collection of - * rectangles, and compute a nice region which is the union of all the - * rectangles. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * The passed-in ``region'' may be modified. - * pOverlap set to TRUE if any retangles overlapped, else FALSE; - * - * Strategy: - * Step 1. Sort the rectangles into ascending order with primary key y1 - * and secondary key x1. - * - * Step 2. Split the rectangles into the minimum number of proper y-x - * banded regions. This may require horizontally merging - * rectangles, and vertically coalescing bands. With any luck, - * this step in an identity tranformation (ala the Box widget), - * or a coalescing into 1 box (ala Menus). - * - * Step 3. Merge the separate regions down to a single region by calling - * miUnion. Maximize the work each miUnion call does by using - * a binary merge. - * - *----------------------------------------------------------------------- - */ - -Bool -miRegionValidate(RegionPtr badreg, Bool *pOverlap) -{ - /* Descriptor for regions under construction in Step 2. */ - typedef struct { - RegionRec reg; - int prevBand; - int curBand; - } RegionInfo; - - int numRects; /* Original numRects for badreg */ - RegionInfo *ri; /* Array of current regions */ - int numRI; /* Number of entries used in ri */ - int sizeRI; /* Number of entries available in ri */ - int i; /* Index into rects */ - int j; /* Index into ri */ - RegionInfo *rit; /* &ri[j] */ - RegionPtr reg; /* ri[j].reg */ - BoxPtr box; /* Current box in rects */ - BoxPtr riBox; /* Last box in ri[j].reg */ - RegionPtr hreg; /* ri[j_half].reg */ - Bool ret = TRUE; - - *pOverlap = FALSE; - if (!badreg->data) - { - good(badreg); - return TRUE; - } - numRects = badreg->data->numRects; - if (!numRects) - { - if (REGION_NAR(badreg)) - return FALSE; - good(badreg); - return TRUE; - } - if (badreg->extents.x1 < badreg->extents.x2) - { - if ((numRects) == 1) - { - xfreeData(badreg); - badreg->data = (RegDataPtr) NULL; - } - else - { - DOWNSIZE(badreg, numRects); - } - good(badreg); - return TRUE; - } - - /* Step 1: Sort the rects array into ascending (y1, x1) order */ - QuickSortRects(REGION_BOXPTR(badreg), numRects); - - /* Step 2: Scatter the sorted array into the minimum number of regions */ - - /* Set up the first region to be the first rectangle in badreg */ - /* Note that step 2 code will never overflow the ri[0].reg rects array */ - ri = (RegionInfo *) xalloc(4 * sizeof(RegionInfo)); - if (!ri) - return miRegionBreak (badreg); - sizeRI = 4; - numRI = 1; - ri[0].prevBand = 0; - ri[0].curBand = 0; - ri[0].reg = *badreg; - box = REGION_BOXPTR(&ri[0].reg); - ri[0].reg.extents = *box; - ri[0].reg.data->numRects = 1; - - /* Now scatter rectangles into the minimum set of valid regions. If the - next rectangle to be added to a region would force an existing rectangle - in the region to be split up in order to maintain y-x banding, just - forget it. Try the next region. If it doesn't fit cleanly into any - region, make a new one. */ - - for (i = numRects; --i > 0;) - { - box++; - /* Look for a region to append box to */ - for (j = numRI, rit = ri; --j >= 0; rit++) - { - reg = &rit->reg; - riBox = REGION_END(reg); - - if (box->y1 == riBox->y1 && box->y2 == riBox->y2) - { - /* box is in same band as riBox. Merge or append it */ - if (box->x1 <= riBox->x2) - { - /* Merge it with riBox */ - if (box->x1 < riBox->x2) *pOverlap = TRUE; - if (box->x2 > riBox->x2) riBox->x2 = box->x2; - } - else - { - RECTALLOC_BAIL(reg, 1, bail); - *REGION_TOP(reg) = *box; - reg->data->numRects++; - } - goto NextRect; /* So sue me */ - } - else if (box->y1 >= riBox->y2) - { - /* Put box into new band */ - if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; - if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1; - Coalesce(reg, rit->prevBand, rit->curBand); - rit->curBand = reg->data->numRects; - RECTALLOC_BAIL(reg, 1, bail); - *REGION_TOP(reg) = *box; - reg->data->numRects++; - goto NextRect; - } - /* Well, this region was inappropriate. Try the next one. */ - } /* for j */ - - /* Uh-oh. No regions were appropriate. Create a new one. */ - if (sizeRI == numRI) - { - /* Oops, allocate space for new region information */ - sizeRI <<= 1; - rit = (RegionInfo *) xrealloc(ri, sizeRI * sizeof(RegionInfo)); - if (!rit) - goto bail; - ri = rit; - rit = &ri[numRI]; - } - numRI++; - rit->prevBand = 0; - rit->curBand = 0; - rit->reg.extents = *box; - rit->reg.data = NULL; - if (!miRectAlloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */ - goto bail; -NextRect: ; - } /* for i */ - - /* Make a final pass over each region in order to Coalesce and set - extents.x2 and extents.y2 */ - - for (j = numRI, rit = ri; --j >= 0; rit++) - { - reg = &rit->reg; - riBox = REGION_END(reg); - reg->extents.y2 = riBox->y2; - if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; - Coalesce(reg, rit->prevBand, rit->curBand); - if (reg->data->numRects == 1) /* keep unions happy below */ - { - xfreeData(reg); - reg->data = NULL; - } - } - - /* Step 3: Union all regions into a single region */ - while (numRI > 1) - { - int half = numRI/2; - for (j = numRI & 1; j < (half + (numRI & 1)); j++) - { - reg = &ri[j].reg; - hreg = &ri[j+half].reg; - if (!miRegionOp(reg, reg, hreg, miUnionO, TRUE, TRUE, pOverlap)) - ret = FALSE; - if (hreg->extents.x1 < reg->extents.x1) - reg->extents.x1 = hreg->extents.x1; - if (hreg->extents.y1 < reg->extents.y1) - reg->extents.y1 = hreg->extents.y1; - if (hreg->extents.x2 > reg->extents.x2) - reg->extents.x2 = hreg->extents.x2; - if (hreg->extents.y2 > reg->extents.y2) - reg->extents.y2 = hreg->extents.y2; - xfreeData(hreg); - } - numRI -= half; - } - *badreg = ri[0].reg; - xfree(ri); - good(badreg); - return ret; -bail: - for (i = 0; i < numRI; i++) - xfreeData(&ri[i].reg); - xfree (ri); - return miRegionBreak (badreg); -} - -RegionPtr -miRectsToRegion(int nrects, xRectangle *prect, int ctype) -{ - - RegionPtr pRgn; - RegDataPtr pData; - BoxPtr pBox; - int i; - int x1, y1, x2, y2; - - pRgn = miRegionCreate(NullBox, 0); - if (REGION_NAR (pRgn)) - return pRgn; - if (!nrects) - return pRgn; - if (nrects == 1) - { - x1 = prect->x; - y1 = prect->y; - if ((x2 = x1 + (int) prect->width) > MAXSHORT) - x2 = MAXSHORT; - if ((y2 = y1 + (int) prect->height) > MAXSHORT) - y2 = MAXSHORT; - if (x1 != x2 && y1 != y2) - { - pRgn->extents.x1 = x1; - pRgn->extents.y1 = y1; - pRgn->extents.x2 = x2; - pRgn->extents.y2 = y2; - pRgn->data = NULL; - } - return pRgn; - } - pData = xallocData(nrects); - if (!pData) - { - miRegionBreak (pRgn); - return pRgn; - } - pBox = (BoxPtr) (pData + 1); - for (i = nrects; --i >= 0; prect++) - { - x1 = prect->x; - y1 = prect->y; - if ((x2 = x1 + (int) prect->width) > MAXSHORT) - x2 = MAXSHORT; - if ((y2 = y1 + (int) prect->height) > MAXSHORT) - y2 = MAXSHORT; - if (x1 != x2 && y1 != y2) - { - pBox->x1 = x1; - pBox->y1 = y1; - pBox->x2 = x2; - pBox->y2 = y2; - pBox++; - } - } - if (pBox != (BoxPtr) (pData + 1)) - { - pData->size = nrects; - pData->numRects = pBox - (BoxPtr) (pData + 1); - pRgn->data = pData; - if (ctype != CT_YXBANDED) - { - Bool overlap; /* result ignored */ - pRgn->extents.x1 = pRgn->extents.x2 = 0; - miRegionValidate(pRgn, &overlap); - } - else - miSetExtents(pRgn); - good(pRgn); - } - else - { - xfree (pData); - } - return pRgn; -} - -/*====================================================================== - * Region Subtraction - *====================================================================*/ - - -/*- - *----------------------------------------------------------------------- - * miSubtractO -- - * Overlapping band subtraction. x1 is the left-most point not yet - * checked. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * pReg may have rectangles added to it. - * - *----------------------------------------------------------------------- - */ -/*ARGSUSED*/ - -/*- - *----------------------------------------------------------------------- - * miSubtract -- - * Subtract regS from regM and leave the result in regD. - * S stands for subtrahend, M for minuend and D for difference. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * regD is overwritten. - * - *----------------------------------------------------------------------- - */ -Bool -miSubtract(RegionPtr regD, RegionPtr regM, RegionPtr regS) -{ - return pixman_region_subtract (regD, regM, regS); -} - -/*====================================================================== - * Region Inversion - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miInverse -- - * Take a region and a box and return a region that is everything - * in the box but not in the region. The careful reader will note - * that this is the same as subtracting the region from the box... - * - * Results: - * TRUE. - * - * Side Effects: - * newReg is overwritten. - * - *----------------------------------------------------------------------- - */ -Bool -miInverse( - RegionPtr newReg, /* Destination region */ - RegionPtr reg1, /* Region to invert */ - BoxPtr invRect /* Bounding box for inversion */ - ) -{ - return pixman_region_inverse (newReg, reg1, invRect); -} -int -miRectIn(RegionPtr region, BoxPtr prect) -{ - return pixman_region_contains_rectangle (region, prect); -} - -/* TranslateRegion(pReg, x, y) - translates in place -*/ - -void -miTranslateRegion(RegionPtr pReg, int x, int y) -{ - pixman_region_translate (pReg, x, y); -} - -void -miRegionReset(RegionPtr pReg, BoxPtr pBox) -{ - pixman_region_reset (pReg, pBox); -} - -Bool -miPointInRegion( - RegionPtr pReg, - int x, - int y, - BoxPtr box /* "return" value */ - ) -{ - return pixman_region_contains_point (pReg, x, y, box); -} - -Bool -miRegionNotEmpty(RegionPtr pReg) -{ - return pixman_region_not_empty (pReg); -} - -Bool -miRegionBroken(RegionPtr pReg) -{ - good(pReg); - return (REGION_NAR(pReg)); -} - -void -miRegionEmpty(RegionPtr pReg) -{ - good(pReg); - xfreeData(pReg); - pReg->extents.x2 = pReg->extents.x1; - pReg->extents.y2 = pReg->extents.y1; - pReg->data = &miEmptyData; -} - -BoxPtr -miRegionExtents(RegionPtr pReg) -{ - good(pReg); - return(&pReg->extents); -} - -#define ExchangeSpans(a, b) \ -{ \ - DDXPointRec tpt; \ - int tw; \ - \ - tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \ - tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ -} - -/* ||| I should apply the merge sort code to rectangle sorting above, and see - if mapping time can be improved. But right now I've been at work 12 hours, - so forget it. -*/ - -static void QuickSortSpans( - DDXPointRec spans[], - int widths[], - int numSpans) -{ - int y; - int i, j, m; - DDXPointPtr r; - - /* Always called with numSpans > 1 */ - /* Sorts only by y, doesn't bother to sort by x */ - - do - { - if (numSpans < 9) - { - /* Do insertion sort */ - int yprev; - - yprev = spans[0].y; - i = 1; - do - { /* while i != numSpans */ - y = spans[i].y; - if (yprev > y) - { - /* spans[i] is out of order. Move into proper location. */ - DDXPointRec tpt; - int tw, k; - - for (j = 0; y >= spans[j].y; j++) {} - tpt = spans[i]; - tw = widths[i]; - for (k = i; k != j; k--) - { - spans[k] = spans[k-1]; - widths[k] = widths[k-1]; - } - spans[j] = tpt; - widths[j] = tw; - y = spans[i].y; - } /* if out of order */ - yprev = y; - i++; - } while (i != numSpans); - return; - } - - /* Choose partition element, stick in location 0 */ - m = numSpans / 2; - if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); - if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1); - if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); - y = spans[0].y; - - /* Partition array */ - i = 0; - j = numSpans; - do - { - r = &(spans[i]); - do - { - r++; - i++; - } while (i != numSpans && r->y < y); - r = &(spans[j]); - do - { - r--; - j--; - } while (y < r->y); - if (i < j) - ExchangeSpans(i, j); - } while (i < j); - - /* Move partition element back to middle */ - ExchangeSpans(0, j); - - /* Recurse */ - if (numSpans-j-1 > 1) - QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1); - numSpans = j; - } while (numSpans > 1); -} - -#define NextBand() \ -{ \ - clipy1 = pboxBandStart->y1; \ - clipy2 = pboxBandStart->y2; \ - pboxBandEnd = pboxBandStart + 1; \ - while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \ - pboxBandEnd++; \ - } \ - for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \ -} - -/* - Clip a list of scanlines to a region. The caller has allocated the - space. FSorted is non-zero if the scanline origins are in ascending - order. - returns the number of new, clipped scanlines. -*/ - -int -miClipSpans( - RegionPtr prgnDst, - DDXPointPtr ppt, - int *pwidth, - int nspans, - DDXPointPtr pptNew, - int *pwidthNew, - int fSorted) -{ - DDXPointPtr pptLast; - int *pwidthNewStart; /* the vengeance of Xerox! */ - int y, x1, x2; - int numRects; - - good(prgnDst); - pptLast = ppt + nspans; - pwidthNewStart = pwidthNew; - - if (!prgnDst->data) - { - /* Do special fast code with clip boundaries in registers(?) */ - /* It doesn't pay much to make use of fSorted in this case, - so we lump everything together. */ - - int clipx1, clipx2, clipy1, clipy2; - - clipx1 = prgnDst->extents.x1; - clipy1 = prgnDst->extents.y1; - clipx2 = prgnDst->extents.x2; - clipy2 = prgnDst->extents.y2; - - for (; ppt != pptLast; ppt++, pwidth++) - { - y = ppt->y; - x1 = ppt->x; - if (clipy1 <= y && y < clipy2) - { - x2 = x1 + *pwidth; - if (x1 < clipx1) x1 = clipx1; - if (x2 > clipx2) x2 = clipx2; - if (x1 < x2) - { - /* part of span in clip rectangle */ - pptNew->x = x1; - pptNew->y = y; - *pwidthNew = x2 - x1; - pptNew++; - pwidthNew++; - } - } - } /* end for */ - - } - else if ((numRects = prgnDst->data->numRects)) - { - /* Have to clip against many boxes */ - BoxPtr pboxBandStart, pboxBandEnd; - BoxPtr pbox; - BoxPtr pboxLast; - int clipy1, clipy2; - - /* In this case, taking advantage of sorted spans gains more than - the sorting costs. */ - if ((! fSorted) && (nspans > 1)) - QuickSortSpans(ppt, pwidth, nspans); - - pboxBandStart = REGION_BOXPTR(prgnDst); - pboxLast = pboxBandStart + numRects; - - NextBand(); - - for (; ppt != pptLast; ) - { - y = ppt->y; - if (y < clipy2) - { - /* span is in the current band */ - pbox = pboxBandStart; - x1 = ppt->x; - x2 = x1 + *pwidth; - do - { /* For each box in band */ - int newx1, newx2; - - newx1 = x1; - newx2 = x2; - if (newx1 < pbox->x1) newx1 = pbox->x1; - if (newx2 > pbox->x2) newx2 = pbox->x2; - if (newx1 < newx2) - { - /* Part of span in clip rectangle */ - pptNew->x = newx1; - pptNew->y = y; - *pwidthNew = newx2 - newx1; - pptNew++; - pwidthNew++; - } - pbox++; - } while (pbox != pboxBandEnd); - ppt++; - pwidth++; - } - else - { - /* Move to next band, adjust ppt as needed */ - pboxBandStart = pboxBandEnd; - if (pboxBandStart == pboxLast) - break; /* We're completely done */ - NextBand(); - } - } - } - return (pwidthNew - pwidthNewStart); -} +/***********************************************************
+
+Copyright 1987, 1988, 1989, 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.
+
+
+Copyright 1987, 1988, 1989 by
+Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+******************************************************************/
+
+/* The panoramix components contained the following notice */
+/*****************************************************************
+
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+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
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "regionstr.h"
+#include <X11/Xprotostr.h>
+#include <X11/Xfuncproto.h>
+#include "gc.h"
+#include "mi.h"
+#include "mispans.h"
+#include <pixman.h>
+
+#undef assert
+#ifdef REGION_DEBUG
+#define assert(expr) { \
+ CARD32 *foo = NULL; \
+ if (!(expr)) { \
+ ErrorF("Assertion failed file %s, line %d: %s\n", \
+ __FILE__, __LINE__, #expr); \
+ *foo = 0xdeadbeef; /* to get a backtrace */ \
+ } \
+ }
+#else
+#define assert(expr)
+#endif
+
+#define good(reg) assert(miValidRegion(reg))
+
+/*
+ * The functions in this file implement the Region abstraction used extensively
+ * throughout the X11 sample server. A Region is simply a set of disjoint
+ * (non-overlapping) rectangles, plus an "extent" rectangle which is the
+ * smallest single rectangle that contains all the non-overlapping rectangles.
+ *
+ * A Region is implemented as a "y-x-banded" array of rectangles. This array
+ * imposes two degrees of order. First, all rectangles are sorted by top side
+ * y coordinate first (y1), and then by left side x coordinate (x1).
+ *
+ * Furthermore, the rectangles are grouped into "bands". Each rectangle in a
+ * band has the same top y coordinate (y1), and each has the same bottom y
+ * coordinate (y2). Thus all rectangles in a band differ only in their left
+ * and right side (x1 and x2). Bands are implicit in the array of rectangles:
+ * there is no separate list of band start pointers.
+ *
+ * The y-x band representation does not minimize rectangles. In particular,
+ * if a rectangle vertically crosses a band (the rectangle has scanlines in
+ * the y1 to y2 area spanned by the band), then the rectangle may be broken
+ * down into two or more smaller rectangles stacked one atop the other.
+ *
+ * ----------- -----------
+ * | | | | band 0
+ * | | -------- ----------- --------
+ * | | | | in y-x banded | | | | band 1
+ * | | | | form is | | | |
+ * ----------- | | ----------- --------
+ * | | | | band 2
+ * -------- --------
+ *
+ * An added constraint on the rectangles is that they must cover as much
+ * horizontal area as possible: no two rectangles within a band are allowed
+ * to touch.
+ *
+ * Whenever possible, bands will be merged together to cover a greater vertical
+ * distance (and thus reduce the number of rectangles). Two bands can be merged
+ * only if the bottom of one touches the top of the other and they have
+ * rectangles in the same places (of the same width, of course).
+ *
+ * Adam de Boor wrote most of the original region code. Joel McCormack
+ * substantially modified or rewrote most of the core arithmetic routines,
+ * and added miRegionValidate in order to support several speed improvements
+ * to miValidateTree. Bob Scheifler changed the representation to be more
+ * compact when empty or a single rectangle, and did a bunch of gratuitous
+ * reformatting.
+ */
+
+/* true iff two Boxes overlap */
+#define EXTENTCHECK(r1,r2) \
+ (!( ((r1)->x2 <= (r2)->x1) || \
+ ((r1)->x1 >= (r2)->x2) || \
+ ((r1)->y2 <= (r2)->y1) || \
+ ((r1)->y1 >= (r2)->y2) ) )
+
+/* true iff (x,y) is in Box */
+#define INBOX(r,x,y) \
+ ( ((r)->x2 > x) && \
+ ((r)->x1 <= x) && \
+ ((r)->y2 > y) && \
+ ((r)->y1 <= y) )
+
+/* true iff Box r1 contains Box r2 */
+#define SUBSUMES(r1,r2) \
+ ( ((r1)->x1 <= (r2)->x1) && \
+ ((r1)->x2 >= (r2)->x2) && \
+ ((r1)->y1 <= (r2)->y1) && \
+ ((r1)->y2 >= (r2)->y2) )
+
+#define xallocData(n) malloc(REGION_SZOF(n))
+#define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
+
+#define RECTALLOC_BAIL(pReg,n,bail) \
+if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
+ if (!miRectAlloc(pReg, n)) { goto bail; }
+
+#define RECTALLOC(pReg,n) \
+if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
+ if (!miRectAlloc(pReg, n)) { return FALSE; }
+
+#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \
+{ \
+ pNextRect->x1 = nx1; \
+ pNextRect->y1 = ny1; \
+ pNextRect->x2 = nx2; \
+ pNextRect->y2 = ny2; \
+ pNextRect++; \
+}
+
+#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \
+{ \
+ if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
+ { \
+ if (!miRectAlloc(pReg, 1)) \
+ return FALSE; \
+ pNextRect = REGION_TOP(pReg); \
+ } \
+ ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \
+ pReg->data->numRects++; \
+ assert(pReg->data->numRects<=pReg->data->size); \
+}
+
+
+#define DOWNSIZE(reg,numRects) \
+if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
+{ \
+ RegDataPtr NewData; \
+ NewData = (RegDataPtr)realloc((reg)->data, REGION_SZOF(numRects)); \
+ if (NewData) \
+ { \
+ NewData->size = (numRects); \
+ (reg)->data = NewData; \
+ } \
+}
+
+
+BoxRec miEmptyBox = {0, 0, 0, 0};
+RegDataRec miEmptyData = {0, 0};
+
+RegDataRec miBrokenData = {0, 0};
+static RegionRec miBrokenRegion = { { 0, 0, 0, 0 }, &miBrokenData };
+
+void
+InitRegions (void)
+{
+ pixman_region_set_static_pointers (&miEmptyBox, &miEmptyData, &miBrokenData);
+}
+
+/*****************************************************************
+ * RegionCreate(rect, size)
+ * This routine does a simple malloc to make a structure of
+ * REGION of "size" number of rectangles.
+ *****************************************************************/
+
+RegionPtr
+miRegionCreate(BoxPtr rect, int size)
+{
+ RegionPtr pReg;
+
+ pReg = (RegionPtr)malloc(sizeof(RegionRec));
+ if (!pReg)
+ return &miBrokenRegion;
+
+ miRegionInit (pReg, rect, size);
+
+ return(pReg);
+}
+
+void
+miRegionDestroy(RegionPtr pReg)
+{
+ pixman_region_fini (pReg);
+ if (pReg != &miBrokenRegion)
+ free(pReg);
+}
+
+void
+miPrintRegion(RegionPtr rgn)
+{
+ int num, size;
+ int i;
+ BoxPtr rects;
+
+ num = REGION_NUM_RECTS(rgn);
+ size = REGION_SIZE(rgn);
+ rects = REGION_RECTS(rgn);
+ ErrorF("[mi] num: %d size: %d\n", num, size);
+ ErrorF("[mi] extents: %d %d %d %d\n",
+ rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
+ for (i = 0; i < num; i++)
+ ErrorF("[mi] %d %d %d %d \n",
+ rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
+ ErrorF("[mi] \n");
+}
+
+Bool
+miRegionEqual(RegionPtr reg1, RegionPtr reg2)
+{
+ return pixman_region_equal (reg1, reg2);
+}
+
+#ifdef DEBUG
+Bool
+miValidRegion(RegionPtr reg)
+{
+ int i, numRects;
+
+ if ((reg->extents.x1 > reg->extents.x2) ||
+ (reg->extents.y1 > reg->extents.y2))
+ return FALSE;
+ numRects = REGION_NUM_RECTS(reg);
+ if (!numRects)
+ return ((reg->extents.x1 == reg->extents.x2) &&
+ (reg->extents.y1 == reg->extents.y2) &&
+ (reg->data->size || (reg->data == &miEmptyData)));
+ else if (numRects == 1)
+ return (!reg->data);
+ else
+ {
+ BoxPtr pboxP, pboxN;
+ BoxRec box;
+
+ pboxP = REGION_RECTS(reg);
+ box = *pboxP;
+ box.y2 = pboxP[numRects-1].y2;
+ pboxN = pboxP + 1;
+ for (i = numRects; --i > 0; pboxP++, pboxN++)
+ {
+ if ((pboxN->x1 >= pboxN->x2) ||
+ (pboxN->y1 >= pboxN->y2))
+ return FALSE;
+ if (pboxN->x1 < box.x1)
+ box.x1 = pboxN->x1;
+ if (pboxN->x2 > box.x2)
+ box.x2 = pboxN->x2;
+ if ((pboxN->y1 < pboxP->y1) ||
+ ((pboxN->y1 == pboxP->y1) &&
+ ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2))))
+ return FALSE;
+ }
+ return ((box.x1 == reg->extents.x1) &&
+ (box.x2 == reg->extents.x2) &&
+ (box.y1 == reg->extents.y1) &&
+ (box.y2 == reg->extents.y2));
+ }
+}
+#endif /* DEBUG */
+
+/*****************************************************************
+ * RegionInit(pReg, rect, size)
+ * Outer region rect is statically allocated.
+ *****************************************************************/
+
+void
+miRegionInit(RegionPtr pReg, BoxPtr rect, int size)
+{
+ if (rect)
+ pixman_region_init_with_extents (pReg, rect);
+ else
+ pixman_region_init (pReg);
+}
+
+void
+miRegionUninit(RegionPtr pReg)
+{
+ pixman_region_fini (pReg);
+}
+
+Bool
+miRegionBreak (RegionPtr pReg)
+{
+ xfreeData (pReg);
+ pReg->extents = miEmptyBox;
+ pReg->data = &miBrokenData;
+ return FALSE;
+}
+
+Bool
+miRectAlloc(RegionPtr pRgn, int n)
+{
+ RegDataPtr data;
+
+ if (!pRgn->data)
+ {
+ n++;
+ pRgn->data = xallocData(n);
+ if (!pRgn->data)
+ return miRegionBreak (pRgn);
+ pRgn->data->numRects = 1;
+ *REGION_BOXPTR(pRgn) = pRgn->extents;
+ }
+ else if (!pRgn->data->size)
+ {
+ pRgn->data = xallocData(n);
+ if (!pRgn->data)
+ return miRegionBreak (pRgn);
+ pRgn->data->numRects = 0;
+ }
+ else
+ {
+ if (n == 1)
+ {
+ n = pRgn->data->numRects;
+ if (n > 500) /* XXX pick numbers out of a hat */
+ n = 250;
+ }
+ n += pRgn->data->numRects;
+ data = (RegDataPtr)realloc(pRgn->data, REGION_SZOF(n));
+ if (!data)
+ return miRegionBreak (pRgn);
+ pRgn->data = data;
+ }
+ pRgn->data->size = n;
+ return TRUE;
+}
+
+Bool
+miRegionCopy(RegionPtr dst, RegionPtr src)
+{
+ return pixman_region_copy (dst, src);
+}
+
+/*======================================================================
+ * Generic Region Operator
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * miCoalesce --
+ * Attempt to merge the boxes in the current band with those in the
+ * previous one. We are guaranteed that the current band extends to
+ * the end of the rects array. Used only by miRegionOp.
+ *
+ * Results:
+ * The new index for the previous band.
+ *
+ * Side Effects:
+ * If coalescing takes place:
+ * - rectangles in the previous band will have their y2 fields
+ * altered.
+ * - pReg->data->numRects will be decreased.
+ *
+ *-----------------------------------------------------------------------
+ */
+_X_INLINE static int
+miCoalesce (
+ RegionPtr pReg, /* Region to coalesce */
+ int prevStart, /* Index of start of previous band */
+ int curStart) /* Index of start of current band */
+{
+ BoxPtr pPrevBox; /* Current box in previous band */
+ BoxPtr pCurBox; /* Current box in current band */
+ int numRects; /* Number rectangles in both bands */
+ int y2; /* Bottom of current band */
+ /*
+ * Figure out how many rectangles are in the band.
+ */
+ numRects = curStart - prevStart;
+ assert(numRects == pReg->data->numRects - curStart);
+
+ if (!numRects) return curStart;
+
+ /*
+ * The bands may only be coalesced if the bottom of the previous
+ * matches the top scanline of the current.
+ */
+ pPrevBox = REGION_BOX(pReg, prevStart);
+ pCurBox = REGION_BOX(pReg, curStart);
+ if (pPrevBox->y2 != pCurBox->y1) return curStart;
+
+ /*
+ * Make sure the bands have boxes in the same places. This
+ * assumes that boxes have been added in such a way that they
+ * cover the most area possible. I.e. two boxes in a band must
+ * have some horizontal space between them.
+ */
+ y2 = pCurBox->y2;
+
+ do {
+ if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {
+ return (curStart);
+ }
+ pPrevBox++;
+ pCurBox++;
+ numRects--;
+ } while (numRects);
+
+ /*
+ * The bands may be merged, so set the bottom y of each box
+ * in the previous band to the bottom y of the current band.
+ */
+ numRects = curStart - prevStart;
+ pReg->data->numRects -= numRects;
+ do {
+ pPrevBox--;
+ pPrevBox->y2 = y2;
+ numRects--;
+ } while (numRects);
+ return prevStart;
+}
+
+
+/* Quicky macro to avoid trivial reject procedure calls to miCoalesce */
+
+#define Coalesce(newReg, prevBand, curBand) \
+ if (curBand - prevBand == newReg->data->numRects - curBand) { \
+ prevBand = miCoalesce(newReg, prevBand, curBand); \
+ } else { \
+ prevBand = curBand; \
+ }
+
+/*-
+ *-----------------------------------------------------------------------
+ * miAppendNonO --
+ * Handle a non-overlapping band for the union and subtract operations.
+ * Just adds the (top/bottom-clipped) rectangles into the region.
+ * Doesn't have to check for subsumption or anything.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * pReg->data->numRects is incremented and the rectangles overwritten
+ * with the rectangles we're passed.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+_X_INLINE static Bool
+miAppendNonO (
+ RegionPtr pReg,
+ BoxPtr r,
+ BoxPtr rEnd,
+ int y1,
+ int y2)
+{
+ BoxPtr pNextRect;
+ int newRects;
+
+ newRects = rEnd - r;
+
+ assert(y1 < y2);
+ assert(newRects != 0);
+
+ /* Make sure we have enough space for all rectangles to be added */
+ RECTALLOC(pReg, newRects);
+ pNextRect = REGION_TOP(pReg);
+ pReg->data->numRects += newRects;
+ do {
+ assert(r->x1 < r->x2);
+ ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
+ r++;
+ } while (r != rEnd);
+
+ return TRUE;
+}
+
+#define FindBand(r, rBandEnd, rEnd, ry1) \
+{ \
+ ry1 = r->y1; \
+ rBandEnd = r+1; \
+ while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \
+ rBandEnd++; \
+ } \
+}
+
+#define AppendRegions(newReg, r, rEnd) \
+{ \
+ int newRects; \
+ if ((newRects = rEnd - r)) { \
+ RECTALLOC(newReg, newRects); \
+ memmove((char *)REGION_TOP(newReg),(char *)r, \
+ newRects * sizeof(BoxRec)); \
+ newReg->data->numRects += newRects; \
+ } \
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * miRegionOp --
+ * Apply an operation to two regions. Called by miUnion, miInverse,
+ * miSubtract, miIntersect.... Both regions MUST have at least one
+ * rectangle, and cannot be the same object.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * The new region is overwritten.
+ * pOverlap set to TRUE if overlapFunc ever returns TRUE.
+ *
+ * Notes:
+ * The idea behind this function is to view the two regions as sets.
+ * Together they cover a rectangle of area that this function divides
+ * into horizontal bands where points are covered only by one region
+ * or by both. For the first case, the nonOverlapFunc is called with
+ * each the band and the band's upper and lower extents. For the
+ * second, the overlapFunc is called to process the entire band. It
+ * is responsible for clipping the rectangles in the band, though
+ * this function provides the boundaries.
+ * At the end of each band, the new region is coalesced, if possible,
+ * to reduce the number of rectangles in the region.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+typedef Bool (*OverlapProcPtr)(
+ RegionPtr pReg,
+ BoxPtr r1,
+ BoxPtr r1End,
+ BoxPtr r2,
+ BoxPtr r2End,
+ short y1,
+ short y2,
+ Bool *pOverlap);
+
+static Bool
+miRegionOp(
+ RegionPtr newReg, /* Place to store result */
+ RegionPtr reg1, /* First region in operation */
+ RegionPtr reg2, /* 2d region in operation */
+ OverlapProcPtr overlapFunc, /* Function to call for over-
+ * lapping bands */
+ Bool appendNon1, /* Append non-overlapping bands */
+ /* in region 1 ? */
+ Bool appendNon2, /* Append non-overlapping bands */
+ /* in region 2 ? */
+ Bool *pOverlap)
+{
+ BoxPtr r1; /* Pointer into first region */
+ BoxPtr r2; /* Pointer into 2d region */
+ BoxPtr r1End; /* End of 1st region */
+ BoxPtr r2End; /* End of 2d region */
+ short ybot; /* Bottom of intersection */
+ short ytop; /* Top of intersection */
+ RegDataPtr oldData; /* Old data for newReg */
+ int prevBand; /* Index of start of
+ * previous band in newReg */
+ int curBand; /* Index of start of current
+ * band in newReg */
+ BoxPtr r1BandEnd; /* End of current band in r1 */
+ BoxPtr r2BandEnd; /* End of current band in r2 */
+ short top; /* Top of non-overlapping band */
+ short bot; /* Bottom of non-overlapping band*/
+ int r1y1; /* Temps for r1->y1 and r2->y1 */
+ int r2y1;
+ int newSize;
+ int numRects;
+
+ /*
+ * Break any region computed from a broken region
+ */
+ if (REGION_NAR (reg1) || REGION_NAR(reg2))
+ return miRegionBreak (newReg);
+
+ /*
+ * Initialization:
+ * set r1, r2, r1End and r2End appropriately, save the rectangles
+ * of the destination region until the end in case it's one of
+ * the two source regions, then mark the "new" region empty, allocating
+ * another array of rectangles for it to use.
+ */
+
+ r1 = REGION_RECTS(reg1);
+ newSize = REGION_NUM_RECTS(reg1);
+ r1End = r1 + newSize;
+ numRects = REGION_NUM_RECTS(reg2);
+ r2 = REGION_RECTS(reg2);
+ r2End = r2 + numRects;
+ assert(r1 != r1End);
+ assert(r2 != r2End);
+
+ oldData = NULL;
+ if (((newReg == reg1) && (newSize > 1)) ||
+ ((newReg == reg2) && (numRects > 1)))
+ {
+ oldData = newReg->data;
+ newReg->data = &miEmptyData;
+ }
+ /* guess at new size */
+ if (numRects > newSize)
+ newSize = numRects;
+ newSize <<= 1;
+ if (!newReg->data)
+ newReg->data = &miEmptyData;
+ else if (newReg->data->size)
+ newReg->data->numRects = 0;
+ if (newSize > newReg->data->size)
+ if (!miRectAlloc(newReg, newSize))
+ return FALSE;
+
+ /*
+ * Initialize ybot.
+ * In the upcoming loop, ybot and ytop serve different functions depending
+ * on whether the band being handled is an overlapping or non-overlapping
+ * band.
+ * In the case of a non-overlapping band (only one of the regions
+ * has points in the band), ybot is the bottom of the most recent
+ * intersection and thus clips the top of the rectangles in that band.
+ * ytop is the top of the next intersection between the two regions and
+ * serves to clip the bottom of the rectangles in the current band.
+ * For an overlapping band (where the two regions intersect), ytop clips
+ * the top of the rectangles of both regions and ybot clips the bottoms.
+ */
+
+ ybot = min(r1->y1, r2->y1);
+
+ /*
+ * prevBand serves to mark the start of the previous band so rectangles
+ * can be coalesced into larger rectangles. qv. miCoalesce, above.
+ * In the beginning, there is no previous band, so prevBand == curBand
+ * (curBand is set later on, of course, but the first band will always
+ * start at index 0). prevBand and curBand must be indices because of
+ * the possible expansion, and resultant moving, of the new region's
+ * array of rectangles.
+ */
+ prevBand = 0;
+
+ do {
+ /*
+ * This algorithm proceeds one source-band (as opposed to a
+ * destination band, which is determined by where the two regions
+ * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
+ * rectangle after the last one in the current band for their
+ * respective regions.
+ */
+ assert(r1 != r1End);
+ assert(r2 != r2End);
+
+ FindBand(r1, r1BandEnd, r1End, r1y1);
+ FindBand(r2, r2BandEnd, r2End, r2y1);
+
+ /*
+ * First handle the band that doesn't intersect, if any.
+ *
+ * Note that attention is restricted to one band in the
+ * non-intersecting region at once, so if a region has n
+ * bands between the current position and the next place it overlaps
+ * the other, this entire loop will be passed through n times.
+ */
+ if (r1y1 < r2y1) {
+ if (appendNon1) {
+ top = max(r1y1, ybot);
+ bot = min(r1->y2, r2y1);
+ if (top != bot) {
+ curBand = newReg->data->numRects;
+ miAppendNonO(newReg, r1, r1BandEnd, top, bot);
+ Coalesce(newReg, prevBand, curBand);
+ }
+ }
+ ytop = r2y1;
+ } else if (r2y1 < r1y1) {
+ if (appendNon2) {
+ top = max(r2y1, ybot);
+ bot = min(r2->y2, r1y1);
+ if (top != bot) {
+ curBand = newReg->data->numRects;
+ miAppendNonO(newReg, r2, r2BandEnd, top, bot);
+ Coalesce(newReg, prevBand, curBand);
+ }
+ }
+ ytop = r1y1;
+ } else {
+ ytop = r1y1;
+ }
+
+ /*
+ * Now see if we've hit an intersecting band. The two bands only
+ * intersect if ybot > ytop
+ */
+ ybot = min(r1->y2, r2->y2);
+ if (ybot > ytop) {
+ curBand = newReg->data->numRects;
+ (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,
+ pOverlap);
+ Coalesce(newReg, prevBand, curBand);
+ }
+
+ /*
+ * If we've finished with a band (y2 == ybot) we skip forward
+ * in the region to the next band.
+ */
+ if (r1->y2 == ybot) r1 = r1BandEnd;
+ if (r2->y2 == ybot) r2 = r2BandEnd;
+
+ } while (r1 != r1End && r2 != r2End);
+
+ /*
+ * Deal with whichever region (if any) still has rectangles left.
+ *
+ * We only need to worry about banding and coalescing for the very first
+ * band left. After that, we can just group all remaining boxes,
+ * regardless of how many bands, into one final append to the list.
+ */
+
+ if ((r1 != r1End) && appendNon1) {
+ /* Do first nonOverlap1Func call, which may be able to coalesce */
+ FindBand(r1, r1BandEnd, r1End, r1y1);
+ curBand = newReg->data->numRects;
+ miAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2);
+ Coalesce(newReg, prevBand, curBand);
+ /* Just append the rest of the boxes */
+ AppendRegions(newReg, r1BandEnd, r1End);
+
+ } else if ((r2 != r2End) && appendNon2) {
+ /* Do first nonOverlap2Func call, which may be able to coalesce */
+ FindBand(r2, r2BandEnd, r2End, r2y1);
+ curBand = newReg->data->numRects;
+ miAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2);
+ Coalesce(newReg, prevBand, curBand);
+ /* Append rest of boxes */
+ AppendRegions(newReg, r2BandEnd, r2End);
+ }
+
+ if (oldData)
+ free(oldData);
+
+ if (!(numRects = newReg->data->numRects))
+ {
+ xfreeData(newReg);
+ newReg->data = &miEmptyData;
+ }
+ else if (numRects == 1)
+ {
+ newReg->extents = *REGION_BOXPTR(newReg);
+ xfreeData(newReg);
+ newReg->data = NULL;
+ }
+ else
+ {
+ DOWNSIZE(newReg, numRects);
+ }
+
+ return TRUE;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * miSetExtents --
+ * Reset the extents of a region to what they should be. Called by
+ * miSubtract and miIntersect as they can't figure it out along the
+ * way or do so easily, as miUnion can.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The region's 'extents' structure is overwritten.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+miSetExtents (RegionPtr pReg)
+{
+ BoxPtr pBox, pBoxEnd;
+
+ if (!pReg->data)
+ return;
+ if (!pReg->data->size)
+ {
+ pReg->extents.x2 = pReg->extents.x1;
+ pReg->extents.y2 = pReg->extents.y1;
+ return;
+ }
+
+ pBox = REGION_BOXPTR(pReg);
+ pBoxEnd = REGION_END(pReg);
+
+ /*
+ * Since pBox is the first rectangle in the region, it must have the
+ * smallest y1 and since pBoxEnd is the last rectangle in the region,
+ * it must have the largest y2, because of banding. Initialize x1 and
+ * x2 from pBox and pBoxEnd, resp., as good things to initialize them
+ * to...
+ */
+ pReg->extents.x1 = pBox->x1;
+ pReg->extents.y1 = pBox->y1;
+ pReg->extents.x2 = pBoxEnd->x2;
+ pReg->extents.y2 = pBoxEnd->y2;
+
+ assert(pReg->extents.y1 < pReg->extents.y2);
+ while (pBox <= pBoxEnd) {
+ if (pBox->x1 < pReg->extents.x1)
+ pReg->extents.x1 = pBox->x1;
+ if (pBox->x2 > pReg->extents.x2)
+ pReg->extents.x2 = pBox->x2;
+ pBox++;
+ };
+
+ assert(pReg->extents.x1 < pReg->extents.x2);
+}
+
+/*======================================================================
+ * Region Intersection
+ *====================================================================*/
+/*-
+ *-----------------------------------------------------------------------
+ * miIntersectO --
+ * Handle an overlapping band for miIntersect.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * Rectangles may be added to the region.
+ *
+ *-----------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+Bool
+miIntersect(
+ RegionPtr newReg, /* destination Region */
+ RegionPtr reg1,
+ RegionPtr reg2 /* source regions */
+ )
+{
+ return pixman_region_intersect (newReg, reg1, reg2);
+}
+
+#define MERGERECT(r) \
+{ \
+ if (r->x1 <= x2) { \
+ /* Merge with current rectangle */ \
+ if (r->x1 < x2) *pOverlap = TRUE; \
+ if (x2 < r->x2) x2 = r->x2; \
+ } else { \
+ /* Add current rectangle, start new one */ \
+ NEWRECT(pReg, pNextRect, x1, y1, x2, y2); \
+ x1 = r->x1; \
+ x2 = r->x2; \
+ } \
+ r++; \
+}
+
+/*======================================================================
+ * Region Union
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * miUnionO --
+ * Handle an overlapping band for the union operation. Picks the
+ * left-most rectangle each time and merges it into the region.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * pReg is overwritten.
+ * pOverlap is set to TRUE if any boxes overlap.
+ *
+ *-----------------------------------------------------------------------
+ */
+static Bool
+miUnionO (
+ RegionPtr pReg,
+ BoxPtr r1,
+ BoxPtr r1End,
+ BoxPtr r2,
+ BoxPtr r2End,
+ short y1,
+ short y2,
+ Bool *pOverlap)
+{
+ BoxPtr pNextRect;
+ int x1; /* left and right side of current union */
+ int x2;
+
+ assert (y1 < y2);
+ assert(r1 != r1End && r2 != r2End);
+
+ pNextRect = REGION_TOP(pReg);
+
+ /* Start off current rectangle */
+ if (r1->x1 < r2->x1)
+ {
+ x1 = r1->x1;
+ x2 = r1->x2;
+ r1++;
+ }
+ else
+ {
+ x1 = r2->x1;
+ x2 = r2->x2;
+ r2++;
+ }
+ while (r1 != r1End && r2 != r2End)
+ {
+ if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
+ }
+
+ /* Finish off whoever (if any) is left */
+ if (r1 != r1End)
+ {
+ do
+ {
+ MERGERECT(r1);
+ } while (r1 != r1End);
+ }
+ else if (r2 != r2End)
+ {
+ do
+ {
+ MERGERECT(r2);
+ } while (r2 != r2End);
+ }
+
+ /* Add current rectangle */
+ NEWRECT(pReg, pNextRect, x1, y1, x2, y2);
+
+ return TRUE;
+}
+
+Bool
+miUnion(
+ RegionPtr newReg, /* destination Region */
+ RegionPtr reg1,
+ RegionPtr reg2 /* source regions */
+ )
+{
+ return pixman_region_union (newReg, reg1, reg2);
+}
+
+/*======================================================================
+ * Batch Rectangle Union
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * miRegionAppend --
+ *
+ * "Append" the rgn rectangles onto the end of dstrgn, maintaining
+ * knowledge of YX-banding when it's easy. Otherwise, dstrgn just
+ * becomes a non-y-x-banded random collection of rectangles, and not
+ * yet a true region. After a sequence of appends, the caller must
+ * call miRegionValidate to ensure that a valid region is constructed.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * dstrgn is modified if rgn has rectangles.
+ *
+ */
+Bool
+miRegionAppend(RegionPtr dstrgn, RegionPtr rgn)
+{
+ int numRects, dnumRects, size;
+ BoxPtr new, old;
+ Bool prepend;
+
+ if (REGION_NAR(rgn))
+ return miRegionBreak (dstrgn);
+
+ if (!rgn->data && (dstrgn->data == &miEmptyData))
+ {
+ dstrgn->extents = rgn->extents;
+ dstrgn->data = NULL;
+ return TRUE;
+ }
+
+ numRects = REGION_NUM_RECTS(rgn);
+ if (!numRects)
+ return TRUE;
+ prepend = FALSE;
+ size = numRects;
+ dnumRects = REGION_NUM_RECTS(dstrgn);
+ if (!dnumRects && (size < 200))
+ size = 200; /* XXX pick numbers out of a hat */
+ RECTALLOC(dstrgn, size);
+ old = REGION_RECTS(rgn);
+ if (!dnumRects)
+ dstrgn->extents = rgn->extents;
+ else if (dstrgn->extents.x2 > dstrgn->extents.x1)
+ {
+ BoxPtr first, last;
+
+ first = old;
+ last = REGION_BOXPTR(dstrgn) + (dnumRects - 1);
+ if ((first->y1 > last->y2) ||
+ ((first->y1 == last->y1) && (first->y2 == last->y2) &&
+ (first->x1 > last->x2)))
+ {
+ if (rgn->extents.x1 < dstrgn->extents.x1)
+ dstrgn->extents.x1 = rgn->extents.x1;
+ if (rgn->extents.x2 > dstrgn->extents.x2)
+ dstrgn->extents.x2 = rgn->extents.x2;
+ dstrgn->extents.y2 = rgn->extents.y2;
+ }
+ else
+ {
+ first = REGION_BOXPTR(dstrgn);
+ last = old + (numRects - 1);
+ if ((first->y1 > last->y2) ||
+ ((first->y1 == last->y1) && (first->y2 == last->y2) &&
+ (first->x1 > last->x2)))
+ {
+ prepend = TRUE;
+ if (rgn->extents.x1 < dstrgn->extents.x1)
+ dstrgn->extents.x1 = rgn->extents.x1;
+ if (rgn->extents.x2 > dstrgn->extents.x2)
+ dstrgn->extents.x2 = rgn->extents.x2;
+ dstrgn->extents.y1 = rgn->extents.y1;
+ }
+ else
+ dstrgn->extents.x2 = dstrgn->extents.x1;
+ }
+ }
+ if (prepend)
+ {
+ new = REGION_BOX(dstrgn, numRects);
+ if (dnumRects == 1)
+ *new = *REGION_BOXPTR(dstrgn);
+ else
+ memmove((char *)new,(char *)REGION_BOXPTR(dstrgn),
+ dnumRects * sizeof(BoxRec));
+ new = REGION_BOXPTR(dstrgn);
+ }
+ else
+ new = REGION_BOXPTR(dstrgn) + dnumRects;
+ if (numRects == 1)
+ *new = *old;
+ else
+ memmove((char *)new, (char *)old, numRects * sizeof(BoxRec));
+ dstrgn->data->numRects += numRects;
+ return TRUE;
+}
+
+
+#define ExchangeRects(a, b) \
+{ \
+ BoxRec t; \
+ t = rects[a]; \
+ rects[a] = rects[b]; \
+ rects[b] = t; \
+}
+
+static void
+QuickSortRects(
+ BoxRec rects[],
+ int numRects)
+{
+ int y1;
+ int x1;
+ int i, j;
+ BoxPtr r;
+
+ /* Always called with numRects > 1 */
+
+ do
+ {
+ if (numRects == 2)
+ {
+ if (rects[0].y1 > rects[1].y1 ||
+ (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
+ ExchangeRects(0, 1);
+ return;
+ }
+
+ /* Choose partition element, stick in location 0 */
+ ExchangeRects(0, numRects >> 1);
+ y1 = rects[0].y1;
+ x1 = rects[0].x1;
+
+ /* Partition array */
+ i = 0;
+ j = numRects;
+ do
+ {
+ r = &(rects[i]);
+ do
+ {
+ r++;
+ i++;
+ } while (i != numRects &&
+ (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
+ r = &(rects[j]);
+ do
+ {
+ r--;
+ j--;
+ } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
+ if (i < j)
+ ExchangeRects(i, j);
+ } while (i < j);
+
+ /* Move partition element back to middle */
+ ExchangeRects(0, j);
+
+ /* Recurse */
+ if (numRects-j-1 > 1)
+ QuickSortRects(&rects[j+1], numRects-j-1);
+ numRects = j;
+ } while (numRects > 1);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * miRegionValidate --
+ *
+ * Take a ``region'' which is a non-y-x-banded random collection of
+ * rectangles, and compute a nice region which is the union of all the
+ * rectangles.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * The passed-in ``region'' may be modified.
+ * pOverlap set to TRUE if any retangles overlapped, else FALSE;
+ *
+ * Strategy:
+ * Step 1. Sort the rectangles into ascending order with primary key y1
+ * and secondary key x1.
+ *
+ * Step 2. Split the rectangles into the minimum number of proper y-x
+ * banded regions. This may require horizontally merging
+ * rectangles, and vertically coalescing bands. With any luck,
+ * this step in an identity tranformation (ala the Box widget),
+ * or a coalescing into 1 box (ala Menus).
+ *
+ * Step 3. Merge the separate regions down to a single region by calling
+ * miUnion. Maximize the work each miUnion call does by using
+ * a binary merge.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+Bool
+miRegionValidate(RegionPtr badreg, Bool *pOverlap)
+{
+ /* Descriptor for regions under construction in Step 2. */
+ typedef struct {
+ RegionRec reg;
+ int prevBand;
+ int curBand;
+ } RegionInfo;
+
+ int numRects; /* Original numRects for badreg */
+ RegionInfo *ri; /* Array of current regions */
+ int numRI; /* Number of entries used in ri */
+ int sizeRI; /* Number of entries available in ri */
+ int i; /* Index into rects */
+ int j; /* Index into ri */
+ RegionInfo *rit; /* &ri[j] */
+ RegionPtr reg; /* ri[j].reg */
+ BoxPtr box; /* Current box in rects */
+ BoxPtr riBox; /* Last box in ri[j].reg */
+ RegionPtr hreg; /* ri[j_half].reg */
+ Bool ret = TRUE;
+
+ *pOverlap = FALSE;
+ if (!badreg->data)
+ {
+ good(badreg);
+ return TRUE;
+ }
+ numRects = badreg->data->numRects;
+ if (!numRects)
+ {
+ if (REGION_NAR(badreg))
+ return FALSE;
+ good(badreg);
+ return TRUE;
+ }
+ if (badreg->extents.x1 < badreg->extents.x2)
+ {
+ if ((numRects) == 1)
+ {
+ xfreeData(badreg);
+ badreg->data = (RegDataPtr) NULL;
+ }
+ else
+ {
+ DOWNSIZE(badreg, numRects);
+ }
+ good(badreg);
+ return TRUE;
+ }
+
+ /* Step 1: Sort the rects array into ascending (y1, x1) order */
+ QuickSortRects(REGION_BOXPTR(badreg), numRects);
+
+ /* Step 2: Scatter the sorted array into the minimum number of regions */
+
+ /* Set up the first region to be the first rectangle in badreg */
+ /* Note that step 2 code will never overflow the ri[0].reg rects array */
+ ri = (RegionInfo *) malloc(4 * sizeof(RegionInfo));
+ if (!ri)
+ return miRegionBreak (badreg);
+ sizeRI = 4;
+ numRI = 1;
+ ri[0].prevBand = 0;
+ ri[0].curBand = 0;
+ ri[0].reg = *badreg;
+ box = REGION_BOXPTR(&ri[0].reg);
+ ri[0].reg.extents = *box;
+ ri[0].reg.data->numRects = 1;
+
+ /* Now scatter rectangles into the minimum set of valid regions. If the
+ next rectangle to be added to a region would force an existing rectangle
+ in the region to be split up in order to maintain y-x banding, just
+ forget it. Try the next region. If it doesn't fit cleanly into any
+ region, make a new one. */
+
+ for (i = numRects; --i > 0;)
+ {
+ box++;
+ /* Look for a region to append box to */
+ for (j = numRI, rit = ri; --j >= 0; rit++)
+ {
+ reg = &rit->reg;
+ riBox = REGION_END(reg);
+
+ if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
+ {
+ /* box is in same band as riBox. Merge or append it */
+ if (box->x1 <= riBox->x2)
+ {
+ /* Merge it with riBox */
+ if (box->x1 < riBox->x2) *pOverlap = TRUE;
+ if (box->x2 > riBox->x2) riBox->x2 = box->x2;
+ }
+ else
+ {
+ RECTALLOC_BAIL(reg, 1, bail);
+ *REGION_TOP(reg) = *box;
+ reg->data->numRects++;
+ }
+ goto NextRect; /* So sue me */
+ }
+ else if (box->y1 >= riBox->y2)
+ {
+ /* Put box into new band */
+ if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
+ if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1;
+ Coalesce(reg, rit->prevBand, rit->curBand);
+ rit->curBand = reg->data->numRects;
+ RECTALLOC_BAIL(reg, 1, bail);
+ *REGION_TOP(reg) = *box;
+ reg->data->numRects++;
+ goto NextRect;
+ }
+ /* Well, this region was inappropriate. Try the next one. */
+ } /* for j */
+
+ /* Uh-oh. No regions were appropriate. Create a new one. */
+ if (sizeRI == numRI)
+ {
+ /* Oops, allocate space for new region information */
+ sizeRI <<= 1;
+ rit = (RegionInfo *) realloc(ri, sizeRI * sizeof(RegionInfo));
+ if (!rit)
+ goto bail;
+ ri = rit;
+ rit = &ri[numRI];
+ }
+ numRI++;
+ rit->prevBand = 0;
+ rit->curBand = 0;
+ rit->reg.extents = *box;
+ rit->reg.data = NULL;
+ if (!miRectAlloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
+ goto bail;
+NextRect: ;
+ } /* for i */
+
+ /* Make a final pass over each region in order to Coalesce and set
+ extents.x2 and extents.y2 */
+
+ for (j = numRI, rit = ri; --j >= 0; rit++)
+ {
+ reg = &rit->reg;
+ riBox = REGION_END(reg);
+ reg->extents.y2 = riBox->y2;
+ if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
+ Coalesce(reg, rit->prevBand, rit->curBand);
+ if (reg->data->numRects == 1) /* keep unions happy below */
+ {
+ xfreeData(reg);
+ reg->data = NULL;
+ }
+ }
+
+ /* Step 3: Union all regions into a single region */
+ while (numRI > 1)
+ {
+ int half = numRI/2;
+ for (j = numRI & 1; j < (half + (numRI & 1)); j++)
+ {
+ reg = &ri[j].reg;
+ hreg = &ri[j+half].reg;
+ if (!miRegionOp(reg, reg, hreg, miUnionO, TRUE, TRUE, pOverlap))
+ ret = FALSE;
+ if (hreg->extents.x1 < reg->extents.x1)
+ reg->extents.x1 = hreg->extents.x1;
+ if (hreg->extents.y1 < reg->extents.y1)
+ reg->extents.y1 = hreg->extents.y1;
+ if (hreg->extents.x2 > reg->extents.x2)
+ reg->extents.x2 = hreg->extents.x2;
+ if (hreg->extents.y2 > reg->extents.y2)
+ reg->extents.y2 = hreg->extents.y2;
+ xfreeData(hreg);
+ }
+ numRI -= half;
+ }
+ *badreg = ri[0].reg;
+ free(ri);
+ good(badreg);
+ return ret;
+bail:
+ for (i = 0; i < numRI; i++)
+ xfreeData(&ri[i].reg);
+ free(ri);
+ return miRegionBreak (badreg);
+}
+
+RegionPtr
+miRectsToRegion(int nrects, xRectangle *prect, int ctype)
+{
+
+ RegionPtr pRgn;
+ RegDataPtr pData;
+ BoxPtr pBox;
+ int i;
+ int x1, y1, x2, y2;
+
+ pRgn = miRegionCreate(NullBox, 0);
+ if (REGION_NAR (pRgn))
+ return pRgn;
+ if (!nrects)
+ return pRgn;
+ if (nrects == 1)
+ {
+ x1 = prect->x;
+ y1 = prect->y;
+ if ((x2 = x1 + (int) prect->width) > MAXSHORT)
+ x2 = MAXSHORT;
+ if ((y2 = y1 + (int) prect->height) > MAXSHORT)
+ y2 = MAXSHORT;
+ if (x1 != x2 && y1 != y2)
+ {
+ pRgn->extents.x1 = x1;
+ pRgn->extents.y1 = y1;
+ pRgn->extents.x2 = x2;
+ pRgn->extents.y2 = y2;
+ pRgn->data = NULL;
+ }
+ return pRgn;
+ }
+ pData = xallocData(nrects);
+ if (!pData)
+ {
+ miRegionBreak (pRgn);
+ return pRgn;
+ }
+ pBox = (BoxPtr) (pData + 1);
+ for (i = nrects; --i >= 0; prect++)
+ {
+ x1 = prect->x;
+ y1 = prect->y;
+ if ((x2 = x1 + (int) prect->width) > MAXSHORT)
+ x2 = MAXSHORT;
+ if ((y2 = y1 + (int) prect->height) > MAXSHORT)
+ y2 = MAXSHORT;
+ if (x1 != x2 && y1 != y2)
+ {
+ pBox->x1 = x1;
+ pBox->y1 = y1;
+ pBox->x2 = x2;
+ pBox->y2 = y2;
+ pBox++;
+ }
+ }
+ if (pBox != (BoxPtr) (pData + 1))
+ {
+ pData->size = nrects;
+ pData->numRects = pBox - (BoxPtr) (pData + 1);
+ pRgn->data = pData;
+ if (ctype != CT_YXBANDED)
+ {
+ Bool overlap; /* result ignored */
+ pRgn->extents.x1 = pRgn->extents.x2 = 0;
+ miRegionValidate(pRgn, &overlap);
+ }
+ else
+ miSetExtents(pRgn);
+ good(pRgn);
+ }
+ else
+ {
+ free(pData);
+ }
+ return pRgn;
+}
+
+/*======================================================================
+ * Region Subtraction
+ *====================================================================*/
+
+
+/*-
+ *-----------------------------------------------------------------------
+ * miSubtractO --
+ * Overlapping band subtraction. x1 is the left-most point not yet
+ * checked.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * pReg may have rectangles added to it.
+ *
+ *-----------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * miSubtract --
+ * Subtract regS from regM and leave the result in regD.
+ * S stands for subtrahend, M for minuend and D for difference.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * regD is overwritten.
+ *
+ *-----------------------------------------------------------------------
+ */
+Bool
+miSubtract(RegionPtr regD, RegionPtr regM, RegionPtr regS)
+{
+ return pixman_region_subtract (regD, regM, regS);
+}
+
+/*======================================================================
+ * Region Inversion
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * miInverse --
+ * Take a region and a box and return a region that is everything
+ * in the box but not in the region. The careful reader will note
+ * that this is the same as subtracting the region from the box...
+ *
+ * Results:
+ * TRUE.
+ *
+ * Side Effects:
+ * newReg is overwritten.
+ *
+ *-----------------------------------------------------------------------
+ */
+Bool
+miInverse(
+ RegionPtr newReg, /* Destination region */
+ RegionPtr reg1, /* Region to invert */
+ BoxPtr invRect /* Bounding box for inversion */
+ )
+{
+ return pixman_region_inverse (newReg, reg1, invRect);
+}
+int
+miRectIn(RegionPtr region, BoxPtr prect)
+{
+ return pixman_region_contains_rectangle (region, prect);
+}
+
+/* TranslateRegion(pReg, x, y)
+ translates in place
+*/
+
+void
+miTranslateRegion(RegionPtr pReg, int x, int y)
+{
+ pixman_region_translate (pReg, x, y);
+}
+
+void
+miRegionReset(RegionPtr pReg, BoxPtr pBox)
+{
+ pixman_region_reset (pReg, pBox);
+}
+
+Bool
+miPointInRegion(
+ RegionPtr pReg,
+ int x,
+ int y,
+ BoxPtr box /* "return" value */
+ )
+{
+ return pixman_region_contains_point (pReg, x, y, box);
+}
+
+Bool
+miRegionNotEmpty(RegionPtr pReg)
+{
+ return pixman_region_not_empty (pReg);
+}
+
+Bool
+miRegionBroken(RegionPtr pReg)
+{
+ good(pReg);
+ return (REGION_NAR(pReg));
+}
+
+void
+miRegionEmpty(RegionPtr pReg)
+{
+ good(pReg);
+ xfreeData(pReg);
+ pReg->extents.x2 = pReg->extents.x1;
+ pReg->extents.y2 = pReg->extents.y1;
+ pReg->data = &miEmptyData;
+}
+
+BoxPtr
+miRegionExtents(RegionPtr pReg)
+{
+ good(pReg);
+ return(&pReg->extents);
+}
+
+#define ExchangeSpans(a, b) \
+{ \
+ DDXPointRec tpt; \
+ int tw; \
+ \
+ tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \
+ tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
+}
+
+/* ||| I should apply the merge sort code to rectangle sorting above, and see
+ if mapping time can be improved. But right now I've been at work 12 hours,
+ so forget it.
+*/
+
+static void QuickSortSpans(
+ DDXPointRec spans[],
+ int widths[],
+ int numSpans)
+{
+ int y;
+ int i, j, m;
+ DDXPointPtr r;
+
+ /* Always called with numSpans > 1 */
+ /* Sorts only by y, doesn't bother to sort by x */
+
+ do
+ {
+ if (numSpans < 9)
+ {
+ /* Do insertion sort */
+ int yprev;
+
+ yprev = spans[0].y;
+ i = 1;
+ do
+ { /* while i != numSpans */
+ y = spans[i].y;
+ if (yprev > y)
+ {
+ /* spans[i] is out of order. Move into proper location. */
+ DDXPointRec tpt;
+ int tw, k;
+
+ for (j = 0; y >= spans[j].y; j++) {}
+ tpt = spans[i];
+ tw = widths[i];
+ for (k = i; k != j; k--)
+ {
+ spans[k] = spans[k-1];
+ widths[k] = widths[k-1];
+ }
+ spans[j] = tpt;
+ widths[j] = tw;
+ y = spans[i].y;
+ } /* if out of order */
+ yprev = y;
+ i++;
+ } while (i != numSpans);
+ return;
+ }
+
+ /* Choose partition element, stick in location 0 */
+ m = numSpans / 2;
+ if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
+ if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1);
+ if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
+ y = spans[0].y;
+
+ /* Partition array */
+ i = 0;
+ j = numSpans;
+ do
+ {
+ r = &(spans[i]);
+ do
+ {
+ r++;
+ i++;
+ } while (i != numSpans && r->y < y);
+ r = &(spans[j]);
+ do
+ {
+ r--;
+ j--;
+ } while (y < r->y);
+ if (i < j)
+ ExchangeSpans(i, j);
+ } while (i < j);
+
+ /* Move partition element back to middle */
+ ExchangeSpans(0, j);
+
+ /* Recurse */
+ if (numSpans-j-1 > 1)
+ QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
+ numSpans = j;
+ } while (numSpans > 1);
+}
+
+#define NextBand() \
+{ \
+ clipy1 = pboxBandStart->y1; \
+ clipy2 = pboxBandStart->y2; \
+ pboxBandEnd = pboxBandStart + 1; \
+ while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \
+ pboxBandEnd++; \
+ } \
+ for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \
+}
+
+/*
+ Clip a list of scanlines to a region. The caller has allocated the
+ space. FSorted is non-zero if the scanline origins are in ascending
+ order.
+ returns the number of new, clipped scanlines.
+*/
+
+int
+miClipSpans(
+ RegionPtr prgnDst,
+ DDXPointPtr ppt,
+ int *pwidth,
+ int nspans,
+ DDXPointPtr pptNew,
+ int *pwidthNew,
+ int fSorted)
+{
+ DDXPointPtr pptLast;
+ int *pwidthNewStart; /* the vengeance of Xerox! */
+ int y, x1, x2;
+ int numRects;
+
+ good(prgnDst);
+ pptLast = ppt + nspans;
+ pwidthNewStart = pwidthNew;
+
+ if (!prgnDst->data)
+ {
+ /* Do special fast code with clip boundaries in registers(?) */
+ /* It doesn't pay much to make use of fSorted in this case,
+ so we lump everything together. */
+
+ int clipx1, clipx2, clipy1, clipy2;
+
+ clipx1 = prgnDst->extents.x1;
+ clipy1 = prgnDst->extents.y1;
+ clipx2 = prgnDst->extents.x2;
+ clipy2 = prgnDst->extents.y2;
+
+ for (; ppt != pptLast; ppt++, pwidth++)
+ {
+ y = ppt->y;
+ x1 = ppt->x;
+ if (clipy1 <= y && y < clipy2)
+ {
+ x2 = x1 + *pwidth;
+ if (x1 < clipx1) x1 = clipx1;
+ if (x2 > clipx2) x2 = clipx2;
+ if (x1 < x2)
+ {
+ /* part of span in clip rectangle */
+ pptNew->x = x1;
+ pptNew->y = y;
+ *pwidthNew = x2 - x1;
+ pptNew++;
+ pwidthNew++;
+ }
+ }
+ } /* end for */
+
+ }
+ else if ((numRects = prgnDst->data->numRects))
+ {
+ /* Have to clip against many boxes */
+ BoxPtr pboxBandStart, pboxBandEnd;
+ BoxPtr pbox;
+ BoxPtr pboxLast;
+ int clipy1, clipy2;
+
+ /* In this case, taking advantage of sorted spans gains more than
+ the sorting costs. */
+ if ((! fSorted) && (nspans > 1))
+ QuickSortSpans(ppt, pwidth, nspans);
+
+ pboxBandStart = REGION_BOXPTR(prgnDst);
+ pboxLast = pboxBandStart + numRects;
+
+ NextBand();
+
+ for (; ppt != pptLast; )
+ {
+ y = ppt->y;
+ if (y < clipy2)
+ {
+ /* span is in the current band */
+ pbox = pboxBandStart;
+ x1 = ppt->x;
+ x2 = x1 + *pwidth;
+ do
+ { /* For each box in band */
+ int newx1, newx2;
+
+ newx1 = x1;
+ newx2 = x2;
+ if (newx1 < pbox->x1) newx1 = pbox->x1;
+ if (newx2 > pbox->x2) newx2 = pbox->x2;
+ if (newx1 < newx2)
+ {
+ /* Part of span in clip rectangle */
+ pptNew->x = newx1;
+ pptNew->y = y;
+ *pwidthNew = newx2 - newx1;
+ pptNew++;
+ pwidthNew++;
+ }
+ pbox++;
+ } while (pbox != pboxBandEnd);
+ ppt++;
+ pwidth++;
+ }
+ else
+ {
+ /* Move to next band, adjust ppt as needed */
+ pboxBandStart = pboxBandEnd;
+ if (pboxBandStart == pboxLast)
+ break; /* We're completely done */
+ NextBand();
+ }
+ }
+ }
+ return (pwidthNew - pwidthNewStart);
+}
diff --git a/xorg-server/mi/miscrinit.c b/xorg-server/mi/miscrinit.c index 96113d65d..2af17672b 100644 --- a/xorg-server/mi/miscrinit.c +++ b/xorg-server/mi/miscrinit.c @@ -1,313 +1,312 @@ -/* - -Copyright 1990, 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 <X11/X.h> -#include "servermd.h" -#include "misc.h" -#include "mi.h" -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "dix.h" -#include "miline.h" -#ifdef MITSHM -#include <X11/extensions/shm.h> -#include "shmint.h" -#endif - -/* We use this structure to propogate some information from miScreenInit to - * miCreateScreenResources. miScreenInit allocates the structure, fills it - * in, and puts it into pScreen->devPrivate. miCreateScreenResources - * extracts the info and frees the structure. We could've accomplished the - * same thing by adding fields to the screen structure, but they would have - * ended up being redundant, and would have exposed this mi implementation - * detail to the whole server. - */ - -typedef struct -{ - pointer pbits; /* pointer to framebuffer */ - int width; /* delta to add to a framebuffer addr to move one row down */ -} miScreenInitParmsRec, *miScreenInitParmsPtr; - - -/* this plugs into pScreen->ModifyPixmapHeader */ -Bool -miModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, - int bitsPerPixel, int devKind, pointer pPixData) -{ - if (!pPixmap) - return FALSE; - - /* - * If all arguments are specified, reinitialize everything (including - * validated state). - */ - if ((width > 0) && (height > 0) && (depth > 0) && (bitsPerPixel > 0) && - (devKind > 0) && pPixData) { - pPixmap->drawable.depth = depth; - pPixmap->drawable.bitsPerPixel = bitsPerPixel; - pPixmap->drawable.id = 0; - pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - pPixmap->drawable.x = 0; - pPixmap->drawable.y = 0; - pPixmap->drawable.width = width; - pPixmap->drawable.height = height; - pPixmap->devKind = devKind; - pPixmap->refcnt = 1; - pPixmap->devPrivate.ptr = pPixData; - } else { - /* - * Only modify specified fields, keeping all others intact. - */ - - if (width > 0) - pPixmap->drawable.width = width; - - if (height > 0) - pPixmap->drawable.height = height; - - if (depth > 0) - pPixmap->drawable.depth = depth; - - if (bitsPerPixel > 0) - pPixmap->drawable.bitsPerPixel = bitsPerPixel; - else if ((bitsPerPixel < 0) && (depth > 0)) - pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth); - - /* - * CAVEAT: Non-SI DDXen may use devKind and devPrivate fields for - * other purposes. - */ - if (devKind > 0) - pPixmap->devKind = devKind; - else if ((devKind < 0) && ((width > 0) || (depth > 0))) - pPixmap->devKind = PixmapBytePad(pPixmap->drawable.width, - pPixmap->drawable.depth); - - if (pPixData) - pPixmap->devPrivate.ptr = pPixData; - } - return TRUE; -} - -static Bool -miCloseScreen (int iScreen, ScreenPtr pScreen) -{ - return ((*pScreen->DestroyPixmap)((PixmapPtr)pScreen->devPrivate)); -} - -/* With the introduction of pixmap privates, the "screen pixmap" can no - * longer be created in miScreenInit, since all the modules that could - * possibly ask for pixmap private space have not been initialized at - * that time. pScreen->CreateScreenResources is called after all - * possible private-requesting modules have been inited; we create the - * screen pixmap here. - */ -Bool -miCreateScreenResources(ScreenPtr pScreen) -{ - miScreenInitParmsPtr pScrInitParms; - pointer value; - - pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; - - /* if width is non-zero, pScreen->devPrivate will be a pixmap - * else it will just take the value pbits - */ - if (pScrInitParms->width) - { - PixmapPtr pPixmap; - - /* create a pixmap with no data, then redirect it to point to - * the screen - */ - pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); - if (!pPixmap) - return FALSE; - - if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width, - pScreen->height, pScreen->rootDepth, - BitsPerPixel(pScreen->rootDepth), - PixmapBytePad(pScrInitParms->width, pScreen->rootDepth), - pScrInitParms->pbits)) - return FALSE; - value = (pointer)pPixmap; - } - else - { - value = pScrInitParms->pbits; - } - xfree(pScreen->devPrivate); /* freeing miScreenInitParmsRec */ - pScreen->devPrivate = value; /* pPixmap or pbits */ - return TRUE; -} - -Bool -miScreenDevPrivateInit(ScreenPtr pScreen, int width, pointer pbits) -{ - miScreenInitParmsPtr pScrInitParms; - - /* Stash pbits and width in a short-lived miScreenInitParmsRec attached - * to the screen, until CreateScreenResources can put them in the - * screen pixmap. - */ - pScrInitParms = xalloc(sizeof(miScreenInitParmsRec)); - if (!pScrInitParms) - return FALSE; - pScrInitParms->pbits = pbits; - pScrInitParms->width = width; - pScreen->devPrivate = (pointer)pScrInitParms; - return TRUE; -} - -static PixmapPtr -miGetScreenPixmap(ScreenPtr pScreen) -{ - return (PixmapPtr)(pScreen->devPrivate); -} - -static void -miSetScreenPixmap(PixmapPtr pPix) -{ - if (pPix) - pPix->drawable.pScreen->devPrivate = (pointer)pPix; -} - -Bool -miScreenInit( - ScreenPtr pScreen, - pointer pbits, /* pointer to screen bits */ - int xsize, int ysize, /* in pixels */ - int dpix, int dpiy, /* dots per inch */ - int width, /* pixel width of frame buffer */ - int rootDepth, /* depth of root window */ - int numDepths, /* number of depths supported */ - DepthRec *depths, /* supported depths */ - VisualID rootVisual, /* root visual */ - int numVisuals, /* number of visuals supported */ - VisualRec *visuals /* supported visuals */ - ) -{ - pScreen->width = xsize; - pScreen->height = ysize; - pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10); - pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10); - pScreen->numDepths = numDepths; - pScreen->rootDepth = rootDepth; - pScreen->allowedDepths = depths; - pScreen->rootVisual = rootVisual; - /* defColormap */ - pScreen->minInstalledCmaps = 1; - pScreen->maxInstalledCmaps = 1; - pScreen->backingStoreSupport = NotUseful; - pScreen->saveUnderSupport = NotUseful; - /* whitePixel, blackPixel */ - pScreen->ModifyPixmapHeader = miModifyPixmapHeader; - pScreen->CreateScreenResources = miCreateScreenResources; - pScreen->GetScreenPixmap = miGetScreenPixmap; - pScreen->SetScreenPixmap = miSetScreenPixmap; - pScreen->numVisuals = numVisuals; - pScreen->visuals = visuals; - if (width) - { -#ifdef MITSHM - ShmRegisterFbFuncs(pScreen); -#endif - pScreen->CloseScreen = miCloseScreen; - } - /* else CloseScreen */ - /* QueryBestSize, SaveScreen, GetImage, GetSpans */ - pScreen->PointerNonInterestBox = (PointerNonInterestBoxProcPtr) 0; - pScreen->SourceValidate = (SourceValidateProcPtr) 0; - /* CreateWindow, DestroyWindow, PositionWindow, ChangeWindowAttributes */ - /* RealizeWindow, UnrealizeWindow */ - pScreen->ValidateTree = miValidateTree; - pScreen->PostValidateTree = (PostValidateTreeProcPtr) 0; - pScreen->WindowExposures = miWindowExposures; - /* CopyWindow */ - pScreen->ClearToBackground = miClearToBackground; - pScreen->ClipNotify = (ClipNotifyProcPtr) 0; - pScreen->RestackWindow = (RestackWindowProcPtr) 0; - /* CreatePixmap, DestroyPixmap */ - /* RealizeFont, UnrealizeFont */ - /* CreateGC */ - /* CreateColormap, DestroyColormap, InstallColormap, UninstallColormap */ - /* ListInstalledColormaps, StoreColors, ResolveColor */ - /* BitmapToRegion */ - pScreen->SendGraphicsExpose = miSendGraphicsExpose; - pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA; - pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA; - pScreen->blockData = (pointer)0; - pScreen->wakeupData = (pointer)0; - pScreen->MarkWindow = miMarkWindow; - pScreen->MarkOverlappedWindows = miMarkOverlappedWindows; - pScreen->ChangeSaveUnder = NULL; - pScreen->PostChangeSaveUnder = NULL; - pScreen->MoveWindow = miMoveWindow; - pScreen->ResizeWindow = miSlideAndSizeWindow; - pScreen->GetLayerWindow = miGetLayerWindow; - pScreen->HandleExposures = miHandleValidateExposures; - pScreen->ReparentWindow = (ReparentWindowProcPtr) 0; - pScreen->ChangeBorderWidth = miChangeBorderWidth; - pScreen->SetShape = miSetShape; - pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow; - - pScreen->SaveDoomedAreas = 0; - pScreen->RestoreAreas = 0; - pScreen->ExposeCopy = 0; - pScreen->TranslateBackingStore = 0; - pScreen->ClearBackingStore = 0; - pScreen->DrawGuarantee = 0; - - miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS); - - return miScreenDevPrivateInit(pScreen, width, pbits); -} - -static int privateKeyIndex; -static DevPrivateKey privateKey = &privateKeyIndex; - -DevPrivateKey -miAllocateGCPrivateIndex(void) -{ - return privateKey; -} - -static int miZeroLineScreenKeyIndex; -DevPrivateKey miZeroLineScreenKey = &miZeroLineScreenKeyIndex; - -void -miSetZeroLineBias(ScreenPtr pScreen, unsigned int bias) -{ - dixSetPrivate(&pScreen->devPrivates, miZeroLineScreenKey, - (unsigned long *)(unsigned long)bias); -} +/*
+
+Copyright 1990, 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 <X11/X.h>
+#include "servermd.h"
+#include "misc.h"
+#include "mi.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "dix.h"
+#include "miline.h"
+#ifdef MITSHM
+#include <X11/extensions/shm.h>
+#include "shmint.h"
+#endif
+
+/* We use this structure to propogate some information from miScreenInit to
+ * miCreateScreenResources. miScreenInit allocates the structure, fills it
+ * in, and puts it into pScreen->devPrivate. miCreateScreenResources
+ * extracts the info and frees the structure. We could've accomplished the
+ * same thing by adding fields to the screen structure, but they would have
+ * ended up being redundant, and would have exposed this mi implementation
+ * detail to the whole server.
+ */
+
+typedef struct
+{
+ pointer pbits; /* pointer to framebuffer */
+ int width; /* delta to add to a framebuffer addr to move one row down */
+} miScreenInitParmsRec, *miScreenInitParmsPtr;
+
+
+/* this plugs into pScreen->ModifyPixmapHeader */
+Bool
+miModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ if (!pPixmap)
+ return FALSE;
+
+ /*
+ * If all arguments are specified, reinitialize everything (including
+ * validated state).
+ */
+ if ((width > 0) && (height > 0) && (depth > 0) && (bitsPerPixel > 0) &&
+ (devKind > 0) && pPixData) {
+ pPixmap->drawable.depth = depth;
+ pPixmap->drawable.bitsPerPixel = bitsPerPixel;
+ pPixmap->drawable.id = 0;
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pPixmap->drawable.x = 0;
+ pPixmap->drawable.y = 0;
+ pPixmap->drawable.width = width;
+ pPixmap->drawable.height = height;
+ pPixmap->devKind = devKind;
+ pPixmap->refcnt = 1;
+ pPixmap->devPrivate.ptr = pPixData;
+ } else {
+ /*
+ * Only modify specified fields, keeping all others intact.
+ */
+
+ if (width > 0)
+ pPixmap->drawable.width = width;
+
+ if (height > 0)
+ pPixmap->drawable.height = height;
+
+ if (depth > 0)
+ pPixmap->drawable.depth = depth;
+
+ if (bitsPerPixel > 0)
+ pPixmap->drawable.bitsPerPixel = bitsPerPixel;
+ else if ((bitsPerPixel < 0) && (depth > 0))
+ pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth);
+
+ /*
+ * CAVEAT: Non-SI DDXen may use devKind and devPrivate fields for
+ * other purposes.
+ */
+ if (devKind > 0)
+ pPixmap->devKind = devKind;
+ else if ((devKind < 0) && ((width > 0) || (depth > 0)))
+ pPixmap->devKind = PixmapBytePad(pPixmap->drawable.width,
+ pPixmap->drawable.depth);
+
+ if (pPixData)
+ pPixmap->devPrivate.ptr = pPixData;
+ }
+ return TRUE;
+}
+
+static Bool
+miCloseScreen (int iScreen, ScreenPtr pScreen)
+{
+ return ((*pScreen->DestroyPixmap)((PixmapPtr)pScreen->devPrivate));
+}
+
+/* With the introduction of pixmap privates, the "screen pixmap" can no
+ * longer be created in miScreenInit, since all the modules that could
+ * possibly ask for pixmap private space have not been initialized at
+ * that time. pScreen->CreateScreenResources is called after all
+ * possible private-requesting modules have been inited; we create the
+ * screen pixmap here.
+ */
+Bool
+miCreateScreenResources(ScreenPtr pScreen)
+{
+ miScreenInitParmsPtr pScrInitParms;
+ pointer value;
+
+ pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate;
+
+ /* if width is non-zero, pScreen->devPrivate will be a pixmap
+ * else it will just take the value pbits
+ */
+ if (pScrInitParms->width)
+ {
+ PixmapPtr pPixmap;
+
+ /* create a pixmap with no data, then redirect it to point to
+ * the screen
+ */
+ pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0);
+ if (!pPixmap)
+ return FALSE;
+
+ if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width,
+ pScreen->height, pScreen->rootDepth,
+ BitsPerPixel(pScreen->rootDepth),
+ PixmapBytePad(pScrInitParms->width, pScreen->rootDepth),
+ pScrInitParms->pbits))
+ return FALSE;
+ value = (pointer)pPixmap;
+ }
+ else
+ {
+ value = pScrInitParms->pbits;
+ }
+ free(pScreen->devPrivate); /* freeing miScreenInitParmsRec */
+ pScreen->devPrivate = value; /* pPixmap or pbits */
+ return TRUE;
+}
+
+Bool
+miScreenDevPrivateInit(ScreenPtr pScreen, int width, pointer pbits)
+{
+ miScreenInitParmsPtr pScrInitParms;
+
+ /* Stash pbits and width in a short-lived miScreenInitParmsRec attached
+ * to the screen, until CreateScreenResources can put them in the
+ * screen pixmap.
+ */
+ pScrInitParms = malloc(sizeof(miScreenInitParmsRec));
+ if (!pScrInitParms)
+ return FALSE;
+ pScrInitParms->pbits = pbits;
+ pScrInitParms->width = width;
+ pScreen->devPrivate = (pointer)pScrInitParms;
+ return TRUE;
+}
+
+static PixmapPtr
+miGetScreenPixmap(ScreenPtr pScreen)
+{
+ return (PixmapPtr)(pScreen->devPrivate);
+}
+
+static void
+miSetScreenPixmap(PixmapPtr pPix)
+{
+ if (pPix)
+ pPix->drawable.pScreen->devPrivate = (pointer)pPix;
+}
+
+Bool
+miScreenInit(
+ ScreenPtr pScreen,
+ pointer pbits, /* pointer to screen bits */
+ int xsize, int ysize, /* in pixels */
+ int dpix, int dpiy, /* dots per inch */
+ int width, /* pixel width of frame buffer */
+ int rootDepth, /* depth of root window */
+ int numDepths, /* number of depths supported */
+ DepthRec *depths, /* supported depths */
+ VisualID rootVisual, /* root visual */
+ int numVisuals, /* number of visuals supported */
+ VisualRec *visuals /* supported visuals */
+ )
+{
+ pScreen->width = xsize;
+ pScreen->height = ysize;
+ pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10);
+ pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10);
+ pScreen->numDepths = numDepths;
+ pScreen->rootDepth = rootDepth;
+ pScreen->allowedDepths = depths;
+ pScreen->rootVisual = rootVisual;
+ /* defColormap */
+ pScreen->minInstalledCmaps = 1;
+ pScreen->maxInstalledCmaps = 1;
+ pScreen->backingStoreSupport = NotUseful;
+ pScreen->saveUnderSupport = NotUseful;
+ /* whitePixel, blackPixel */
+ pScreen->ModifyPixmapHeader = miModifyPixmapHeader;
+ pScreen->CreateScreenResources = miCreateScreenResources;
+ pScreen->GetScreenPixmap = miGetScreenPixmap;
+ pScreen->SetScreenPixmap = miSetScreenPixmap;
+ pScreen->numVisuals = numVisuals;
+ pScreen->visuals = visuals;
+ if (width)
+ {
+#ifdef MITSHM
+ ShmRegisterFbFuncs(pScreen);
+#endif
+ pScreen->CloseScreen = miCloseScreen;
+ }
+ /* else CloseScreen */
+ /* QueryBestSize, SaveScreen, GetImage, GetSpans */
+ pScreen->SourceValidate = (SourceValidateProcPtr) 0;
+ /* CreateWindow, DestroyWindow, PositionWindow, ChangeWindowAttributes */
+ /* RealizeWindow, UnrealizeWindow */
+ pScreen->ValidateTree = miValidateTree;
+ pScreen->PostValidateTree = (PostValidateTreeProcPtr) 0;
+ pScreen->WindowExposures = miWindowExposures;
+ /* CopyWindow */
+ pScreen->ClearToBackground = miClearToBackground;
+ pScreen->ClipNotify = (ClipNotifyProcPtr) 0;
+ pScreen->RestackWindow = (RestackWindowProcPtr) 0;
+ /* CreatePixmap, DestroyPixmap */
+ /* RealizeFont, UnrealizeFont */
+ /* CreateGC */
+ /* CreateColormap, DestroyColormap, InstallColormap, UninstallColormap */
+ /* ListInstalledColormaps, StoreColors, ResolveColor */
+ /* BitmapToRegion */
+ pScreen->SendGraphicsExpose = miSendGraphicsExpose;
+ pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA;
+ pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA;
+ pScreen->blockData = (pointer)0;
+ pScreen->wakeupData = (pointer)0;
+ pScreen->MarkWindow = miMarkWindow;
+ pScreen->MarkOverlappedWindows = miMarkOverlappedWindows;
+ pScreen->ChangeSaveUnder = NULL;
+ pScreen->PostChangeSaveUnder = NULL;
+ pScreen->MoveWindow = miMoveWindow;
+ pScreen->ResizeWindow = miSlideAndSizeWindow;
+ pScreen->GetLayerWindow = miGetLayerWindow;
+ pScreen->HandleExposures = miHandleValidateExposures;
+ pScreen->ReparentWindow = (ReparentWindowProcPtr) 0;
+ pScreen->ChangeBorderWidth = miChangeBorderWidth;
+ pScreen->SetShape = miSetShape;
+ pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow;
+
+ pScreen->SaveDoomedAreas = 0;
+ pScreen->RestoreAreas = 0;
+ pScreen->ExposeCopy = 0;
+ pScreen->TranslateBackingStore = 0;
+ pScreen->ClearBackingStore = 0;
+ pScreen->DrawGuarantee = 0;
+
+ miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS);
+
+ return miScreenDevPrivateInit(pScreen, width, pbits);
+}
+
+static int privateKeyIndex;
+static DevPrivateKey privateKey = &privateKeyIndex;
+
+DevPrivateKey
+miAllocateGCPrivateIndex(void)
+{
+ return privateKey;
+}
+
+static int miZeroLineScreenKeyIndex;
+DevPrivateKey miZeroLineScreenKey = &miZeroLineScreenKeyIndex;
+
+void
+miSetZeroLineBias(ScreenPtr pScreen, unsigned int bias)
+{
+ dixSetPrivate(&pScreen->devPrivates, miZeroLineScreenKey,
+ (unsigned long *)(unsigned long)bias);
+}
diff --git a/xorg-server/mi/mispans.c b/xorg-server/mi/mispans.c index 5504341c4..7b332ee34 100644 --- a/xorg-server/mi/mispans.c +++ b/xorg-server/mi/mispans.c @@ -1,529 +1,529 @@ -/*********************************************************** - -Copyright 1989, 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. - - -Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 "misc.h" -#include "pixmapstr.h" -#include "gcstruct.h" -#include "mispans.h" - -/* - -These routines maintain lists of Spans, in order to implement the -``touch-each-pixel-once'' rules of wide lines and arcs. - -Written by Joel McCormack, Summer 1989. - -*/ - - -void miInitSpanGroup(SpanGroup *spanGroup) -{ - spanGroup->size = 0; - spanGroup->count = 0; - spanGroup->group = NULL; - spanGroup->ymin = MAXSHORT; - spanGroup->ymax = MINSHORT; -} /* InitSpanGroup */ - -#define YMIN(spans) (spans->points[0].y) -#define YMAX(spans) (spans->points[spans->count-1].y) - -static void miSubtractSpans (SpanGroup *spanGroup, Spans *sub) -{ - int i, subCount, spansCount; - int ymin, ymax, xmin, xmax; - Spans *spans; - DDXPointPtr subPt, spansPt; - int *subWid, *spansWid; - int extra; - - ymin = YMIN(sub); - ymax = YMAX(sub); - spans = spanGroup->group; - for (i = spanGroup->count; i; i--, spans++) { - if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) { - subCount = sub->count; - subPt = sub->points; - subWid = sub->widths; - spansCount = spans->count; - spansPt = spans->points; - spansWid = spans->widths; - extra = 0; - for (;;) - { - while (spansCount && spansPt->y < subPt->y) - { - spansPt++; spansWid++; spansCount--; - } - if (!spansCount) - break; - while (subCount && subPt->y < spansPt->y) - { - subPt++; subWid++; subCount--; - } - if (!subCount) - break; - if (subPt->y == spansPt->y) - { - xmin = subPt->x; - xmax = xmin + *subWid; - if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax) - { - ; - } - else if (xmin <= spansPt->x) - { - if (xmax >= spansPt->x + *spansWid) - { - memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1)); - memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1)); - spansPt--; - spansWid--; - spans->count--; - extra++; - } - else - { - *spansWid = *spansWid - (xmax - spansPt->x); - spansPt->x = xmax; - } - } - else - { - if (xmax >= spansPt->x + *spansWid) - { - *spansWid = xmin - spansPt->x; - } - else - { - if (!extra) { - DDXPointPtr newPt; - int *newwid; - -#define EXTRA 8 - newPt = (DDXPointPtr) xrealloc (spans->points, (spans->count + EXTRA) * sizeof (DDXPointRec)); - if (!newPt) - break; - spansPt = newPt + (spansPt - spans->points); - spans->points = newPt; - newwid = (int *) xrealloc (spans->widths, (spans->count + EXTRA) * sizeof (int)); - if (!newwid) - break; - spansWid = newwid + (spansWid - spans->widths); - spans->widths = newwid; - extra = EXTRA; - } - memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount)); - memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount)); - spans->count++; - extra--; - *spansWid = xmin - spansPt->x; - spansWid++; - spansPt++; - *spansWid = *spansWid - (xmax - spansPt->x); - spansPt->x = xmax; - } - } - } - spansPt++; spansWid++; spansCount--; - } - } - } -} - -void miAppendSpans(SpanGroup *spanGroup, SpanGroup *otherGroup, Spans *spans) -{ - int ymin, ymax; - int spansCount; - - spansCount = spans->count; - if (spansCount > 0) { - if (spanGroup->size == spanGroup->count) { - spanGroup->size = (spanGroup->size + 8) * 2; - spanGroup->group = (Spans *) - xrealloc(spanGroup->group, sizeof(Spans) * spanGroup->size); - } - - spanGroup->group[spanGroup->count] = *spans; - (spanGroup->count)++; - ymin = spans->points[0].y; - if (ymin < spanGroup->ymin) spanGroup->ymin = ymin; - ymax = spans->points[spansCount - 1].y; - if (ymax > spanGroup->ymax) spanGroup->ymax = ymax; - if (otherGroup && - otherGroup->ymin < ymax && - ymin < otherGroup->ymax) - { - miSubtractSpans (otherGroup, spans); - } - } - else - { - xfree (spans->points); - xfree (spans->widths); - } -} /* AppendSpans */ - -void miFreeSpanGroup(SpanGroup *spanGroup) -{ - if (spanGroup->group != NULL) xfree(spanGroup->group); -} - -static void QuickSortSpansX( - DDXPointRec points[], - int widths[], - int numSpans ) -{ - int x; - int i, j, m; - DDXPointPtr r; - -/* Always called with numSpans > 1 */ -/* Sorts only by x, as all y should be the same */ - -#define ExchangeSpans(a, b) \ -{ \ - DDXPointRec tpt; \ - int tw; \ - \ - tpt = points[a]; points[a] = points[b]; points[b] = tpt; \ - tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ -} - - do { - if (numSpans < 9) { - /* Do insertion sort */ - int xprev; - - xprev = points[0].x; - i = 1; - do { /* while i != numSpans */ - x = points[i].x; - if (xprev > x) { - /* points[i] is out of order. Move into proper location. */ - DDXPointRec tpt; - int tw, k; - - for (j = 0; x >= points[j].x; j++) {} - tpt = points[i]; - tw = widths[i]; - for (k = i; k != j; k--) { - points[k] = points[k-1]; - widths[k] = widths[k-1]; - } - points[j] = tpt; - widths[j] = tw; - x = points[i].x; - } /* if out of order */ - xprev = x; - i++; - } while (i != numSpans); - return; - } - - /* Choose partition element, stick in location 0 */ - m = numSpans / 2; - if (points[m].x > points[0].x) ExchangeSpans(m, 0); - if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1); - if (points[m].x > points[0].x) ExchangeSpans(m, 0); - x = points[0].x; - - /* Partition array */ - i = 0; - j = numSpans; - do { - r = &(points[i]); - do { - r++; - i++; - } while (i != numSpans && r->x < x); - r = &(points[j]); - do { - r--; - j--; - } while (x < r->x); - if (i < j) ExchangeSpans(i, j); - } while (i < j); - - /* Move partition element back to middle */ - ExchangeSpans(0, j); - - /* Recurse */ - if (numSpans-j-1 > 1) - QuickSortSpansX(&points[j+1], &widths[j+1], numSpans-j-1); - numSpans = j; - } while (numSpans > 1); -} /* QuickSortSpans */ - - -static int UniquifySpansX( - Spans *spans, - DDXPointRec *newPoints, - int *newWidths ) -{ - int newx1, newx2, oldpt, i, y; - DDXPointRec *oldPoints; - int *oldWidths; - int *startNewWidths; - -/* Always called with numSpans > 1 */ -/* Uniquify the spans, and stash them into newPoints and newWidths. Return the - number of unique spans. */ - - - startNewWidths = newWidths; - - oldPoints = spans->points; - oldWidths = spans->widths; - - y = oldPoints->y; - newx1 = oldPoints->x; - newx2 = newx1 + *oldWidths; - - for (i = spans->count-1; i != 0; i--) { - oldPoints++; - oldWidths++; - oldpt = oldPoints->x; - if (oldpt > newx2) { - /* Write current span, start a new one */ - newPoints->x = newx1; - newPoints->y = y; - *newWidths = newx2 - newx1; - newPoints++; - newWidths++; - newx1 = oldpt; - newx2 = oldpt + *oldWidths; - } else { - /* extend current span, if old extends beyond new */ - oldpt = oldpt + *oldWidths; - if (oldpt > newx2) newx2 = oldpt; - } - } /* for */ - - /* Write final span */ - newPoints->x = newx1; - *newWidths = newx2 - newx1; - newPoints->y = y; - - return (newWidths - startNewWidths) + 1; -} /* UniquifySpansX */ - -static void -miDisposeSpanGroup (SpanGroup *spanGroup) -{ - int i; - Spans *spans; - - for (i = 0; i < spanGroup->count; i++) - { - spans = spanGroup->group + i; - xfree (spans->points); - xfree (spans->widths); - } -} - -void miFillUniqueSpanGroup(DrawablePtr pDraw, GCPtr pGC, SpanGroup *spanGroup) -{ - int i; - Spans *spans; - Spans *yspans; - int *ysizes; - int ymin, ylength; - - /* Outgoing spans for one big call to FillSpans */ - DDXPointPtr points; - int *widths; - int count; - - if (spanGroup->count == 0) return; - - if (spanGroup->count == 1) { - /* Already should be sorted, unique */ - spans = spanGroup->group; - (*pGC->ops->FillSpans) - (pDraw, pGC, spans->count, spans->points, spans->widths, TRUE); - xfree(spans->points); - xfree(spans->widths); - } - else - { - /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */ - /* This seems to be the fastest thing to do. I've tried sorting on - both x and y at the same time rather than creating into all those - y buckets, but it was somewhat slower. */ - - ymin = spanGroup->ymin; - ylength = spanGroup->ymax - ymin + 1; - - /* Allocate Spans for y buckets */ - yspans = xalloc(ylength * sizeof(Spans)); - ysizes = xalloc(ylength * sizeof (int)); - - if (!yspans || !ysizes) - { - if (yspans) - xfree (yspans); - if (ysizes) - xfree (ysizes); - miDisposeSpanGroup (spanGroup); - return; - } - - for (i = 0; i != ylength; i++) { - ysizes[i] = 0; - yspans[i].count = 0; - yspans[i].points = NULL; - yspans[i].widths = NULL; - } - - /* Go through every single span and put it into the correct bucket */ - count = 0; - for (i = 0, spans = spanGroup->group; - i != spanGroup->count; - i++, spans++) { - int index; - int j; - - for (j = 0, points = spans->points, widths = spans->widths; - j != spans->count; - j++, points++, widths++) { - index = points->y - ymin; - if (index >= 0 && index < ylength) { - Spans *newspans = &(yspans[index]); - if (newspans->count == ysizes[index]) { - DDXPointPtr newpoints; - int *newwidths; - ysizes[index] = (ysizes[index] + 8) * 2; - newpoints = (DDXPointPtr) xrealloc( - newspans->points, - ysizes[index] * sizeof(DDXPointRec)); - newwidths = (int *) xrealloc( - newspans->widths, - ysizes[index] * sizeof(int)); - if (!newpoints || !newwidths) - { - int i; - - for (i = 0; i < ylength; i++) - { - xfree (yspans[i].points); - xfree (yspans[i].widths); - } - xfree (yspans); - xfree (ysizes); - miDisposeSpanGroup (spanGroup); - return; - } - newspans->points = newpoints; - newspans->widths = newwidths; - } - newspans->points[newspans->count] = *points; - newspans->widths[newspans->count] = *widths; - (newspans->count)++; - } /* if y value of span in range */ - } /* for j through spans */ - count += spans->count; - xfree(spans->points); - spans->points = NULL; - xfree(spans->widths); - spans->widths = NULL; - } /* for i thorough Spans */ - - /* Now sort by x and uniquify each bucket into the final array */ - points = xalloc(count * sizeof(DDXPointRec)); - widths = xalloc(count * sizeof(int)); - if (!points || !widths) - { - int i; - - for (i = 0; i < ylength; i++) - { - xfree (yspans[i].points); - xfree (yspans[i].widths); - } - xfree (yspans); - xfree (ysizes); - if (points) - xfree (points); - if (widths) - xfree (widths); - return; - } - count = 0; - for (i = 0; i != ylength; i++) { - int ycount = yspans[i].count; - if (ycount > 0) { - if (ycount > 1) { - QuickSortSpansX(yspans[i].points, yspans[i].widths, ycount); - count += UniquifySpansX - (&(yspans[i]), &(points[count]), &(widths[count])); - } else { - points[count] = yspans[i].points[0]; - widths[count] = yspans[i].widths[0]; - count++; - } - xfree(yspans[i].points); - xfree(yspans[i].widths); - } - } - - (*pGC->ops->FillSpans) (pDraw, pGC, count, points, widths, TRUE); - xfree(points); - xfree(widths); - xfree(yspans); - xfree(ysizes); /* use (DE)xalloc for these? */ - } - - spanGroup->count = 0; - spanGroup->ymin = MAXSHORT; - spanGroup->ymax = MINSHORT; -} +/***********************************************************
+
+Copyright 1989, 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.
+
+
+Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 "misc.h"
+#include "pixmapstr.h"
+#include "gcstruct.h"
+#include "mispans.h"
+
+/*
+
+These routines maintain lists of Spans, in order to implement the
+``touch-each-pixel-once'' rules of wide lines and arcs.
+
+Written by Joel McCormack, Summer 1989.
+
+*/
+
+
+void miInitSpanGroup(SpanGroup *spanGroup)
+{
+ spanGroup->size = 0;
+ spanGroup->count = 0;
+ spanGroup->group = NULL;
+ spanGroup->ymin = MAXSHORT;
+ spanGroup->ymax = MINSHORT;
+} /* InitSpanGroup */
+
+#define YMIN(spans) (spans->points[0].y)
+#define YMAX(spans) (spans->points[spans->count-1].y)
+
+static void miSubtractSpans (SpanGroup *spanGroup, Spans *sub)
+{
+ int i, subCount, spansCount;
+ int ymin, ymax, xmin, xmax;
+ Spans *spans;
+ DDXPointPtr subPt, spansPt;
+ int *subWid, *spansWid;
+ int extra;
+
+ ymin = YMIN(sub);
+ ymax = YMAX(sub);
+ spans = spanGroup->group;
+ for (i = spanGroup->count; i; i--, spans++) {
+ if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) {
+ subCount = sub->count;
+ subPt = sub->points;
+ subWid = sub->widths;
+ spansCount = spans->count;
+ spansPt = spans->points;
+ spansWid = spans->widths;
+ extra = 0;
+ for (;;)
+ {
+ while (spansCount && spansPt->y < subPt->y)
+ {
+ spansPt++; spansWid++; spansCount--;
+ }
+ if (!spansCount)
+ break;
+ while (subCount && subPt->y < spansPt->y)
+ {
+ subPt++; subWid++; subCount--;
+ }
+ if (!subCount)
+ break;
+ if (subPt->y == spansPt->y)
+ {
+ xmin = subPt->x;
+ xmax = xmin + *subWid;
+ if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax)
+ {
+ ;
+ }
+ else if (xmin <= spansPt->x)
+ {
+ if (xmax >= spansPt->x + *spansWid)
+ {
+ memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1));
+ memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1));
+ spansPt--;
+ spansWid--;
+ spans->count--;
+ extra++;
+ }
+ else
+ {
+ *spansWid = *spansWid - (xmax - spansPt->x);
+ spansPt->x = xmax;
+ }
+ }
+ else
+ {
+ if (xmax >= spansPt->x + *spansWid)
+ {
+ *spansWid = xmin - spansPt->x;
+ }
+ else
+ {
+ if (!extra) {
+ DDXPointPtr newPt;
+ int *newwid;
+
+#define EXTRA 8
+ newPt = (DDXPointPtr) realloc(spans->points, (spans->count + EXTRA) * sizeof (DDXPointRec));
+ if (!newPt)
+ break;
+ spansPt = newPt + (spansPt - spans->points);
+ spans->points = newPt;
+ newwid = (int *) realloc(spans->widths, (spans->count + EXTRA) * sizeof (int));
+ if (!newwid)
+ break;
+ spansWid = newwid + (spansWid - spans->widths);
+ spans->widths = newwid;
+ extra = EXTRA;
+ }
+ memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount));
+ memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount));
+ spans->count++;
+ extra--;
+ *spansWid = xmin - spansPt->x;
+ spansWid++;
+ spansPt++;
+ *spansWid = *spansWid - (xmax - spansPt->x);
+ spansPt->x = xmax;
+ }
+ }
+ }
+ spansPt++; spansWid++; spansCount--;
+ }
+ }
+ }
+}
+
+void miAppendSpans(SpanGroup *spanGroup, SpanGroup *otherGroup, Spans *spans)
+{
+ int ymin, ymax;
+ int spansCount;
+
+ spansCount = spans->count;
+ if (spansCount > 0) {
+ if (spanGroup->size == spanGroup->count) {
+ spanGroup->size = (spanGroup->size + 8) * 2;
+ spanGroup->group = (Spans *)
+ realloc(spanGroup->group, sizeof(Spans) * spanGroup->size);
+ }
+
+ spanGroup->group[spanGroup->count] = *spans;
+ (spanGroup->count)++;
+ ymin = spans->points[0].y;
+ if (ymin < spanGroup->ymin) spanGroup->ymin = ymin;
+ ymax = spans->points[spansCount - 1].y;
+ if (ymax > spanGroup->ymax) spanGroup->ymax = ymax;
+ if (otherGroup &&
+ otherGroup->ymin < ymax &&
+ ymin < otherGroup->ymax)
+ {
+ miSubtractSpans (otherGroup, spans);
+ }
+ }
+ else
+ {
+ free(spans->points);
+ free(spans->widths);
+ }
+} /* AppendSpans */
+
+void miFreeSpanGroup(SpanGroup *spanGroup)
+{
+ if (spanGroup->group != NULL) free(spanGroup->group);
+}
+
+static void QuickSortSpansX(
+ DDXPointRec points[],
+ int widths[],
+ int numSpans )
+{
+ int x;
+ int i, j, m;
+ DDXPointPtr r;
+
+/* Always called with numSpans > 1 */
+/* Sorts only by x, as all y should be the same */
+
+#define ExchangeSpans(a, b) \
+{ \
+ DDXPointRec tpt; \
+ int tw; \
+ \
+ tpt = points[a]; points[a] = points[b]; points[b] = tpt; \
+ tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
+}
+
+ do {
+ if (numSpans < 9) {
+ /* Do insertion sort */
+ int xprev;
+
+ xprev = points[0].x;
+ i = 1;
+ do { /* while i != numSpans */
+ x = points[i].x;
+ if (xprev > x) {
+ /* points[i] is out of order. Move into proper location. */
+ DDXPointRec tpt;
+ int tw, k;
+
+ for (j = 0; x >= points[j].x; j++) {}
+ tpt = points[i];
+ tw = widths[i];
+ for (k = i; k != j; k--) {
+ points[k] = points[k-1];
+ widths[k] = widths[k-1];
+ }
+ points[j] = tpt;
+ widths[j] = tw;
+ x = points[i].x;
+ } /* if out of order */
+ xprev = x;
+ i++;
+ } while (i != numSpans);
+ return;
+ }
+
+ /* Choose partition element, stick in location 0 */
+ m = numSpans / 2;
+ if (points[m].x > points[0].x) ExchangeSpans(m, 0);
+ if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1);
+ if (points[m].x > points[0].x) ExchangeSpans(m, 0);
+ x = points[0].x;
+
+ /* Partition array */
+ i = 0;
+ j = numSpans;
+ do {
+ r = &(points[i]);
+ do {
+ r++;
+ i++;
+ } while (i != numSpans && r->x < x);
+ r = &(points[j]);
+ do {
+ r--;
+ j--;
+ } while (x < r->x);
+ if (i < j) ExchangeSpans(i, j);
+ } while (i < j);
+
+ /* Move partition element back to middle */
+ ExchangeSpans(0, j);
+
+ /* Recurse */
+ if (numSpans-j-1 > 1)
+ QuickSortSpansX(&points[j+1], &widths[j+1], numSpans-j-1);
+ numSpans = j;
+ } while (numSpans > 1);
+} /* QuickSortSpans */
+
+
+static int UniquifySpansX(
+ Spans *spans,
+ DDXPointRec *newPoints,
+ int *newWidths )
+{
+ int newx1, newx2, oldpt, i, y;
+ DDXPointRec *oldPoints;
+ int *oldWidths;
+ int *startNewWidths;
+
+/* Always called with numSpans > 1 */
+/* Uniquify the spans, and stash them into newPoints and newWidths. Return the
+ number of unique spans. */
+
+
+ startNewWidths = newWidths;
+
+ oldPoints = spans->points;
+ oldWidths = spans->widths;
+
+ y = oldPoints->y;
+ newx1 = oldPoints->x;
+ newx2 = newx1 + *oldWidths;
+
+ for (i = spans->count-1; i != 0; i--) {
+ oldPoints++;
+ oldWidths++;
+ oldpt = oldPoints->x;
+ if (oldpt > newx2) {
+ /* Write current span, start a new one */
+ newPoints->x = newx1;
+ newPoints->y = y;
+ *newWidths = newx2 - newx1;
+ newPoints++;
+ newWidths++;
+ newx1 = oldpt;
+ newx2 = oldpt + *oldWidths;
+ } else {
+ /* extend current span, if old extends beyond new */
+ oldpt = oldpt + *oldWidths;
+ if (oldpt > newx2) newx2 = oldpt;
+ }
+ } /* for */
+
+ /* Write final span */
+ newPoints->x = newx1;
+ *newWidths = newx2 - newx1;
+ newPoints->y = y;
+
+ return (newWidths - startNewWidths) + 1;
+} /* UniquifySpansX */
+
+static void
+miDisposeSpanGroup (SpanGroup *spanGroup)
+{
+ int i;
+ Spans *spans;
+
+ for (i = 0; i < spanGroup->count; i++)
+ {
+ spans = spanGroup->group + i;
+ free(spans->points);
+ free(spans->widths);
+ }
+}
+
+void miFillUniqueSpanGroup(DrawablePtr pDraw, GCPtr pGC, SpanGroup *spanGroup)
+{
+ int i;
+ Spans *spans;
+ Spans *yspans;
+ int *ysizes;
+ int ymin, ylength;
+
+ /* Outgoing spans for one big call to FillSpans */
+ DDXPointPtr points;
+ int *widths;
+ int count;
+
+ if (spanGroup->count == 0) return;
+
+ if (spanGroup->count == 1) {
+ /* Already should be sorted, unique */
+ spans = spanGroup->group;
+ (*pGC->ops->FillSpans)
+ (pDraw, pGC, spans->count, spans->points, spans->widths, TRUE);
+ free(spans->points);
+ free(spans->widths);
+ }
+ else
+ {
+ /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */
+ /* This seems to be the fastest thing to do. I've tried sorting on
+ both x and y at the same time rather than creating into all those
+ y buckets, but it was somewhat slower. */
+
+ ymin = spanGroup->ymin;
+ ylength = spanGroup->ymax - ymin + 1;
+
+ /* Allocate Spans for y buckets */
+ yspans = malloc(ylength * sizeof(Spans));
+ ysizes = malloc(ylength * sizeof (int));
+
+ if (!yspans || !ysizes)
+ {
+ if (yspans)
+ free(yspans);
+ if (ysizes)
+ free(ysizes);
+ miDisposeSpanGroup (spanGroup);
+ return;
+ }
+
+ for (i = 0; i != ylength; i++) {
+ ysizes[i] = 0;
+ yspans[i].count = 0;
+ yspans[i].points = NULL;
+ yspans[i].widths = NULL;
+ }
+
+ /* Go through every single span and put it into the correct bucket */
+ count = 0;
+ for (i = 0, spans = spanGroup->group;
+ i != spanGroup->count;
+ i++, spans++) {
+ int index;
+ int j;
+
+ for (j = 0, points = spans->points, widths = spans->widths;
+ j != spans->count;
+ j++, points++, widths++) {
+ index = points->y - ymin;
+ if (index >= 0 && index < ylength) {
+ Spans *newspans = &(yspans[index]);
+ if (newspans->count == ysizes[index]) {
+ DDXPointPtr newpoints;
+ int *newwidths;
+ ysizes[index] = (ysizes[index] + 8) * 2;
+ newpoints = (DDXPointPtr) realloc(
+ newspans->points,
+ ysizes[index] * sizeof(DDXPointRec));
+ newwidths = (int *) realloc(
+ newspans->widths,
+ ysizes[index] * sizeof(int));
+ if (!newpoints || !newwidths)
+ {
+ int i;
+
+ for (i = 0; i < ylength; i++)
+ {
+ free(yspans[i].points);
+ free(yspans[i].widths);
+ }
+ free(yspans);
+ free(ysizes);
+ miDisposeSpanGroup (spanGroup);
+ return;
+ }
+ newspans->points = newpoints;
+ newspans->widths = newwidths;
+ }
+ newspans->points[newspans->count] = *points;
+ newspans->widths[newspans->count] = *widths;
+ (newspans->count)++;
+ } /* if y value of span in range */
+ } /* for j through spans */
+ count += spans->count;
+ free(spans->points);
+ spans->points = NULL;
+ free(spans->widths);
+ spans->widths = NULL;
+ } /* for i thorough Spans */
+
+ /* Now sort by x and uniquify each bucket into the final array */
+ points = malloc(count * sizeof(DDXPointRec));
+ widths = malloc(count * sizeof(int));
+ if (!points || !widths)
+ {
+ int i;
+
+ for (i = 0; i < ylength; i++)
+ {
+ free(yspans[i].points);
+ free(yspans[i].widths);
+ }
+ free(yspans);
+ free(ysizes);
+ if (points)
+ free(points);
+ if (widths)
+ free(widths);
+ return;
+ }
+ count = 0;
+ for (i = 0; i != ylength; i++) {
+ int ycount = yspans[i].count;
+ if (ycount > 0) {
+ if (ycount > 1) {
+ QuickSortSpansX(yspans[i].points, yspans[i].widths, ycount);
+ count += UniquifySpansX
+ (&(yspans[i]), &(points[count]), &(widths[count]));
+ } else {
+ points[count] = yspans[i].points[0];
+ widths[count] = yspans[i].widths[0];
+ count++;
+ }
+ free(yspans[i].points);
+ free(yspans[i].widths);
+ }
+ }
+
+ (*pGC->ops->FillSpans) (pDraw, pGC, count, points, widths, TRUE);
+ free(points);
+ free(widths);
+ free(yspans);
+ free(ysizes); /* use (DE)xalloc for these? */
+ }
+
+ spanGroup->count = 0;
+ spanGroup->ymin = MAXSHORT;
+ spanGroup->ymax = MINSHORT;
+}
diff --git a/xorg-server/mi/misprite.c b/xorg-server/mi/misprite.c index ac025e1ff..b0f7ecd39 100644 --- a/xorg-server/mi/misprite.c +++ b/xorg-server/mi/misprite.c @@ -1,1115 +1,1115 @@ -/* - * misprite.c - * - * machine independent software sprite routines - */ - -/* - -Copyright 1989, 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 <X11/X.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "pixmapstr.h" -#include "input.h" -#include "mi.h" -#include "cursorstr.h" -#include <X11/fonts/font.h> -#include "scrnintstr.h" -#include "colormapst.h" -#include "windowstr.h" -#include "gcstruct.h" -#include "mipointer.h" -#include "misprite.h" -#include "dixfontstr.h" -#include <X11/fonts/fontstruct.h> -#include "inputstr.h" -#include "damage.h" - -typedef struct { - CursorPtr pCursor; - int x; /* cursor hotspot */ - int y; - BoxRec saved; /* saved area from the screen */ - Bool isUp; /* cursor in frame buffer */ - Bool shouldBeUp; /* cursor should be displayed */ - WindowPtr pCacheWin; /* window the cursor last seen in */ - Bool isInCacheWin; - Bool checkPixels; /* check colormap collision */ - ScreenPtr pScreen; -} miCursorInfoRec, *miCursorInfoPtr; - -/* - * per screen information - */ - -typedef struct { - /* screen procedures */ - CloseScreenProcPtr CloseScreen; - GetImageProcPtr GetImage; - GetSpansProcPtr GetSpans; - SourceValidateProcPtr SourceValidate; - - /* window procedures */ - CopyWindowProcPtr CopyWindow; - - /* colormap procedures */ - InstallColormapProcPtr InstallColormap; - StoreColorsProcPtr StoreColors; - - /* os layer procedures */ - ScreenBlockHandlerProcPtr BlockHandler; - - /* device cursor procedures */ - DeviceCursorInitializeProcPtr DeviceCursorInitialize; - DeviceCursorCleanupProcPtr DeviceCursorCleanup; - - xColorItem colors[2]; - ColormapPtr pInstalledMap; - ColormapPtr pColormap; - VisualPtr pVisual; - miSpriteCursorFuncPtr funcs; - DamagePtr pDamage; /* damage tracking structure */ - Bool damageRegistered; -} miSpriteScreenRec, *miSpriteScreenPtr; - -#define SOURCE_COLOR 0 -#define MASK_COLOR 1 - -/* - * Overlap BoxPtr and Box elements - */ -#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ - (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ - ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) - -/* - * Overlap BoxPtr, origins, and rectangle - */ -#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ - BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) - -/* - * Overlap BoxPtr, origins and RectPtr - */ -#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ - ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ - (int)((pRect)->width), (int)((pRect)->height)) -/* - * Overlap BoxPtr and horizontal span - */ -#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) - -#define LINE_SORT(x1,y1,x2,y2) \ -{ int _t; \ - if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ - if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } - -#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ - BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) - - -#define SPRITE_DEBUG_ENABLE 0 -#if SPRITE_DEBUG_ENABLE -#define SPRITE_DEBUG(x) ErrorF x -#else -#define SPRITE_DEBUG(x) -#endif - -#define MISPRITE(dev) \ - ((!IsMaster(dev) && !dev->u.master) ? \ - (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \ - (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey)) - -static void -miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) -{ - if (pScreenPriv->damageRegistered) { - DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable), - pScreenPriv->pDamage); - pScreenPriv->damageRegistered = 0; - } -} - -static void -miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) -{ - if (!pScreenPriv->damageRegistered) { - pScreenPriv->damageRegistered = 1; - DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable), - pScreenPriv->pDamage); - } -} - -static void -miSpriteIsUp(miCursorInfoPtr pDevCursor) -{ - pDevCursor->isUp = TRUE; -} - -static void -miSpriteIsDown(miCursorInfoPtr pDevCursor) -{ - pDevCursor->isUp = FALSE; -} - -/* - * screen wrappers - */ - -static int miSpriteScreenKeyIndex; -static DevPrivateKey miSpriteScreenKey = &miSpriteScreenKeyIndex; -static int miSpriteDevPrivatesKeyIndex; -static DevPrivateKey miSpriteDevPrivatesKey = &miSpriteDevPrivatesKeyIndex; - -static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); -static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, - int w, int h, unsigned int format, - unsigned long planemask, char *pdstLine); -static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, - DDXPointPtr ppt, int *pwidth, int nspans, - char *pdstStart); -static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, - int width, int height); -static void miSpriteCopyWindow (WindowPtr pWindow, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc); -static void miSpriteBlockHandler(int i, pointer blockData, - pointer pTimeout, - pointer pReadMask); -static void miSpriteInstallColormap(ColormapPtr pMap); -static void miSpriteStoreColors(ColormapPtr pMap, int ndef, - xColorItem *pdef); - -static void miSpriteComputeSaved(DeviceIntPtr pDev, - ScreenPtr pScreen); - -static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, - ScreenPtr pScreen); - -#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \ - ((miSpriteScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \ - miSpriteScreenKey))->field) -#define SCREEN_EPILOGUE(pScreen, field)\ - ((pScreen)->field = miSprite##field) - -/* - * pointer-sprite method table - */ - -static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y); -static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y); - -miPointerSpriteFuncRec miSpritePointerFuncs = { - miSpriteRealizeCursor, - miSpriteUnrealizeCursor, - miSpriteSetCursor, - miSpriteMoveCursor, - miSpriteDeviceCursorInitialize, - miSpriteDeviceCursorCleanup, -}; - -/* - * other misc functions - */ - -static void miSpriteRemoveCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteRestoreCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); - -static void -miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) -{ - ScreenPtr pScreen = closure; - miSpriteScreenPtr pScreenPriv; - miCursorInfoPtr pCursorInfo; - DeviceIntPtr pDev; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - - if (pCursorInfo->isUp && - pCursorInfo->pScreen == pScreen && - miRectIn(pRegion, &pCursorInfo->saved) != rgnOUT) - { - SPRITE_DEBUG(("Damage remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } -} - -/* - * miSpriteInitialize -- called from device-dependent screen - * initialization proc after all of the function pointers have - * been stored in the screen structure. - */ - -Bool -miSpriteInitialize (ScreenPtr pScreen, - miSpriteCursorFuncPtr cursorFuncs, - miPointerScreenFuncPtr screenFuncs) -{ - miSpriteScreenPtr pScreenPriv; - VisualPtr pVisual; - - if (!DamageSetup (pScreen)) - return FALSE; - - pScreenPriv = xalloc (sizeof (miSpriteScreenRec)); - if (!pScreenPriv) - return FALSE; - - pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, - NULL, - DamageReportRawRegion, - TRUE, - pScreen, - pScreen); - - if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) - { - xfree (pScreenPriv); - return FALSE; - } - for (pVisual = pScreen->visuals; - pVisual->vid != pScreen->rootVisual; - pVisual++) - ; - pScreenPriv->pVisual = pVisual; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreenPriv->GetImage = pScreen->GetImage; - pScreenPriv->GetSpans = pScreen->GetSpans; - pScreenPriv->SourceValidate = pScreen->SourceValidate; - - pScreenPriv->CopyWindow = pScreen->CopyWindow; - - pScreenPriv->InstallColormap = pScreen->InstallColormap; - pScreenPriv->StoreColors = pScreen->StoreColors; - - pScreenPriv->BlockHandler = pScreen->BlockHandler; - - pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize; - pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup; - - pScreenPriv->pInstalledMap = NULL; - pScreenPriv->pColormap = NULL; - pScreenPriv->funcs = cursorFuncs; - pScreenPriv->colors[SOURCE_COLOR].red = 0; - pScreenPriv->colors[SOURCE_COLOR].green = 0; - pScreenPriv->colors[SOURCE_COLOR].blue = 0; - pScreenPriv->colors[MASK_COLOR].red = 0; - pScreenPriv->colors[MASK_COLOR].green = 0; - pScreenPriv->colors[MASK_COLOR].blue = 0; - pScreenPriv->damageRegistered = 0; - - dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv); - - pScreen->CloseScreen = miSpriteCloseScreen; - pScreen->GetImage = miSpriteGetImage; - pScreen->GetSpans = miSpriteGetSpans; - pScreen->SourceValidate = miSpriteSourceValidate; - - pScreen->CopyWindow = miSpriteCopyWindow; - pScreen->InstallColormap = miSpriteInstallColormap; - pScreen->StoreColors = miSpriteStoreColors; - - pScreen->BlockHandler = miSpriteBlockHandler; - - return TRUE; -} - -/* - * Screen wrappers - */ - -/* - * CloseScreen wrapper -- unwrap everything, free the private data - * and call the wrapped function - */ - -static Bool -miSpriteCloseScreen (int i, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->GetImage = pScreenPriv->GetImage; - pScreen->GetSpans = pScreenPriv->GetSpans; - pScreen->SourceValidate = pScreenPriv->SourceValidate; - pScreen->BlockHandler = pScreenPriv->BlockHandler; - pScreen->InstallColormap = pScreenPriv->InstallColormap; - pScreen->StoreColors = pScreenPriv->StoreColors; - - DamageDestroy (pScreenPriv->pDamage); - - xfree (pScreenPriv); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static void -miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, - unsigned int format, unsigned long planemask, - char *pdstLine) -{ - ScreenPtr pScreen = pDrawable->pScreen; - miSpriteScreenPtr pScreenPriv; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - - SCREEN_PROLOGUE (pScreen, GetImage); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey); - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, - sx, sy, w, h)) - { - SPRITE_DEBUG (("GetImage remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } - - (*pScreen->GetImage) (pDrawable, sx, sy, w, h, - format, planemask, pdstLine); - - SCREEN_EPILOGUE (pScreen, GetImage); -} - -static void -miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, - int *pwidth, int nspans, char *pdstStart) -{ - ScreenPtr pScreen = pDrawable->pScreen; - miSpriteScreenPtr pScreenPriv; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - - SCREEN_PROLOGUE (pScreen, GetSpans); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey); - - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - { - DDXPointPtr pts; - int *widths; - int nPts; - int xorg, - yorg; - - xorg = pDrawable->x; - yorg = pDrawable->y; - - for (pts = ppt, widths = pwidth, nPts = nspans; - nPts--; - pts++, widths++) - { - if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg, - pts->x+xorg,*widths)) - { - SPRITE_DEBUG (("GetSpans remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - break; - } - } - } - } - } - } - - (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); - - SCREEN_EPILOGUE (pScreen, GetSpans); -} - -static void -miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, - int height) -{ - ScreenPtr pScreen = pDrawable->pScreen; - miSpriteScreenPtr pScreenPriv; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - - SCREEN_PROLOGUE (pScreen, SourceValidate); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey); - - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, - x, y, width, height)) - { - SPRITE_DEBUG (("SourceValidate remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } - - if (pScreen->SourceValidate) - (*pScreen->SourceValidate) (pDrawable, x, y, width, height); - - SCREEN_EPILOGUE (pScreen, SourceValidate); -} - -static void -miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - miSpriteScreenPtr pScreenPriv; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - - SCREEN_PROLOGUE (pScreen, CopyWindow); - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - /* - * Damage will take care of destination check - */ - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - miRectIn(prgnSrc, &pCursorInfo->saved) != rgnOUT) - { - SPRITE_DEBUG (("CopyWindow remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - - (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); - SCREEN_EPILOGUE (pScreen, CopyWindow); -} - -static void -miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout, - pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[i]; - miSpriteScreenPtr pPriv; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - - pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - SCREEN_PROLOGUE(pScreen, BlockHandler); - - (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); - - SCREEN_EPILOGUE(pScreen, BlockHandler); - - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo && !pCursorInfo->isUp - && pCursorInfo->pScreen == pScreen - && pCursorInfo->shouldBeUp) - { - SPRITE_DEBUG (("BlockHandler restore\n")); - miSpriteSaveUnderCursor (pDev, pScreen); - } - } - } - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo && !pCursorInfo->isUp && - pCursorInfo->pScreen == pScreen && - pCursorInfo->shouldBeUp) - { - SPRITE_DEBUG (("BlockHandler restore\n")); - miSpriteRestoreCursor (pDev, pScreen); - } - } - } -} - -static void -miSpriteInstallColormap (ColormapPtr pMap) -{ - ScreenPtr pScreen = pMap->pScreen; - miSpriteScreenPtr pPriv; - - pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - SCREEN_PROLOGUE(pScreen, InstallColormap); - - (*pScreen->InstallColormap) (pMap); - - SCREEN_EPILOGUE(pScreen, InstallColormap); - - /* InstallColormap can be called before devices are initialized. */ - pPriv->pInstalledMap = pMap; - if (pPriv->pColormap != pMap) - { - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - pCursorInfo->checkPixels = TRUE; - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - miSpriteRemoveCursor(pDev, pScreen); - } - } - - } -} - -static void -miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) -{ - ScreenPtr pScreen = pMap->pScreen; - miSpriteScreenPtr pPriv; - int i; - int updated; - VisualPtr pVisual; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - - pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - SCREEN_PROLOGUE(pScreen, StoreColors); - - (*pScreen->StoreColors) (pMap, ndef, pdef); - - SCREEN_EPILOGUE(pScreen, StoreColors); - - if (pPriv->pColormap == pMap) - { - updated = 0; - pVisual = pMap->pVisual; - if (pVisual->class == DirectColor) - { - /* Direct color - match on any of the subfields */ - -#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) - -#define UpdateDAC(dev, plane,dac,mask) {\ - if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ - dev->colors[plane].dac = pdef[i].dac; \ - updated = 1; \ - } \ -} - -#define CheckDirect(dev, plane) \ - UpdateDAC(dev, plane,red,redMask) \ - UpdateDAC(dev, plane,green,greenMask) \ - UpdateDAC(dev, plane,blue,blueMask) - - for (i = 0; i < ndef; i++) - { - CheckDirect (pPriv, SOURCE_COLOR) - CheckDirect (pPriv, MASK_COLOR) - } - } - else - { - /* PseudoColor/GrayScale - match on exact pixel */ - for (i = 0; i < ndef; i++) - { - if (pdef[i].pixel == - pPriv->colors[SOURCE_COLOR].pixel) - { - pPriv->colors[SOURCE_COLOR] = pdef[i]; - if (++updated == 2) - break; - } - if (pdef[i].pixel == - pPriv->colors[MASK_COLOR].pixel) - { - pPriv->colors[MASK_COLOR] = pdef[i]; - if (++updated == 2) - break; - } - } - } - if (updated) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - pCursorInfo->checkPixels = TRUE; - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } -} - -static void -miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv = - dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - CursorPtr pCursor; - xColorItem *sourceColor, *maskColor; - - pCursor = pDevCursor->pCursor; - sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; - maskColor = &pScreenPriv->colors[MASK_COLOR]; - if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || - !(pCursor->foreRed == sourceColor->red && - pCursor->foreGreen == sourceColor->green && - pCursor->foreBlue == sourceColor->blue && - pCursor->backRed == maskColor->red && - pCursor->backGreen == maskColor->green && - pCursor->backBlue == maskColor->blue)) - { - pScreenPriv->pColormap = pScreenPriv->pInstalledMap; - sourceColor->red = pCursor->foreRed; - sourceColor->green = pCursor->foreGreen; - sourceColor->blue = pCursor->foreBlue; - FakeAllocColor (pScreenPriv->pColormap, sourceColor); - maskColor->red = pCursor->backRed; - maskColor->green = pCursor->backGreen; - maskColor->blue = pCursor->backBlue; - FakeAllocColor (pScreenPriv->pColormap, maskColor); - /* "free" the pixels right away, don't let this confuse you */ - FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); - FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); - } - - pDevCursor->checkPixels = FALSE; - -} - -/* - * miPointer interface routines - */ - -#define SPRITE_PAD 8 - -static Bool -miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - miSpriteScreenPtr pScreenPriv; - miCursorInfoPtr pCursorInfo; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - if (!IsMaster(pDev) && !pDev->u.master) - return FALSE; - - pCursorInfo = MISPRITE(pDev); - - if (pCursor == pCursorInfo->pCursor) - pCursorInfo->checkPixels = TRUE; - - return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); -} - -static Bool -miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - miSpriteScreenPtr pScreenPriv; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); -} - -static void -miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y) -{ - miSpriteScreenPtr pScreenPriv; - miCursorInfoPtr pPointer; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - - if (!IsMaster(pDev) && !pDev->u.master) - return; - - pPointer = MISPRITE(pDev); - - if (!pCursor) - { - pPointer->shouldBeUp = FALSE; - if (pPointer->isUp) - miSpriteRemoveCursor (pDev, pScreen); - pPointer->pCursor = 0; - return; - } - pPointer->shouldBeUp = TRUE; - if (pPointer->x == x && - pPointer->y == y && - pPointer->pCursor == pCursor && - !pPointer->checkPixels) - { - return; - } - pPointer->x = x; - pPointer->y = y; - pPointer->pCacheWin = NullWindow; - if (pPointer->checkPixels || pPointer->pCursor != pCursor) - { - pPointer->pCursor = pCursor; - miSpriteFindColors (pPointer, pScreen); - } - if (pPointer->isUp) { -#if 0 - /* FIXME: Disabled for MPX, should be rewritten */ - int sx, sy; - /* - * check to see if the old saved region - * encloses the new sprite, in which case we use - * the flicker-free MoveCursor primitive. - */ - sx = pointer->x - (int)pCursor->bits->xhot; - sy = pointer->y - (int)pCursor->bits->yhot; - if (sx + (int) pCursor->bits->width >= pointer->saved.x1 && - sx < pointer->saved.x2 && - sy + (int) pCursor->bits->height >= pointer->saved.y1 && - sy < pointer->saved.y2 && - (int) pCursor->bits->width + (2 * SPRITE_PAD) == - pointer->saved.x2 - pointer->saved.x1 && - (int) pCursor->bits->height + (2 * SPRITE_PAD) == - pointer->saved.y2 - pointer->saved.y1 - ) - { - DamageDrawInternal (pScreen, TRUE); - miSpriteIsDown(pCursorInfo); - if (!(sx >= pointer->saved.x1 && - sx + (int)pCursor->bits->width < pointer->saved.x2 - && sy >= pointer->saved.y1 && - sy + (int)pCursor->bits->height < - pointer->saved.y2)) - { - int oldx1, oldy1, dx, dy; - - oldx1 = pointer->saved.x1; - oldy1 = pointer->saved.y1; - dx = oldx1 - (sx - SPRITE_PAD); - dy = oldy1 - (sy - SPRITE_PAD); - pointer->saved.x1 -= dx; - pointer->saved.y1 -= dy; - pointer->saved.x2 -= dx; - pointer->saved.y2 -= dy; - (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, - pointer->saved.x1, - pointer->saved.y1, - pointer->saved.x2 - - pointer->saved.x1, - pointer->saved.y2 - - pointer->saved.y1, - dx, dy); - } - (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, - pointer->saved.x1, - pointer->saved.y1, - pointer->saved.x2 - - pointer->saved.x1, - pointer->saved.y2 - - pointer->saved.y1, - sx - pointer->saved.x1, - sy - pointer->saved.y1, - pointer->colors[SOURCE_COLOR].pixel, - pointer->colors[MASK_COLOR].pixel); - miSpriteIsUp(pCursorInfo); - DamageDrawInternal (pScreen, FALSE); - } - else -#endif - { - SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id)); - miSpriteRemoveCursor (pDev, pScreen); - } - } - - if (!pPointer->isUp && pPointer->pCursor) - { - SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id)); - miSpriteSaveUnderCursor(pDev, pScreen); - miSpriteRestoreCursor (pDev, pScreen); - } - -} - -static void -miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - miSpriteScreenPtr pScreenPriv; - CursorPtr pCursor; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - if (!IsMaster(pDev) && !pDev->u.master) - return; - - pCursor = MISPRITE(pDev)->pCursor; - - miSpriteSetCursor (pDev, pScreen, pCursor, x, y); -} - - -static Bool -miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - miCursorInfoPtr pCursorInfo; - int ret = FALSE; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - - pCursorInfo = xalloc(sizeof(miCursorInfoRec)); - if (!pCursorInfo) - return FALSE; - - pCursorInfo->pCursor = NULL; - pCursorInfo->x = 0; - pCursorInfo->y = 0; - pCursorInfo->isUp = FALSE; - pCursorInfo->shouldBeUp = FALSE; - pCursorInfo->pCacheWin = NullWindow; - pCursorInfo->isInCacheWin = FALSE; - pCursorInfo->checkPixels = TRUE; - pCursorInfo->pScreen = FALSE; - - ret = (*pScreenPriv->funcs->DeviceCursorInitialize)(pDev, pScreen); - if (!ret) - { - xfree(pCursorInfo); - pCursorInfo = NULL; - } - dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo); - return ret; -} - -static void -miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - if (DevHasCursor(pDev)) - { - miSpriteScreenPtr pScreenPriv; - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, - miSpriteScreenKey); - - (*pScreenPriv->funcs->DeviceCursorCleanup)(pDev, pScreen); - } -} - -/* - * undraw/draw cursor - */ - -static void -miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - miCursorInfoPtr pCursorInfo; - - - if (!IsMaster(pDev) && !pDev->u.master) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - pCursorInfo = MISPRITE(pDev); - - miSpriteIsDown(pCursorInfo); - pCursorInfo->pCacheWin = NullWindow; - miSpriteDisableDamage(pScreen, pScreenPriv); - if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDev, - pScreen, - pCursorInfo->saved.x1, - pCursorInfo->saved.y1, - pCursorInfo->saved.x2 - - pCursorInfo->saved.x1, - pCursorInfo->saved.y2 - - pCursorInfo->saved.y1)) - { - miSpriteIsUp(pCursorInfo); - } - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - -/* - * Called from the block handler, saves area under cursor - * before waiting for something to do. - */ - -static void -miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - int x, y; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (!IsMaster(pDev) && !pDev->u.master) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - pCursorInfo = MISPRITE(pDev); - - miSpriteComputeSaved (pDev, pScreen); - pCursor = pCursorInfo->pCursor; - - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - miSpriteDisableDamage(pScreen, pScreenPriv); - - (*pScreenPriv->funcs->SaveUnderCursor) (pDev, - pScreen, - pCursorInfo->saved.x1, - pCursorInfo->saved.y1, - pCursorInfo->saved.x2 - - pCursorInfo->saved.x1, - pCursorInfo->saved.y2 - - pCursorInfo->saved.y1); - SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - - -/* - * Called from the block handler, restores the cursor - * before waiting for something to do. - */ - -static void -miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - int x, y; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (!IsMaster(pDev) && !pDev->u.master) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - pCursorInfo = MISPRITE(pDev); - - miSpriteComputeSaved (pDev, pScreen); - pCursor = pCursorInfo->pCursor; - - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - miSpriteDisableDamage(pScreen, pScreenPriv); - SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); - if (pCursorInfo->checkPixels) - miSpriteFindColors (pCursorInfo, pScreen); - if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen, - pCursor, x, y, - pScreenPriv->colors[SOURCE_COLOR].pixel, - pScreenPriv->colors[MASK_COLOR].pixel)) - { - miSpriteIsUp(pCursorInfo); - pCursorInfo->pScreen = pScreen; - } - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - -/* - * compute the desired area of the screen to save - */ - -static void -miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - int x, y, w, h; - int wpad, hpad; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (!IsMaster(pDev) && !pDev->u.master) - return; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - pCursorInfo = MISPRITE(pDev); - - pCursor = pCursorInfo->pCursor; - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - w = pCursor->bits->width; - h = pCursor->bits->height; - wpad = SPRITE_PAD; - hpad = SPRITE_PAD; - pCursorInfo->saved.x1 = x - wpad; - pCursorInfo->saved.y1 = y - hpad; - pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; - pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; -} - +/*
+ * misprite.c
+ *
+ * machine independent software sprite routines
+ */
+
+/*
+
+Copyright 1989, 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 <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "pixmapstr.h"
+#include "input.h"
+#include "mi.h"
+#include "cursorstr.h"
+#include <X11/fonts/font.h>
+#include "scrnintstr.h"
+#include "colormapst.h"
+#include "windowstr.h"
+#include "gcstruct.h"
+#include "mipointer.h"
+#include "misprite.h"
+#include "dixfontstr.h"
+#include <X11/fonts/fontstruct.h>
+#include "inputstr.h"
+#include "damage.h"
+
+typedef struct {
+ CursorPtr pCursor;
+ int x; /* cursor hotspot */
+ int y;
+ BoxRec saved; /* saved area from the screen */
+ Bool isUp; /* cursor in frame buffer */
+ Bool shouldBeUp; /* cursor should be displayed */
+ WindowPtr pCacheWin; /* window the cursor last seen in */
+ Bool isInCacheWin;
+ Bool checkPixels; /* check colormap collision */
+ ScreenPtr pScreen;
+} miCursorInfoRec, *miCursorInfoPtr;
+
+/*
+ * per screen information
+ */
+
+typedef struct {
+ /* screen procedures */
+ CloseScreenProcPtr CloseScreen;
+ GetImageProcPtr GetImage;
+ GetSpansProcPtr GetSpans;
+ SourceValidateProcPtr SourceValidate;
+
+ /* window procedures */
+ CopyWindowProcPtr CopyWindow;
+
+ /* colormap procedures */
+ InstallColormapProcPtr InstallColormap;
+ StoreColorsProcPtr StoreColors;
+
+ /* os layer procedures */
+ ScreenBlockHandlerProcPtr BlockHandler;
+
+ /* device cursor procedures */
+ DeviceCursorInitializeProcPtr DeviceCursorInitialize;
+ DeviceCursorCleanupProcPtr DeviceCursorCleanup;
+
+ xColorItem colors[2];
+ ColormapPtr pInstalledMap;
+ ColormapPtr pColormap;
+ VisualPtr pVisual;
+ miSpriteCursorFuncPtr funcs;
+ DamagePtr pDamage; /* damage tracking structure */
+ Bool damageRegistered;
+} miSpriteScreenRec, *miSpriteScreenPtr;
+
+#define SOURCE_COLOR 0
+#define MASK_COLOR 1
+
+/*
+ * Overlap BoxPtr and Box elements
+ */
+#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
+ (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
+ ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
+
+/*
+ * Overlap BoxPtr, origins, and rectangle
+ */
+#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
+ BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
+
+/*
+ * Overlap BoxPtr, origins and RectPtr
+ */
+#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
+ ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
+ (int)((pRect)->width), (int)((pRect)->height))
+/*
+ * Overlap BoxPtr and horizontal span
+ */
+#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
+
+#define LINE_SORT(x1,y1,x2,y2) \
+{ int _t; \
+ if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
+ if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
+
+#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
+ BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
+
+
+#define SPRITE_DEBUG_ENABLE 0
+#if SPRITE_DEBUG_ENABLE
+#define SPRITE_DEBUG(x) ErrorF x
+#else
+#define SPRITE_DEBUG(x)
+#endif
+
+#define MISPRITE(dev) \
+ ((!IsMaster(dev) && !dev->u.master) ? \
+ (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
+ (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
+
+static void
+miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
+{
+ if (pScreenPriv->damageRegistered) {
+ DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
+ pScreenPriv->pDamage);
+ pScreenPriv->damageRegistered = 0;
+ }
+}
+
+static void
+miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
+{
+ if (!pScreenPriv->damageRegistered) {
+ pScreenPriv->damageRegistered = 1;
+ DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
+ pScreenPriv->pDamage);
+ }
+}
+
+static void
+miSpriteIsUp(miCursorInfoPtr pDevCursor)
+{
+ pDevCursor->isUp = TRUE;
+}
+
+static void
+miSpriteIsDown(miCursorInfoPtr pDevCursor)
+{
+ pDevCursor->isUp = FALSE;
+}
+
+/*
+ * screen wrappers
+ */
+
+static int miSpriteScreenKeyIndex;
+static DevPrivateKey miSpriteScreenKey = &miSpriteScreenKeyIndex;
+static int miSpriteDevPrivatesKeyIndex;
+static DevPrivateKey miSpriteDevPrivatesKey = &miSpriteDevPrivatesKeyIndex;
+
+static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen);
+static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
+ int w, int h, unsigned int format,
+ unsigned long planemask, char *pdstLine);
+static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
+ DDXPointPtr ppt, int *pwidth, int nspans,
+ char *pdstStart);
+static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
+ int width, int height);
+static void miSpriteCopyWindow (WindowPtr pWindow,
+ DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc);
+static void miSpriteBlockHandler(int i, pointer blockData,
+ pointer pTimeout,
+ pointer pReadMask);
+static void miSpriteInstallColormap(ColormapPtr pMap);
+static void miSpriteStoreColors(ColormapPtr pMap, int ndef,
+ xColorItem *pdef);
+
+static void miSpriteComputeSaved(DeviceIntPtr pDev,
+ ScreenPtr pScreen);
+
+static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
+ ScreenPtr pScreen);
+static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev,
+ ScreenPtr pScreen);
+
+#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
+ ((miSpriteScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \
+ miSpriteScreenKey))->field)
+#define SCREEN_EPILOGUE(pScreen, field)\
+ ((pScreen)->field = miSprite##field)
+
+/*
+ * pointer-sprite method table
+ */
+
+static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor);
+static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor);
+static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor, int x, int y);
+static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y);
+
+miPointerSpriteFuncRec miSpritePointerFuncs = {
+ miSpriteRealizeCursor,
+ miSpriteUnrealizeCursor,
+ miSpriteSetCursor,
+ miSpriteMoveCursor,
+ miSpriteDeviceCursorInitialize,
+ miSpriteDeviceCursorCleanup,
+};
+
+/*
+ * other misc functions
+ */
+
+static void miSpriteRemoveCursor(DeviceIntPtr pDev,
+ ScreenPtr pScreen);
+static void miSpriteSaveUnderCursor(DeviceIntPtr pDev,
+ ScreenPtr pScreen);
+static void miSpriteRestoreCursor(DeviceIntPtr pDev,
+ ScreenPtr pScreen);
+
+static void
+miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+ ScreenPtr pScreen = closure;
+ miSpriteScreenPtr pScreenPriv;
+ miCursorInfoPtr pCursorInfo;
+ DeviceIntPtr pDev;
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+
+ for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+
+ if (pCursorInfo->isUp &&
+ pCursorInfo->pScreen == pScreen &&
+ miRectIn(pRegion, &pCursorInfo->saved) != rgnOUT)
+ {
+ SPRITE_DEBUG(("Damage remove\n"));
+ miSpriteRemoveCursor (pDev, pScreen);
+ }
+ }
+ }
+}
+
+/*
+ * miSpriteInitialize -- called from device-dependent screen
+ * initialization proc after all of the function pointers have
+ * been stored in the screen structure.
+ */
+
+Bool
+miSpriteInitialize (ScreenPtr pScreen,
+ miSpriteCursorFuncPtr cursorFuncs,
+ miPointerScreenFuncPtr screenFuncs)
+{
+ miSpriteScreenPtr pScreenPriv;
+ VisualPtr pVisual;
+
+ if (!DamageSetup (pScreen))
+ return FALSE;
+
+ pScreenPriv = malloc(sizeof (miSpriteScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+
+ pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
+ NULL,
+ DamageReportRawRegion,
+ TRUE,
+ pScreen,
+ pScreen);
+
+ if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
+ {
+ free(pScreenPriv);
+ return FALSE;
+ }
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != pScreen->rootVisual;
+ pVisual++)
+ ;
+ pScreenPriv->pVisual = pVisual;
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreenPriv->GetImage = pScreen->GetImage;
+ pScreenPriv->GetSpans = pScreen->GetSpans;
+ pScreenPriv->SourceValidate = pScreen->SourceValidate;
+
+ pScreenPriv->CopyWindow = pScreen->CopyWindow;
+
+ pScreenPriv->InstallColormap = pScreen->InstallColormap;
+ pScreenPriv->StoreColors = pScreen->StoreColors;
+
+ pScreenPriv->BlockHandler = pScreen->BlockHandler;
+
+ pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize;
+ pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup;
+
+ pScreenPriv->pInstalledMap = NULL;
+ pScreenPriv->pColormap = NULL;
+ pScreenPriv->funcs = cursorFuncs;
+ pScreenPriv->colors[SOURCE_COLOR].red = 0;
+ pScreenPriv->colors[SOURCE_COLOR].green = 0;
+ pScreenPriv->colors[SOURCE_COLOR].blue = 0;
+ pScreenPriv->colors[MASK_COLOR].red = 0;
+ pScreenPriv->colors[MASK_COLOR].green = 0;
+ pScreenPriv->colors[MASK_COLOR].blue = 0;
+ pScreenPriv->damageRegistered = 0;
+
+ dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv);
+
+ pScreen->CloseScreen = miSpriteCloseScreen;
+ pScreen->GetImage = miSpriteGetImage;
+ pScreen->GetSpans = miSpriteGetSpans;
+ pScreen->SourceValidate = miSpriteSourceValidate;
+
+ pScreen->CopyWindow = miSpriteCopyWindow;
+ pScreen->InstallColormap = miSpriteInstallColormap;
+ pScreen->StoreColors = miSpriteStoreColors;
+
+ pScreen->BlockHandler = miSpriteBlockHandler;
+
+ return TRUE;
+}
+
+/*
+ * Screen wrappers
+ */
+
+/*
+ * CloseScreen wrapper -- unwrap everything, free the private data
+ * and call the wrapped function
+ */
+
+static Bool
+miSpriteCloseScreen (int i, ScreenPtr pScreen)
+{
+ miSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->GetImage = pScreenPriv->GetImage;
+ pScreen->GetSpans = pScreenPriv->GetSpans;
+ pScreen->SourceValidate = pScreenPriv->SourceValidate;
+ pScreen->BlockHandler = pScreenPriv->BlockHandler;
+ pScreen->InstallColormap = pScreenPriv->InstallColormap;
+ pScreen->StoreColors = pScreenPriv->StoreColors;
+
+ DamageDestroy (pScreenPriv->pDamage);
+
+ free(pScreenPriv);
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+static void
+miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
+ unsigned int format, unsigned long planemask,
+ char *pdstLine)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ miSpriteScreenPtr pScreenPriv;
+ DeviceIntPtr pDev;
+ miCursorInfoPtr pCursorInfo;
+
+ SCREEN_PROLOGUE (pScreen, GetImage);
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey);
+ for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+ if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
+ ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y,
+ sx, sy, w, h))
+ {
+ SPRITE_DEBUG (("GetImage remove\n"));
+ miSpriteRemoveCursor (pDev, pScreen);
+ }
+ }
+ }
+ }
+
+ (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
+ format, planemask, pdstLine);
+
+ SCREEN_EPILOGUE (pScreen, GetImage);
+}
+
+static void
+miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
+ int *pwidth, int nspans, char *pdstStart)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ miSpriteScreenPtr pScreenPriv;
+ DeviceIntPtr pDev;
+ miCursorInfoPtr pCursorInfo;
+
+ SCREEN_PROLOGUE (pScreen, GetSpans);
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey);
+
+ for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+
+ if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
+ {
+ DDXPointPtr pts;
+ int *widths;
+ int nPts;
+ int xorg,
+ yorg;
+
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ for (pts = ppt, widths = pwidth, nPts = nspans;
+ nPts--;
+ pts++, widths++)
+ {
+ if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
+ pts->x+xorg,*widths))
+ {
+ SPRITE_DEBUG (("GetSpans remove\n"));
+ miSpriteRemoveCursor (pDev, pScreen);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+
+ SCREEN_EPILOGUE (pScreen, GetSpans);
+}
+
+static void
+miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
+ int height)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ miSpriteScreenPtr pScreenPriv;
+ DeviceIntPtr pDev;
+ miCursorInfoPtr pCursorInfo;
+
+ SCREEN_PROLOGUE (pScreen, SourceValidate);
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey);
+
+ for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+ if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
+ ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
+ x, y, width, height))
+ {
+ SPRITE_DEBUG (("SourceValidate remove\n"));
+ miSpriteRemoveCursor (pDev, pScreen);
+ }
+ }
+ }
+ }
+
+ if (pScreen->SourceValidate)
+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
+
+ SCREEN_EPILOGUE (pScreen, SourceValidate);
+}
+
+static void
+miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ miSpriteScreenPtr pScreenPriv;
+ DeviceIntPtr pDev;
+ miCursorInfoPtr pCursorInfo;
+
+ SCREEN_PROLOGUE (pScreen, CopyWindow);
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+
+ for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+ /*
+ * Damage will take care of destination check
+ */
+ if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
+ miRectIn(prgnSrc, &pCursorInfo->saved) != rgnOUT)
+ {
+ SPRITE_DEBUG (("CopyWindow remove\n"));
+ miSpriteRemoveCursor (pDev, pScreen);
+ }
+ }
+ }
+
+ (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
+ SCREEN_EPILOGUE (pScreen, CopyWindow);
+}
+
+static void
+miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ miSpriteScreenPtr pPriv;
+ DeviceIntPtr pDev;
+ miCursorInfoPtr pCursorInfo;
+
+ pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ SCREEN_PROLOGUE(pScreen, BlockHandler);
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ SCREEN_EPILOGUE(pScreen, BlockHandler);
+
+ for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+ if (pCursorInfo && !pCursorInfo->isUp
+ && pCursorInfo->pScreen == pScreen
+ && pCursorInfo->shouldBeUp)
+ {
+ SPRITE_DEBUG (("BlockHandler restore\n"));
+ miSpriteSaveUnderCursor (pDev, pScreen);
+ }
+ }
+ }
+ for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+ if (pCursorInfo && !pCursorInfo->isUp &&
+ pCursorInfo->pScreen == pScreen &&
+ pCursorInfo->shouldBeUp)
+ {
+ SPRITE_DEBUG (("BlockHandler restore\n"));
+ miSpriteRestoreCursor (pDev, pScreen);
+ }
+ }
+ }
+}
+
+static void
+miSpriteInstallColormap (ColormapPtr pMap)
+{
+ ScreenPtr pScreen = pMap->pScreen;
+ miSpriteScreenPtr pPriv;
+
+ pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ SCREEN_PROLOGUE(pScreen, InstallColormap);
+
+ (*pScreen->InstallColormap) (pMap);
+
+ SCREEN_EPILOGUE(pScreen, InstallColormap);
+
+ /* InstallColormap can be called before devices are initialized. */
+ pPriv->pInstalledMap = pMap;
+ if (pPriv->pColormap != pMap)
+ {
+ DeviceIntPtr pDev;
+ miCursorInfoPtr pCursorInfo;
+ for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+ pCursorInfo->checkPixels = TRUE;
+ if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
+ miSpriteRemoveCursor(pDev, pScreen);
+ }
+ }
+
+ }
+}
+
+static void
+miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
+{
+ ScreenPtr pScreen = pMap->pScreen;
+ miSpriteScreenPtr pPriv;
+ int i;
+ int updated;
+ VisualPtr pVisual;
+ DeviceIntPtr pDev;
+ miCursorInfoPtr pCursorInfo;
+
+ pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ SCREEN_PROLOGUE(pScreen, StoreColors);
+
+ (*pScreen->StoreColors) (pMap, ndef, pdef);
+
+ SCREEN_EPILOGUE(pScreen, StoreColors);
+
+ if (pPriv->pColormap == pMap)
+ {
+ updated = 0;
+ pVisual = pMap->pVisual;
+ if (pVisual->class == DirectColor)
+ {
+ /* Direct color - match on any of the subfields */
+
+#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
+
+#define UpdateDAC(dev, plane,dac,mask) {\
+ if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
+ dev->colors[plane].dac = pdef[i].dac; \
+ updated = 1; \
+ } \
+}
+
+#define CheckDirect(dev, plane) \
+ UpdateDAC(dev, plane,red,redMask) \
+ UpdateDAC(dev, plane,green,greenMask) \
+ UpdateDAC(dev, plane,blue,blueMask)
+
+ for (i = 0; i < ndef; i++)
+ {
+ CheckDirect (pPriv, SOURCE_COLOR)
+ CheckDirect (pPriv, MASK_COLOR)
+ }
+ }
+ else
+ {
+ /* PseudoColor/GrayScale - match on exact pixel */
+ for (i = 0; i < ndef; i++)
+ {
+ if (pdef[i].pixel ==
+ pPriv->colors[SOURCE_COLOR].pixel)
+ {
+ pPriv->colors[SOURCE_COLOR] = pdef[i];
+ if (++updated == 2)
+ break;
+ }
+ if (pdef[i].pixel ==
+ pPriv->colors[MASK_COLOR].pixel)
+ {
+ pPriv->colors[MASK_COLOR] = pdef[i];
+ if (++updated == 2)
+ break;
+ }
+ }
+ }
+ if (updated)
+ {
+ for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pCursorInfo = MISPRITE(pDev);
+ pCursorInfo->checkPixels = TRUE;
+ if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
+ miSpriteRemoveCursor (pDev, pScreen);
+ }
+ }
+ }
+ }
+}
+
+static void
+miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
+{
+ miSpriteScreenPtr pScreenPriv =
+ dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ CursorPtr pCursor;
+ xColorItem *sourceColor, *maskColor;
+
+ pCursor = pDevCursor->pCursor;
+ sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
+ maskColor = &pScreenPriv->colors[MASK_COLOR];
+ if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
+ !(pCursor->foreRed == sourceColor->red &&
+ pCursor->foreGreen == sourceColor->green &&
+ pCursor->foreBlue == sourceColor->blue &&
+ pCursor->backRed == maskColor->red &&
+ pCursor->backGreen == maskColor->green &&
+ pCursor->backBlue == maskColor->blue))
+ {
+ pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
+ sourceColor->red = pCursor->foreRed;
+ sourceColor->green = pCursor->foreGreen;
+ sourceColor->blue = pCursor->foreBlue;
+ FakeAllocColor (pScreenPriv->pColormap, sourceColor);
+ maskColor->red = pCursor->backRed;
+ maskColor->green = pCursor->backGreen;
+ maskColor->blue = pCursor->backBlue;
+ FakeAllocColor (pScreenPriv->pColormap, maskColor);
+ /* "free" the pixels right away, don't let this confuse you */
+ FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
+ FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
+ }
+
+ pDevCursor->checkPixels = FALSE;
+
+}
+
+/*
+ * miPointer interface routines
+ */
+
+#define SPRITE_PAD 8
+
+static Bool
+miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
+{
+ miSpriteScreenPtr pScreenPriv;
+ miCursorInfoPtr pCursorInfo;
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ if (!IsMaster(pDev) && !pDev->u.master)
+ return FALSE;
+
+ pCursorInfo = MISPRITE(pDev);
+
+ if (pCursor == pCursorInfo->pCursor)
+ pCursorInfo->checkPixels = TRUE;
+
+ return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
+}
+
+static Bool
+miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
+{
+ miSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
+}
+
+static void
+miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor, int x, int y)
+{
+ miSpriteScreenPtr pScreenPriv;
+ miCursorInfoPtr pPointer;
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+
+ if (!IsMaster(pDev) && !pDev->u.master)
+ return;
+
+ pPointer = MISPRITE(pDev);
+
+ if (!pCursor)
+ {
+ pPointer->shouldBeUp = FALSE;
+ if (pPointer->isUp)
+ miSpriteRemoveCursor (pDev, pScreen);
+ pPointer->pCursor = 0;
+ return;
+ }
+ pPointer->shouldBeUp = TRUE;
+ if (pPointer->x == x &&
+ pPointer->y == y &&
+ pPointer->pCursor == pCursor &&
+ !pPointer->checkPixels)
+ {
+ return;
+ }
+ pPointer->x = x;
+ pPointer->y = y;
+ pPointer->pCacheWin = NullWindow;
+ if (pPointer->checkPixels || pPointer->pCursor != pCursor)
+ {
+ pPointer->pCursor = pCursor;
+ miSpriteFindColors (pPointer, pScreen);
+ }
+ if (pPointer->isUp) {
+#if 0
+ /* FIXME: Disabled for MPX, should be rewritten */
+ int sx, sy;
+ /*
+ * check to see if the old saved region
+ * encloses the new sprite, in which case we use
+ * the flicker-free MoveCursor primitive.
+ */
+ sx = pointer->x - (int)pCursor->bits->xhot;
+ sy = pointer->y - (int)pCursor->bits->yhot;
+ if (sx + (int) pCursor->bits->width >= pointer->saved.x1 &&
+ sx < pointer->saved.x2 &&
+ sy + (int) pCursor->bits->height >= pointer->saved.y1 &&
+ sy < pointer->saved.y2 &&
+ (int) pCursor->bits->width + (2 * SPRITE_PAD) ==
+ pointer->saved.x2 - pointer->saved.x1 &&
+ (int) pCursor->bits->height + (2 * SPRITE_PAD) ==
+ pointer->saved.y2 - pointer->saved.y1
+ )
+ {
+ DamageDrawInternal (pScreen, TRUE);
+ miSpriteIsDown(pCursorInfo);
+ if (!(sx >= pointer->saved.x1 &&
+ sx + (int)pCursor->bits->width < pointer->saved.x2
+ && sy >= pointer->saved.y1 &&
+ sy + (int)pCursor->bits->height <
+ pointer->saved.y2))
+ {
+ int oldx1, oldy1, dx, dy;
+
+ oldx1 = pointer->saved.x1;
+ oldy1 = pointer->saved.y1;
+ dx = oldx1 - (sx - SPRITE_PAD);
+ dy = oldy1 - (sy - SPRITE_PAD);
+ pointer->saved.x1 -= dx;
+ pointer->saved.y1 -= dy;
+ pointer->saved.x2 -= dx;
+ pointer->saved.y2 -= dy;
+ (void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
+ pointer->saved.x1,
+ pointer->saved.y1,
+ pointer->saved.x2 -
+ pointer->saved.x1,
+ pointer->saved.y2 -
+ pointer->saved.y1,
+ dx, dy);
+ }
+ (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
+ pointer->saved.x1,
+ pointer->saved.y1,
+ pointer->saved.x2 -
+ pointer->saved.x1,
+ pointer->saved.y2 -
+ pointer->saved.y1,
+ sx - pointer->saved.x1,
+ sy - pointer->saved.y1,
+ pointer->colors[SOURCE_COLOR].pixel,
+ pointer->colors[MASK_COLOR].pixel);
+ miSpriteIsUp(pCursorInfo);
+ DamageDrawInternal (pScreen, FALSE);
+ }
+ else
+#endif
+ {
+ SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id));
+ miSpriteRemoveCursor (pDev, pScreen);
+ }
+ }
+
+ if (!pPointer->isUp && pPointer->pCursor)
+ {
+ SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id));
+ miSpriteSaveUnderCursor(pDev, pScreen);
+ miSpriteRestoreCursor (pDev, pScreen);
+ }
+
+}
+
+static void
+miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+ miSpriteScreenPtr pScreenPriv;
+ CursorPtr pCursor;
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ if (!IsMaster(pDev) && !pDev->u.master)
+ return;
+
+ pCursor = MISPRITE(pDev)->pCursor;
+
+ miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
+}
+
+
+static Bool
+miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miSpriteScreenPtr pScreenPriv;
+ miCursorInfoPtr pCursorInfo;
+ int ret = FALSE;
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+
+ pCursorInfo = malloc(sizeof(miCursorInfoRec));
+ if (!pCursorInfo)
+ return FALSE;
+
+ pCursorInfo->pCursor = NULL;
+ pCursorInfo->x = 0;
+ pCursorInfo->y = 0;
+ pCursorInfo->isUp = FALSE;
+ pCursorInfo->shouldBeUp = FALSE;
+ pCursorInfo->pCacheWin = NullWindow;
+ pCursorInfo->isInCacheWin = FALSE;
+ pCursorInfo->checkPixels = TRUE;
+ pCursorInfo->pScreen = FALSE;
+
+ ret = (*pScreenPriv->funcs->DeviceCursorInitialize)(pDev, pScreen);
+ if (!ret)
+ {
+ free(pCursorInfo);
+ pCursorInfo = NULL;
+ }
+ dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo);
+ return ret;
+}
+
+static void
+miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ if (DevHasCursor(pDev))
+ {
+ miSpriteScreenPtr pScreenPriv;
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,
+ miSpriteScreenKey);
+
+ (*pScreenPriv->funcs->DeviceCursorCleanup)(pDev, pScreen);
+ }
+}
+
+/*
+ * undraw/draw cursor
+ */
+
+static void
+miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miSpriteScreenPtr pScreenPriv;
+ miCursorInfoPtr pCursorInfo;
+
+
+ if (!IsMaster(pDev) && !pDev->u.master)
+ return;
+
+ DamageDrawInternal (pScreen, TRUE);
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ pCursorInfo = MISPRITE(pDev);
+
+ miSpriteIsDown(pCursorInfo);
+ pCursorInfo->pCacheWin = NullWindow;
+ miSpriteDisableDamage(pScreen, pScreenPriv);
+ if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDev,
+ pScreen,
+ pCursorInfo->saved.x1,
+ pCursorInfo->saved.y1,
+ pCursorInfo->saved.x2 -
+ pCursorInfo->saved.x1,
+ pCursorInfo->saved.y2 -
+ pCursorInfo->saved.y1))
+ {
+ miSpriteIsUp(pCursorInfo);
+ }
+ miSpriteEnableDamage(pScreen, pScreenPriv);
+ DamageDrawInternal (pScreen, FALSE);
+}
+
+/*
+ * Called from the block handler, saves area under cursor
+ * before waiting for something to do.
+ */
+
+static void
+miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miSpriteScreenPtr pScreenPriv;
+ int x, y;
+ CursorPtr pCursor;
+ miCursorInfoPtr pCursorInfo;
+
+ if (!IsMaster(pDev) && !pDev->u.master)
+ return;
+
+ DamageDrawInternal (pScreen, TRUE);
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ pCursorInfo = MISPRITE(pDev);
+
+ miSpriteComputeSaved (pDev, pScreen);
+ pCursor = pCursorInfo->pCursor;
+
+ x = pCursorInfo->x - (int)pCursor->bits->xhot;
+ y = pCursorInfo->y - (int)pCursor->bits->yhot;
+ miSpriteDisableDamage(pScreen, pScreenPriv);
+
+ (*pScreenPriv->funcs->SaveUnderCursor) (pDev,
+ pScreen,
+ pCursorInfo->saved.x1,
+ pCursorInfo->saved.y1,
+ pCursorInfo->saved.x2 -
+ pCursorInfo->saved.x1,
+ pCursorInfo->saved.y2 -
+ pCursorInfo->saved.y1);
+ SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
+ miSpriteEnableDamage(pScreen, pScreenPriv);
+ DamageDrawInternal (pScreen, FALSE);
+}
+
+
+/*
+ * Called from the block handler, restores the cursor
+ * before waiting for something to do.
+ */
+
+static void
+miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miSpriteScreenPtr pScreenPriv;
+ int x, y;
+ CursorPtr pCursor;
+ miCursorInfoPtr pCursorInfo;
+
+ if (!IsMaster(pDev) && !pDev->u.master)
+ return;
+
+ DamageDrawInternal (pScreen, TRUE);
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ pCursorInfo = MISPRITE(pDev);
+
+ miSpriteComputeSaved (pDev, pScreen);
+ pCursor = pCursorInfo->pCursor;
+
+ x = pCursorInfo->x - (int)pCursor->bits->xhot;
+ y = pCursorInfo->y - (int)pCursor->bits->yhot;
+ miSpriteDisableDamage(pScreen, pScreenPriv);
+ SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
+ if (pCursorInfo->checkPixels)
+ miSpriteFindColors (pCursorInfo, pScreen);
+ if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen,
+ pCursor, x, y,
+ pScreenPriv->colors[SOURCE_COLOR].pixel,
+ pScreenPriv->colors[MASK_COLOR].pixel))
+ {
+ miSpriteIsUp(pCursorInfo);
+ pCursorInfo->pScreen = pScreen;
+ }
+ miSpriteEnableDamage(pScreen, pScreenPriv);
+ DamageDrawInternal (pScreen, FALSE);
+}
+
+/*
+ * compute the desired area of the screen to save
+ */
+
+static void
+miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miSpriteScreenPtr pScreenPriv;
+ int x, y, w, h;
+ int wpad, hpad;
+ CursorPtr pCursor;
+ miCursorInfoPtr pCursorInfo;
+
+ if (!IsMaster(pDev) && !pDev->u.master)
+ return;
+
+ pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ pCursorInfo = MISPRITE(pDev);
+
+ pCursor = pCursorInfo->pCursor;
+ x = pCursorInfo->x - (int)pCursor->bits->xhot;
+ y = pCursorInfo->y - (int)pCursor->bits->yhot;
+ w = pCursor->bits->width;
+ h = pCursor->bits->height;
+ wpad = SPRITE_PAD;
+ hpad = SPRITE_PAD;
+ pCursorInfo->saved.x1 = x - wpad;
+ pCursorInfo->saved.y1 = y - hpad;
+ pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
+ pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
+}
+
diff --git a/xorg-server/mi/miwideline.c b/xorg-server/mi/miwideline.c index 181b12e48..9fb540c2b 100644 --- a/xorg-server/mi/miwideline.c +++ b/xorg-server/mi/miwideline.c @@ -1,2260 +1,2193 @@ -/* - -Copyright 1988, 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. - -*/ - -/* Author: Keith Packard, MIT X Consortium */ - -/* - * Mostly integer wideline code. Uses a technique similar to - * bresenham zero-width lines, except walks an X edge - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <stdio.h> -#ifdef _XOPEN_SOURCE -#include <math.h> -#else -#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */ -#include <math.h> -#undef _XOPEN_SOURCE -#endif -#include <X11/X.h> -#include "windowstr.h" -#include "gcstruct.h" -#include "regionstr.h" -#include "miwideline.h" -#include "mi.h" - -/* - * interface data to span-merging polygon filler - */ - -typedef struct _SpanData { - SpanGroup fgGroup, bgGroup; -} SpanDataRec, *SpanDataPtr; - -static void -AppendSpanGroup(GCPtr pGC, unsigned long pixel, Spans *spanPtr, SpanDataPtr spanData) -{ - SpanGroup *group, *othergroup = NULL; - if (pixel == pGC->fgPixel) - { - group = &spanData->fgGroup; - if (pGC->lineStyle == LineDoubleDash) - othergroup = &spanData->bgGroup; - } - else - { - group = &spanData->bgGroup; - othergroup = &spanData->fgGroup; - } - miAppendSpans (group, othergroup, spanPtr); -} - - -static void miLineArc(DrawablePtr pDraw, GCPtr pGC, - unsigned long pixel, SpanDataPtr spanData, - LineFacePtr leftFace, - LineFacePtr rightFace, - double xorg, double yorg, Bool isInt); - - -/* - * spans-based polygon filler - */ - -static void -miFillPolyHelper (DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, - SpanDataPtr spanData, int y, int overall_height, - PolyEdgePtr left, PolyEdgePtr right, - int left_count, int right_count) -{ - int left_x = 0, left_e = 0; - int left_stepx = 0; - int left_signdx = 0; - int left_dy = 0, left_dx = 0; - - int right_x = 0, right_e = 0; - int right_stepx = 0; - int right_signdx = 0; - int right_dy = 0, right_dx = 0; - - int height = 0; - int left_height = 0, right_height = 0; - - DDXPointPtr ppt; - DDXPointPtr pptInit = NULL; - int *pwidth; - int *pwidthInit = NULL; - XID oldPixel; - int xorg; - Spans spanRec; - - left_height = 0; - right_height = 0; - - if (!spanData) - { - pptInit = xalloc (overall_height * sizeof(*ppt)); - if (!pptInit) - return; - pwidthInit = xalloc (overall_height * sizeof(*pwidth)); - if (!pwidthInit) - { - xfree (pptInit); - return; - } - ppt = pptInit; - pwidth = pwidthInit; - oldPixel = pGC->fgPixel; - if (pixel != oldPixel) - { - XID tmpPixel = (XID)pixel; - DoChangeGC (pGC, GCForeground, &tmpPixel, FALSE); - ValidateGC (pDrawable, pGC); - } - } - else - { - spanRec.points = xalloc (overall_height * sizeof (*ppt)); - if (!spanRec.points) - return; - spanRec.widths = xalloc (overall_height * sizeof (int)); - if (!spanRec.widths) - { - xfree (spanRec.points); - return; - } - ppt = spanRec.points; - pwidth = spanRec.widths; - } - - xorg = 0; - if (pGC->miTranslate) - { - y += pDrawable->y; - xorg = pDrawable->x; - } - while ((left_count || left_height) && - (right_count || right_height)) - { - if (!left_height && left_count) - { - left_height = left->height; - left_x = left->x; - left_stepx = left->stepx; - left_signdx = left->signdx; - left_e = left->e; - left_dy = left->dy; - left_dx = left->dx; - --left_count; - ++left; - } - - if (!right_height && right_count) - { - right_height = right->height; - right_x = right->x; - right_stepx = right->stepx; - right_signdx = right->signdx; - right_e = right->e; - right_dy = right->dy; - right_dx = right->dx; - --right_count; - ++right; - } - - height = left_height; - if (height > right_height) - height = right_height; - - left_height -= height; - right_height -= height; - - while (--height >= 0) - { - if (right_x >= left_x) - { - ppt->y = y; - ppt->x = left_x + xorg; - ppt++; - *pwidth++ = right_x - left_x + 1; - } - y++; - - left_x += left_stepx; - left_e += left_dx; - if (left_e > 0) - { - left_x += left_signdx; - left_e -= left_dy; - } - - right_x += right_stepx; - right_e += right_dx; - if (right_e > 0) - { - right_x += right_signdx; - right_e -= right_dy; - } - } - } - if (!spanData) - { - (*pGC->ops->FillSpans) (pDrawable, pGC, ppt - pptInit, pptInit, pwidthInit, TRUE); - xfree (pwidthInit); - xfree (pptInit); - if (pixel != oldPixel) - { - DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); - ValidateGC (pDrawable, pGC); - } - } - else - { - spanRec.count = ppt - spanRec.points; - AppendSpanGroup (pGC, pixel, &spanRec, spanData); - } -} - -static void -miFillRectPolyHelper ( - DrawablePtr pDrawable, - GCPtr pGC, - unsigned long pixel, - SpanDataPtr spanData, - int x, - int y, - int w, - int h) -{ - DDXPointPtr ppt; - int *pwidth; - XID oldPixel; - Spans spanRec; - xRectangle rect; - - if (!spanData) - { - rect.x = x; - rect.y = y; - rect.width = w; - rect.height = h; - oldPixel = pGC->fgPixel; - if (pixel != oldPixel) - { - XID tmpPixel = (XID)pixel; - DoChangeGC (pGC, GCForeground, &tmpPixel, FALSE); - ValidateGC (pDrawable, pGC); - } - (*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect); - if (pixel != oldPixel) - { - DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); - ValidateGC (pDrawable, pGC); - } - } - else - { - spanRec.points = xalloc (h * sizeof (*ppt)); - if (!spanRec.points) - return; - spanRec.widths = xalloc (h * sizeof (int)); - if (!spanRec.widths) - { - xfree (spanRec.points); - return; - } - ppt = spanRec.points; - pwidth = spanRec.widths; - - if (pGC->miTranslate) - { - y += pDrawable->y; - x += pDrawable->x; - } - while (h--) - { - ppt->x = x; - ppt->y = y; - ppt++; - *pwidth++ = w; - y++; - } - spanRec.count = ppt - spanRec.points; - AppendSpanGroup (pGC, pixel, &spanRec, spanData); - } -} - -/* static */ int -miPolyBuildEdge ( - double x0, - double y0, - double k, /* x0 * dy - y0 * dx */ - int dx, - int dy, - int xi, - int yi, - int left, - PolyEdgePtr edge) -{ - int x, y, e; - int xady; - - if (dy < 0) - { - dy = -dy; - dx = -dx; - k = -k; - } - -#ifdef NOTDEF - { - double realk, kerror; - realk = x0 * dy - y0 * dx; - kerror = Fabs (realk - k); - if (kerror > .1) - printf ("realk: %g k: %g\n", realk, k); - } -#endif - y = ICEIL (y0); - xady = ICEIL (k) + y * dx; - - if (xady <= 0) - x = - (-xady / dy) - 1; - else - x = (xady - 1) / dy; - - e = xady - x * dy; - - if (dx >= 0) - { - edge->signdx = 1; - edge->stepx = dx / dy; - edge->dx = dx % dy; - } - else - { - edge->signdx = -1; - edge->stepx = - (-dx / dy); - edge->dx = -dx % dy; - e = dy - e + 1; - } - edge->dy = dy; - edge->x = x + left + xi; - edge->e = e - dy; /* bias to compare against 0 instead of dy */ - return y + yi; -} - -#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) - -/* static */ int -miPolyBuildPoly ( - PolyVertexPtr vertices, - PolySlopePtr slopes, - int count, - int xi, - int yi, - PolyEdgePtr left, - PolyEdgePtr right, - int *pnleft, - int *pnright, - int *h) -{ - int top, bottom; - double miny, maxy; - int i; - int j; - int clockwise; - int slopeoff; - int s; - int nright, nleft; - int y, lasty = 0, bottomy, topy = 0; - - /* find the top of the polygon */ - maxy = miny = vertices[0].y; - bottom = top = 0; - for (i = 1; i < count; i++) - { - if (vertices[i].y < miny) - { - top = i; - miny = vertices[i].y; - } - if (vertices[i].y >= maxy) - { - bottom = i; - maxy = vertices[i].y; - } - } - clockwise = 1; - slopeoff = 0; - - i = top; - j = StepAround (top, -1, count); - - if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) - { - clockwise = -1; - slopeoff = -1; - } - - bottomy = ICEIL (maxy) + yi; - - nright = 0; - - s = StepAround (top, slopeoff, count); - i = top; - while (i != bottom) - { - if (slopes[s].dy != 0) - { - y = miPolyBuildEdge (vertices[i].x, vertices[i].y, - slopes[s].k, - slopes[s].dx, slopes[s].dy, - xi, yi, 0, - &right[nright]); - if (nright != 0) - right[nright-1].height = y - lasty; - else - topy = y; - nright++; - lasty = y; - } - - i = StepAround (i, clockwise, count); - s = StepAround (s, clockwise, count); - } - if (nright != 0) - right[nright-1].height = bottomy - lasty; - - if (slopeoff == 0) - slopeoff = -1; - else - slopeoff = 0; - - nleft = 0; - s = StepAround (top, slopeoff, count); - i = top; - while (i != bottom) - { - if (slopes[s].dy != 0) - { - y = miPolyBuildEdge (vertices[i].x, vertices[i].y, - slopes[s].k, - slopes[s].dx, slopes[s].dy, xi, yi, 1, - &left[nleft]); - - if (nleft != 0) - left[nleft-1].height = y - lasty; - nleft++; - lasty = y; - } - i = StepAround (i, -clockwise, count); - s = StepAround (s, -clockwise, count); - } - if (nleft != 0) - left[nleft-1].height = bottomy - lasty; - *pnleft = nleft; - *pnright = nright; - *h = bottomy - topy; - return topy; -} - -static void -miLineOnePoint ( - DrawablePtr pDrawable, - GCPtr pGC, - unsigned long pixel, - SpanDataPtr spanData, - int x, - int y) -{ - DDXPointRec pt; - int wid; - unsigned long oldPixel; - - MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel); - if (pGC->fillStyle == FillSolid) - { - pt.x = x; - pt.y = y; - (*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt); - } - else - { - wid = 1; - if (pGC->miTranslate) - { - x += pDrawable->x; - y += pDrawable->y; - } - pt.x = x; - pt.y = y; - (*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE); - } - MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel); -} - -static void -miLineJoin ( - DrawablePtr pDrawable, - GCPtr pGC, - unsigned long pixel, - SpanDataPtr spanData, - LineFacePtr pLeft, - LineFacePtr pRight) -{ - double mx = 0, my = 0; - double denom = 0.0; - PolyVertexRec vertices[4]; - PolySlopeRec slopes[4]; - int edgecount; - PolyEdgeRec left[4], right[4]; - int nleft, nright; - int y, height; - int swapslopes; - int joinStyle = pGC->joinStyle; - int lw = pGC->lineWidth; - - if (lw == 1 && !spanData) { - /* See if one of the lines will draw the joining pixel */ - if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0)) - return; - if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0)) - return; - if (joinStyle != JoinRound) { - denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; - if (denom == 0) - return; /* no join to draw */ - } - if (joinStyle != JoinMiter) { - miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y); - return; - } - } else { - if (joinStyle == JoinRound) - { - miLineArc(pDrawable, pGC, pixel, spanData, - pLeft, pRight, - (double)0.0, (double)0.0, TRUE); - return; - } - denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; - if (denom == 0.0) - return; /* no join to draw */ - } - - swapslopes = 0; - if (denom > 0) - { - pLeft->xa = -pLeft->xa; - pLeft->ya = -pLeft->ya; - pLeft->dx = -pLeft->dx; - pLeft->dy = -pLeft->dy; - } - else - { - swapslopes = 1; - pRight->xa = -pRight->xa; - pRight->ya = -pRight->ya; - pRight->dx = -pRight->dx; - pRight->dy = -pRight->dy; - } - - vertices[0].x = pRight->xa; - vertices[0].y = pRight->ya; - slopes[0].dx = -pRight->dy; - slopes[0].dy = pRight->dx; - slopes[0].k = 0; - - vertices[1].x = 0; - vertices[1].y = 0; - slopes[1].dx = pLeft->dy; - slopes[1].dy = -pLeft->dx; - slopes[1].k = 0; - - vertices[2].x = pLeft->xa; - vertices[2].y = pLeft->ya; - - if (joinStyle == JoinMiter) - { - my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - - pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx )) / - denom; - if (pLeft->dy != 0) - { - mx = pLeft->xa + (my - pLeft->ya) * - (double) pLeft->dx / (double) pLeft->dy; - } - else - { - mx = pRight->xa + (my - pRight->ya) * - (double) pRight->dx / (double) pRight->dy; - } - /* check miter limit */ - if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) - joinStyle = JoinBevel; - } - - if (joinStyle == JoinMiter) - { - slopes[2].dx = pLeft->dx; - slopes[2].dy = pLeft->dy; - slopes[2].k = pLeft->k; - if (swapslopes) - { - slopes[2].dx = -slopes[2].dx; - slopes[2].dy = -slopes[2].dy; - slopes[2].k = -slopes[2].k; - } - vertices[3].x = mx; - vertices[3].y = my; - slopes[3].dx = pRight->dx; - slopes[3].dy = pRight->dy; - slopes[3].k = pRight->k; - if (swapslopes) - { - slopes[3].dx = -slopes[3].dx; - slopes[3].dy = -slopes[3].dy; - slopes[3].k = -slopes[3].k; - } - edgecount = 4; - } - else - { - double scale, dx, dy, adx, ady; - - adx = dx = pRight->xa - pLeft->xa; - ady = dy = pRight->ya - pLeft->ya; - if (adx < 0) - adx = -adx; - if (ady < 0) - ady = -ady; - scale = ady; - if (adx > ady) - scale = adx; - slopes[2].dx = (dx * 65536) / scale; - slopes[2].dy = (dy * 65536) / scale; - slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - - (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; - edgecount = 3; - } - - y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, - left, right, &nleft, &nright, &height); - miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright); -} - -static int -miLineArcI ( - DrawablePtr pDraw, - GCPtr pGC, - int xorg, - int yorg, - DDXPointPtr points, - int *widths) -{ - DDXPointPtr tpts, bpts; - int *twids, *bwids; - int x, y, e, ex, slw; - - tpts = points; - twids = widths; - if (pGC->miTranslate) - { - xorg += pDraw->x; - yorg += pDraw->y; - } - slw = pGC->lineWidth; - if (slw == 1) - { - tpts->x = xorg; - tpts->y = yorg; - *twids = 1; - return 1; - } - bpts = tpts + slw; - bwids = twids + slw; - y = (slw >> 1) + 1; - if (slw & 1) - e = - ((y << 2) + 3); - else - e = - (y << 3); - ex = -4; - x = 0; - while (y) - { - e += (y << 3) - 4; - while (e >= 0) - { - x++; - e += (ex = -((x << 3) + 4)); - } - y--; - slw = (x << 1) + 1; - if ((e == ex) && (slw > 1)) - slw--; - tpts->x = xorg - x; - tpts->y = yorg - y; - tpts++; - *twids++ = slw; - if ((y != 0) && ((slw > 1) || (e != ex))) - { - bpts--; - bpts->x = xorg - x; - bpts->y = yorg + y; - *--bwids = slw; - } - } - return (pGC->lineWidth); -} - -#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ - if (ybase == edgey) \ - { \ - if (edgeleft) \ - { \ - if (edge->x > xcl) \ - xcl = edge->x; \ - } \ - else \ - { \ - if (edge->x < xcr) \ - xcr = edge->x; \ - } \ - edgey++; \ - edge->x += edge->stepx; \ - edge->e += edge->dx; \ - if (edge->e > 0) \ - { \ - edge->x += edge->signdx; \ - edge->e -= edge->dy; \ - } \ - } - -static int -miLineArcD ( - DrawablePtr pDraw, - GCPtr pGC, - double xorg, - double yorg, - DDXPointPtr points, - int *widths, - PolyEdgePtr edge1, - int edgey1, - Bool edgeleft1, - PolyEdgePtr edge2, - int edgey2, - Bool edgeleft2) -{ - DDXPointPtr pts; - int *wids; - double radius, x0, y0, el, er, yk, xlk, xrk, k; - int xbase, ybase, y, boty, xl, xr, xcl, xcr; - int ymin, ymax; - Bool edge1IsMin, edge2IsMin; - int ymin1, ymin2; - - pts = points; - wids = widths; - xbase = floor(xorg); - x0 = xorg - xbase; - ybase = ICEIL (yorg); - y0 = yorg - ybase; - if (pGC->miTranslate) - { - xbase += pDraw->x; - ybase += pDraw->y; - edge1->x += pDraw->x; - edge2->x += pDraw->x; - edgey1 += pDraw->y; - edgey2 += pDraw->y; - } - xlk = x0 + x0 + 1.0; - xrk = x0 + x0 - 1.0; - yk = y0 + y0 - 1.0; - radius = ((double)pGC->lineWidth) / 2.0; - y = floor(radius - y0 + 1.0); - ybase -= y; - ymin = ybase; - ymax = 65536; - edge1IsMin = FALSE; - ymin1 = edgey1; - if (edge1->dy >= 0) - { - if (!edge1->dy) - { - if (edgeleft1) - edge1IsMin = TRUE; - else - ymax = edgey1; - edgey1 = 65536; - } - else - { - if ((edge1->signdx < 0) == edgeleft1) - edge1IsMin = TRUE; - } - } - edge2IsMin = FALSE; - ymin2 = edgey2; - if (edge2->dy >= 0) - { - if (!edge2->dy) - { - if (edgeleft2) - edge2IsMin = TRUE; - else - ymax = edgey2; - edgey2 = 65536; - } - else - { - if ((edge2->signdx < 0) == edgeleft2) - edge2IsMin = TRUE; - } - } - if (edge1IsMin) - { - ymin = ymin1; - if (edge2IsMin && ymin1 > ymin2) - ymin = ymin2; - } else if (edge2IsMin) - ymin = ymin2; - el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); - er = el + xrk; - xl = 1; - xr = 0; - if (x0 < 0.5) - { - xl = 0; - el -= xlk; - } - boty = (y0 < -0.5) ? 1 : 0; - if (ybase + y - boty > ymax) - boty = ymax - ybase - y; - while (y > boty) - { - k = (y << 1) + yk; - er += k; - while (er > 0.0) - { - xr++; - er += xrk - (xr << 1); - } - el += k; - while (el >= 0.0) - { - xl--; - el += (xl << 1) - xlk; - } - y--; - ybase++; - if (ybase < ymin) - continue; - xcl = xl + xbase; - xcr = xr + xbase; - CLIPSTEPEDGE(edgey1, edge1, edgeleft1); - CLIPSTEPEDGE(edgey2, edge2, edgeleft2); - if (xcr >= xcl) - { - pts->x = xcl; - pts->y = ybase; - pts++; - *wids++ = xcr - xcl + 1; - } - } - er = xrk - (xr << 1) - er; - el = (xl << 1) - xlk - el; - boty = floor(-y0 - radius + 1.0); - if (ybase + y - boty > ymax) - boty = ymax - ybase - y; - while (y > boty) - { - k = (y << 1) + yk; - er -= k; - while ((er >= 0.0) && (xr >= 0)) - { - xr--; - er += xrk - (xr << 1); - } - el -= k; - while ((el > 0.0) && (xl <= 0)) - { - xl++; - el += (xl << 1) - xlk; - } - y--; - ybase++; - if (ybase < ymin) - continue; - xcl = xl + xbase; - xcr = xr + xbase; - CLIPSTEPEDGE(edgey1, edge1, edgeleft1); - CLIPSTEPEDGE(edgey2, edge2, edgeleft2); - if (xcr >= xcl) - { - pts->x = xcl; - pts->y = ybase; - pts++; - *wids++ = xcr - xcl + 1; - } - } - return (pts - points); -} - -static int -miRoundJoinFace (LineFacePtr face, PolyEdgePtr edge, Bool *leftEdge) -{ - int y; - int dx, dy; - double xa, ya; - Bool left; - - dx = -face->dy; - dy = face->dx; - xa = face->xa; - ya = face->ya; - left = 1; - if (ya > 0) - { - ya = 0.0; - xa = 0.0; - } - if (dy < 0 || (dy == 0 && dx > 0)) - { - dx = -dx; - dy = -dy; - left = !left; - } - if (dx == 0 && dy == 0) - dy = 1; - if (dy == 0) - { - y = ICEIL (face->ya) + face->y; - edge->x = -32767; - edge->stepx = 0; - edge->signdx = 0; - edge->e = -1; - edge->dy = 0; - edge->dx = 0; - edge->height = 0; - } - else - { - y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge); - edge->height = 32767; - } - *leftEdge = !left; - return y; -} - -void -miRoundJoinClip (LineFacePtr pLeft, LineFacePtr pRight, - PolyEdgePtr edge1, PolyEdgePtr edge2, - int *y1, int *y2, Bool *left1, Bool *left2) -{ - double denom; - - denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; - - if (denom >= 0) - { - pLeft->xa = -pLeft->xa; - pLeft->ya = -pLeft->ya; - } - else - { - pRight->xa = -pRight->xa; - pRight->ya = -pRight->ya; - } - *y1 = miRoundJoinFace (pLeft, edge1, left1); - *y2 = miRoundJoinFace (pRight, edge2, left2); -} - -int -miRoundCapClip (LineFacePtr face, Bool isInt, PolyEdgePtr edge, Bool *leftEdge) -{ - int y; - int dx, dy; - double xa, ya, k; - Bool left; - - dx = -face->dy; - dy = face->dx; - xa = face->xa; - ya = face->ya; - k = 0.0; - if (!isInt) - k = face->k; - left = 1; - if (dy < 0 || (dy == 0 && dx > 0)) - { - dx = -dx; - dy = -dy; - xa = -xa; - ya = -ya; - left = !left; - } - if (dx == 0 && dy == 0) - dy = 1; - if (dy == 0) - { - y = ICEIL (face->ya) + face->y; - edge->x = -32767; - edge->stepx = 0; - edge->signdx = 0; - edge->e = -1; - edge->dy = 0; - edge->dx = 0; - edge->height = 0; - } - else - { - y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge); - edge->height = 32767; - } - *leftEdge = !left; - return y; -} - -static void -miLineArc ( - DrawablePtr pDraw, - GCPtr pGC, - unsigned long pixel, - SpanDataPtr spanData, - LineFacePtr leftFace, - LineFacePtr rightFace, - double xorg, - double yorg, - Bool isInt) -{ - DDXPointPtr points; - int *widths; - int xorgi = 0, yorgi = 0; - XID oldPixel; - Spans spanRec; - int n; - PolyEdgeRec edge1, edge2; - int edgey1, edgey2; - Bool edgeleft1, edgeleft2; - - if (isInt) - { - xorgi = leftFace ? leftFace->x : rightFace->x; - yorgi = leftFace ? leftFace->y : rightFace->y; - } - edgey1 = 65536; - edgey2 = 65536; - edge1.x = 0; /* not used, keep memory checkers happy */ - edge1.dy = -1; - edge2.x = 0; /* not used, keep memory checkers happy */ - edge2.dy = -1; - edgeleft1 = FALSE; - edgeleft2 = FALSE; - if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) && - ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) || - (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) - { - if (isInt) - { - xorg = (double) xorgi; - yorg = (double) yorgi; - } - if (leftFace && rightFace) - { - miRoundJoinClip (leftFace, rightFace, &edge1, &edge2, - &edgey1, &edgey2, &edgeleft1, &edgeleft2); - } - else if (leftFace) - { - edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1); - } - else if (rightFace) - { - edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2); - } - isInt = FALSE; - } - if (!spanData) - { - points = xalloc(sizeof(DDXPointRec) * pGC->lineWidth); - if (!points) - return; - widths = xalloc(sizeof(int) * pGC->lineWidth); - if (!widths) - { - xfree(points); - return; - } - oldPixel = pGC->fgPixel; - if (pixel != oldPixel) - { - XID tmpPixel = (XID)pixel; - DoChangeGC(pGC, GCForeground, &tmpPixel, FALSE); - ValidateGC (pDraw, pGC); - } - } - else - { - points = xalloc (pGC->lineWidth * sizeof (DDXPointRec)); - if (!points) - return; - widths = xalloc (pGC->lineWidth * sizeof (int)); - if (!widths) - { - xfree (points); - return; - } - spanRec.points = points; - spanRec.widths = widths; - } - if (isInt) - n = miLineArcI(pDraw, pGC, xorgi, yorgi, points, widths); - else - n = miLineArcD(pDraw, pGC, xorg, yorg, points, widths, - &edge1, edgey1, edgeleft1, - &edge2, edgey2, edgeleft2); - - if (!spanData) - { - (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, TRUE); - xfree(widths); - xfree(points); - if (pixel != oldPixel) - { - DoChangeGC(pGC, GCForeground, &oldPixel, FALSE); - ValidateGC (pDraw, pGC); - } - } - else - { - spanRec.count = n; - AppendSpanGroup (pGC, pixel, &spanRec, spanData); - } -} - -static void -miLineProjectingCap (DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, - SpanDataPtr spanData, LineFacePtr face, Bool isLeft, - double xorg, double yorg, Bool isInt) -{ - int xorgi = 0, yorgi = 0; - int lw; - PolyEdgeRec lefts[2], rights[2]; - int lefty, righty, topy, bottomy; - PolyEdgePtr left, right; - PolyEdgePtr top, bottom; - double xa,ya; - double k; - double xap, yap; - int dx, dy; - double projectXoff, projectYoff; - double maxy; - int finaly; - - if (isInt) - { - xorgi = face->x; - yorgi = face->y; - } - lw = pGC->lineWidth; - dx = face->dx; - dy = face->dy; - k = face->k; - if (dy == 0) - { - lefts[0].height = lw; - lefts[0].x = xorgi; - if (isLeft) - lefts[0].x -= (lw >> 1); - lefts[0].stepx = 0; - lefts[0].signdx = 1; - lefts[0].e = -lw; - lefts[0].dx = 0; - lefts[0].dy = lw; - rights[0].height = lw; - rights[0].x = xorgi; - if (!isLeft) - rights[0].x += ((lw + 1) >> 1); - rights[0].stepx = 0; - rights[0].signdx = 1; - rights[0].e = -lw; - rights[0].dx = 0; - rights[0].dy = lw; - miFillPolyHelper (pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw, - lefts, rights, 1, 1); - } - else if (dx == 0) - { - if (dy < 0) { - dy = -dy; - isLeft = !isLeft; - } - topy = yorgi; - bottomy = yorgi + dy; - if (isLeft) - topy -= (lw >> 1); - else - bottomy += (lw >> 1); - lefts[0].height = bottomy - topy; - lefts[0].x = xorgi - (lw >> 1); - lefts[0].stepx = 0; - lefts[0].signdx = 1; - lefts[0].e = -dy; - lefts[0].dx = dx; - lefts[0].dy = dy; - - rights[0].height = bottomy - topy; - rights[0].x = lefts[0].x + (lw-1); - rights[0].stepx = 0; - rights[0].signdx = 1; - rights[0].e = -dy; - rights[0].dx = dx; - rights[0].dy = dy; - miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, bottomy - topy, lefts, rights, 1, 1); - } - else - { - xa = face->xa; - ya = face->ya; - projectXoff = -ya; - projectYoff = xa; - if (dx < 0) - { - right = &rights[1]; - left = &lefts[0]; - top = &rights[0]; - bottom = &lefts[1]; - } - else - { - right = &rights[0]; - left = &lefts[1]; - top = &lefts[0]; - bottom = &rights[1]; - } - if (isLeft) - { - righty = miPolyBuildEdge (xa, ya, - k, dx, dy, xorgi, yorgi, 0, right); - - xa = -xa; - ya = -ya; - k = -k; - lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, - k, dx, dy, xorgi, yorgi, 1, left); - if (dx > 0) - { - ya = -ya; - xa = -xa; - } - xap = xa - projectXoff; - yap = ya - projectYoff; - topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, - -dy, dx, xorgi, yorgi, dx > 0, top); - bottomy = miPolyBuildEdge (xa, ya, - 0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom); - maxy = -ya; - } - else - { - righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, - k, dx, dy, xorgi, yorgi, 0, right); - - xa = -xa; - ya = -ya; - k = -k; - lefty = miPolyBuildEdge (xa, ya, - k, dx, dy, xorgi, yorgi, 1, left); - if (dx > 0) - { - ya = -ya; - xa = -xa; - } - xap = xa - projectXoff; - yap = ya - projectYoff; - topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top); - bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, - -dy, dx, xorgi, xorgi, dx < 0, bottom); - maxy = -ya + projectYoff; - } - finaly = ICEIL(maxy) + yorgi; - if (dx < 0) - { - left->height = bottomy - lefty; - right->height = finaly - righty; - top->height = righty - topy; - } - else - { - right->height = bottomy - righty; - left->height = finaly - lefty; - top->height = lefty - topy; - } - bottom->height = finaly - bottomy; - miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, - bottom->height + bottomy - topy, lefts, rights, 2, 2); - } -} - -static void -miWideSegment ( - DrawablePtr pDrawable, - GCPtr pGC, - unsigned long pixel, - SpanDataPtr spanData, - int x1, - int y1, - int x2, - int y2, - Bool projectLeft, - Bool projectRight, - LineFacePtr leftFace, - LineFacePtr rightFace) -{ - double l, L, r; - double xa, ya; - double projectXoff = 0.0, projectYoff = 0.0; - double k; - double maxy; - int x, y; - int dx, dy; - int finaly; - PolyEdgePtr left, right; - PolyEdgePtr top, bottom; - int lefty, righty, topy, bottomy; - int signdx; - PolyEdgeRec lefts[2], rights[2]; - LineFacePtr tface; - int lw = pGC->lineWidth; - - /* draw top-to-bottom always */ - if (y2 < y1 || (y2 == y1 && x2 < x1)) - { - x = x1; - x1 = x2; - x2 = x; - - y = y1; - y1 = y2; - y2 = y; - - x = projectLeft; - projectLeft = projectRight; - projectRight = x; - - tface = leftFace; - leftFace = rightFace; - rightFace = tface; - } - - dy = y2 - y1; - signdx = 1; - dx = x2 - x1; - if (dx < 0) - signdx = -1; - - leftFace->x = x1; - leftFace->y = y1; - leftFace->dx = dx; - leftFace->dy = dy; - - rightFace->x = x2; - rightFace->y = y2; - rightFace->dx = -dx; - rightFace->dy = -dy; - - if (dy == 0) - { - rightFace->xa = 0; - rightFace->ya = (double) lw / 2.0; - rightFace->k = -(double) (lw * dx) / 2.0; - leftFace->xa = 0; - leftFace->ya = -rightFace->ya; - leftFace->k = rightFace->k; - x = x1; - if (projectLeft) - x -= (lw >> 1); - y = y1 - (lw >> 1); - dx = x2 - x; - if (projectRight) - dx += ((lw + 1) >> 1); - dy = lw; - miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, - x, y, dx, dy); - } - else if (dx == 0) - { - leftFace->xa = (double) lw / 2.0; - leftFace->ya = 0; - leftFace->k = (double) (lw * dy) / 2.0; - rightFace->xa = -leftFace->xa; - rightFace->ya = 0; - rightFace->k = leftFace->k; - y = y1; - if (projectLeft) - y -= lw >> 1; - x = x1 - (lw >> 1); - dy = y2 - y; - if (projectRight) - dy += ((lw + 1) >> 1); - dx = lw; - miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, - x, y, dx, dy); - } - else - { - l = ((double) lw) / 2.0; - L = hypot ((double) dx, (double) dy); - - if (dx < 0) - { - right = &rights[1]; - left = &lefts[0]; - top = &rights[0]; - bottom = &lefts[1]; - } - else - { - right = &rights[0]; - left = &lefts[1]; - top = &lefts[0]; - bottom = &rights[1]; - } - r = l / L; - - /* coord of upper bound at integral y */ - ya = -r * dx; - xa = r * dy; - - if (projectLeft | projectRight) - { - projectXoff = -ya; - projectYoff = xa; - } - - /* xa * dy - ya * dx */ - k = l * L; - - leftFace->xa = xa; - leftFace->ya = ya; - leftFace->k = k; - rightFace->xa = -xa; - rightFace->ya = -ya; - rightFace->k = k; - - if (projectLeft) - righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, - k, dx, dy, x1, y1, 0, right); - else - righty = miPolyBuildEdge (xa, ya, - k, dx, dy, x1, y1, 0, right); - - /* coord of lower bound at integral y */ - ya = -ya; - xa = -xa; - - /* xa * dy - ya * dx */ - k = - k; - - if (projectLeft) - lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, - k, dx, dy, x1, y1, 1, left); - else - lefty = miPolyBuildEdge (xa, ya, - k, dx, dy, x1, y1, 1, left); - - /* coord of top face at integral y */ - - if (signdx > 0) - { - ya = -ya; - xa = -xa; - } - - if (projectLeft) - { - double xap = xa - projectXoff; - double yap = ya - projectYoff; - topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, - -dy, dx, x1, y1, dx > 0, top); - } - else - topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top); - - /* coord of bottom face at integral y */ - - if (projectRight) - { - double xap = xa + projectXoff; - double yap = ya + projectYoff; - bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, - -dy, dx, x2, y2, dx < 0, bottom); - maxy = -ya + projectYoff; - } - else - { - bottomy = miPolyBuildEdge (xa, ya, - 0.0, -dy, dx, x2, y2, dx < 0, bottom); - maxy = -ya; - } - - finaly = ICEIL (maxy) + y2; - - if (dx < 0) - { - left->height = bottomy - lefty; - right->height = finaly - righty; - top->height = righty - topy; - } - else - { - right->height = bottomy - righty; - left->height = finaly - lefty; - top->height = lefty - topy; - } - bottom->height = finaly - bottomy; - miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, - bottom->height + bottomy - topy, lefts, rights, 2, 2); - } -} - -static SpanDataPtr -miSetupSpanData (GCPtr pGC, SpanDataPtr spanData, int npt) -{ - if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop(pGC->alu)) - return (SpanDataPtr) NULL; - if (pGC->lineStyle == LineDoubleDash) - miInitSpanGroup (&spanData->bgGroup); - miInitSpanGroup (&spanData->fgGroup); - return spanData; -} - -static void -miCleanupSpanData (DrawablePtr pDrawable, GCPtr pGC, SpanDataPtr spanData) -{ - if (pGC->lineStyle == LineDoubleDash) - { - XID oldPixel, pixel; - - pixel = pGC->bgPixel; - oldPixel = pGC->fgPixel; - if (pixel != oldPixel) - { - DoChangeGC (pGC, GCForeground, &pixel, FALSE); - ValidateGC (pDrawable, pGC); - } - miFillUniqueSpanGroup (pDrawable, pGC, &spanData->bgGroup); - miFreeSpanGroup (&spanData->bgGroup); - if (pixel != oldPixel) - { - DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); - ValidateGC (pDrawable, pGC); - } - } - miFillUniqueSpanGroup (pDrawable, pGC, &spanData->fgGroup); - miFreeSpanGroup (&spanData->fgGroup); -} - -void -miWideLine (DrawablePtr pDrawable, GCPtr pGC, - int mode, int npt, DDXPointPtr pPts) -{ - int x1, y1, x2, y2; - SpanDataRec spanDataRec; - SpanDataPtr spanData; - long pixel; - Bool projectLeft, projectRight; - LineFaceRec leftFace, rightFace, prevRightFace; - LineFaceRec firstFace; - int first; - Bool somethingDrawn = FALSE; - Bool selfJoin; - - spanData = miSetupSpanData (pGC, &spanDataRec, npt); - pixel = pGC->fgPixel; - x2 = pPts->x; - y2 = pPts->y; - first = TRUE; - selfJoin = FALSE; - if (npt > 1) - { - if (mode == CoordModePrevious) - { - int nptTmp; - DDXPointPtr pPtsTmp; - - x1 = x2; - y1 = y2; - nptTmp = npt; - pPtsTmp = pPts + 1; - while (--nptTmp) - { - x1 += pPtsTmp->x; - y1 += pPtsTmp->y; - ++pPtsTmp; - } - if (x2 == x1 && y2 == y1) - selfJoin = TRUE; - } - else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) - { - selfJoin = TRUE; - } - } - projectLeft = pGC->capStyle == CapProjecting && !selfJoin; - projectRight = FALSE; - while (--npt) - { - x1 = x2; - y1 = y2; - ++pPts; - x2 = pPts->x; - y2 = pPts->y; - if (mode == CoordModePrevious) - { - x2 += x1; - y2 += y1; - } - if (x1 != x2 || y1 != y2) - { - somethingDrawn = TRUE; - if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin) - projectRight = TRUE; - miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2, - projectLeft, projectRight, &leftFace, &rightFace); - if (first) - { - if (selfJoin) - firstFace = leftFace; - else if (pGC->capStyle == CapRound) - { - if (pGC->lineWidth == 1 && !spanData) - miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1); - else - miLineArc (pDrawable, pGC, pixel, spanData, - &leftFace, (LineFacePtr) NULL, - (double)0.0, (double)0.0, - TRUE); - } - } - else - { - miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, - &prevRightFace); - } - prevRightFace = rightFace; - first = FALSE; - projectLeft = FALSE; - } - if (npt == 1 && somethingDrawn) - { - if (selfJoin) - miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, - &rightFace); - else if (pGC->capStyle == CapRound) - { - if (pGC->lineWidth == 1 && !spanData) - miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2); - else - miLineArc (pDrawable, pGC, pixel, spanData, - (LineFacePtr) NULL, &rightFace, - (double)0.0, (double)0.0, - TRUE); - } - } - } - /* handle crock where all points are coincedent */ - if (!somethingDrawn) - { - projectLeft = pGC->capStyle == CapProjecting; - miWideSegment (pDrawable, pGC, pixel, spanData, - x2, y2, x2, y2, projectLeft, projectLeft, - &leftFace, &rightFace); - if (pGC->capStyle == CapRound) - { - miLineArc (pDrawable, pGC, pixel, spanData, - &leftFace, (LineFacePtr) NULL, - (double)0.0, (double)0.0, - TRUE); - rightFace.dx = -1; /* sleezy hack to make it work */ - miLineArc (pDrawable, pGC, pixel, spanData, - (LineFacePtr) NULL, &rightFace, - (double)0.0, (double)0.0, - TRUE); - } - } - if (spanData) - miCleanupSpanData (pDrawable, pGC, spanData); -} - -#define V_TOP 0 -#define V_RIGHT 1 -#define V_BOTTOM 2 -#define V_LEFT 3 - -static void -miWideDashSegment ( - DrawablePtr pDrawable, - GCPtr pGC, - SpanDataPtr spanData, - int *pDashOffset, - int *pDashIndex, - int x1, - int y1, - int x2, - int y2, - Bool projectLeft, - Bool projectRight, - LineFacePtr leftFace, - LineFacePtr rightFace) -{ - int dashIndex, dashRemain; - unsigned char *pDash; - double L, l; - double k; - PolyVertexRec vertices[4]; - PolyVertexRec saveRight, saveBottom; - PolySlopeRec slopes[4]; - PolyEdgeRec left[2], right[2]; - LineFaceRec lcapFace, rcapFace; - int nleft, nright; - int h; - int y; - int dy, dx; - unsigned long pixel; - double LRemain; - double r; - double rdx, rdy; - double dashDx, dashDy; - double saveK = 0.0; - Bool first = TRUE; - double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0; - unsigned long fgPixel, bgPixel; - - dx = x2 - x1; - dy = y2 - y1; - dashIndex = *pDashIndex; - pDash = pGC->dash; - dashRemain = pDash[dashIndex] - *pDashOffset; - fgPixel = pGC->fgPixel; - bgPixel = pGC->bgPixel; - if (pGC->fillStyle == FillOpaqueStippled || - pGC->fillStyle == FillTiled) - { - bgPixel = fgPixel; - } - - l = ((double) pGC->lineWidth) / 2.0; - if (dx == 0) - { - L = dy; - rdx = 0; - rdy = l; - if (dy < 0) - { - L = -dy; - rdy = -l; - } - } - else if (dy == 0) - { - L = dx; - rdx = l; - rdy = 0; - if (dx < 0) - { - L = -dx; - rdx = -l; - } - } - else - { - L = hypot ((double) dx, (double) dy); - r = l / L; - - rdx = r * dx; - rdy = r * dy; - } - k = l * L; - LRemain = L; - /* All position comments are relative to a line with dx and dy > 0, - * but the code does not depend on this */ - /* top */ - slopes[V_TOP].dx = dx; - slopes[V_TOP].dy = dy; - slopes[V_TOP].k = k; - /* right */ - slopes[V_RIGHT].dx = -dy; - slopes[V_RIGHT].dy = dx; - slopes[V_RIGHT].k = 0; - /* bottom */ - slopes[V_BOTTOM].dx = -dx; - slopes[V_BOTTOM].dy = -dy; - slopes[V_BOTTOM].k = k; - /* left */ - slopes[V_LEFT].dx = dy; - slopes[V_LEFT].dy = -dx; - slopes[V_LEFT].k = 0; - - /* preload the start coordinates */ - vertices[V_RIGHT].x = vertices[V_TOP].x = rdy; - vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx; - - vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy; - vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx; - - if (projectLeft) - { - vertices[V_TOP].x -= rdx; - vertices[V_TOP].y -= rdy; - - vertices[V_LEFT].x -= rdx; - vertices[V_LEFT].y -= rdy; - - slopes[V_LEFT].k = rdx * dx + rdy * dy; - } - - lcenterx = x1; - lcentery = y1; - - if (pGC->capStyle == CapRound) - { - lcapFace.dx = dx; - lcapFace.dy = dy; - lcapFace.x = x1; - lcapFace.y = y1; - - rcapFace.dx = -dx; - rcapFace.dy = -dy; - rcapFace.x = x1; - rcapFace.y = y1; - } - while (LRemain > dashRemain) - { - dashDx = (dashRemain * dx) / L; - dashDy = (dashRemain * dy) / L; - - rcenterx = lcenterx + dashDx; - rcentery = lcentery + dashDy; - - vertices[V_RIGHT].x += dashDx; - vertices[V_RIGHT].y += dashDy; - - vertices[V_BOTTOM].x += dashDx; - vertices[V_BOTTOM].y += dashDy; - - slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy; - - if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) - { - if (pGC->lineStyle == LineOnOffDash && - pGC->capStyle == CapProjecting) - { - saveRight = vertices[V_RIGHT]; - saveBottom = vertices[V_BOTTOM]; - saveK = slopes[V_RIGHT].k; - - if (!first) - { - vertices[V_TOP].x -= rdx; - vertices[V_TOP].y -= rdy; - - vertices[V_LEFT].x -= rdx; - vertices[V_LEFT].y -= rdy; - - slopes[V_LEFT].k = vertices[V_LEFT].x * - slopes[V_LEFT].dy - - vertices[V_LEFT].y * - slopes[V_LEFT].dx; - } - - vertices[V_RIGHT].x += rdx; - vertices[V_RIGHT].y += rdy; - - vertices[V_BOTTOM].x += rdx; - vertices[V_BOTTOM].y += rdy; - - slopes[V_RIGHT].k = vertices[V_RIGHT].x * - slopes[V_RIGHT].dy - - vertices[V_RIGHT].y * - slopes[V_RIGHT].dx; - } - y = miPolyBuildPoly (vertices, slopes, 4, x1, y1, - left, right, &nleft, &nright, &h); - pixel = (dashIndex & 1) ? bgPixel : fgPixel; - miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); - - if (pGC->lineStyle == LineOnOffDash) - { - switch (pGC->capStyle) - { - case CapProjecting: - vertices[V_BOTTOM] = saveBottom; - vertices[V_RIGHT] = saveRight; - slopes[V_RIGHT].k = saveK; - break; - case CapRound: - if (!first) - { - if (dx < 0) - { - lcapFace.xa = -vertices[V_LEFT].x; - lcapFace.ya = -vertices[V_LEFT].y; - lcapFace.k = slopes[V_LEFT].k; - } - else - { - lcapFace.xa = vertices[V_TOP].x; - lcapFace.ya = vertices[V_TOP].y; - lcapFace.k = -slopes[V_LEFT].k; - } - miLineArc (pDrawable, pGC, pixel, spanData, - &lcapFace, (LineFacePtr) NULL, - lcenterx, lcentery, FALSE); - } - if (dx < 0) - { - rcapFace.xa = vertices[V_BOTTOM].x; - rcapFace.ya = vertices[V_BOTTOM].y; - rcapFace.k = slopes[V_RIGHT].k; - } - else - { - rcapFace.xa = -vertices[V_RIGHT].x; - rcapFace.ya = -vertices[V_RIGHT].y; - rcapFace.k = -slopes[V_RIGHT].k; - } - miLineArc (pDrawable, pGC, pixel, spanData, - (LineFacePtr) NULL, &rcapFace, - rcenterx, rcentery, FALSE); - break; - } - } - } - LRemain -= dashRemain; - ++dashIndex; - if (dashIndex == pGC->numInDashList) - dashIndex = 0; - dashRemain = pDash[dashIndex]; - - lcenterx = rcenterx; - lcentery = rcentery; - - vertices[V_TOP] = vertices[V_RIGHT]; - vertices[V_LEFT] = vertices[V_BOTTOM]; - slopes[V_LEFT].k = -slopes[V_RIGHT].k; - first = FALSE; - } - - if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) - { - vertices[V_TOP].x -= dx; - vertices[V_TOP].y -= dy; - - vertices[V_LEFT].x -= dx; - vertices[V_LEFT].y -= dy; - - vertices[V_RIGHT].x = rdy; - vertices[V_RIGHT].y = -rdx; - - vertices[V_BOTTOM].x = -rdy; - vertices[V_BOTTOM].y = rdx; - - - if (projectRight) - { - vertices[V_RIGHT].x += rdx; - vertices[V_RIGHT].y += rdy; - - vertices[V_BOTTOM].x += rdx; - vertices[V_BOTTOM].y += rdy; - slopes[V_RIGHT].k = vertices[V_RIGHT].x * - slopes[V_RIGHT].dy - - vertices[V_RIGHT].y * - slopes[V_RIGHT].dx; - } - else - slopes[V_RIGHT].k = 0; - - if (!first && pGC->lineStyle == LineOnOffDash && - pGC->capStyle == CapProjecting) - { - vertices[V_TOP].x -= rdx; - vertices[V_TOP].y -= rdy; - - vertices[V_LEFT].x -= rdx; - vertices[V_LEFT].y -= rdy; - slopes[V_LEFT].k = vertices[V_LEFT].x * - slopes[V_LEFT].dy - - vertices[V_LEFT].y * - slopes[V_LEFT].dx; - } - else - slopes[V_LEFT].k += dx * dx + dy * dy; - - - y = miPolyBuildPoly (vertices, slopes, 4, x2, y2, - left, right, &nleft, &nright, &h); - - pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; - miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); - if (!first && pGC->lineStyle == LineOnOffDash && - pGC->capStyle == CapRound) - { - lcapFace.x = x2; - lcapFace.y = y2; - if (dx < 0) - { - lcapFace.xa = -vertices[V_LEFT].x; - lcapFace.ya = -vertices[V_LEFT].y; - lcapFace.k = slopes[V_LEFT].k; - } - else - { - lcapFace.xa = vertices[V_TOP].x; - lcapFace.ya = vertices[V_TOP].y; - lcapFace.k = -slopes[V_LEFT].k; - } - miLineArc (pDrawable, pGC, pixel, spanData, - &lcapFace, (LineFacePtr) NULL, - rcenterx, rcentery, FALSE); - } - } - dashRemain = ((double) dashRemain) - LRemain; - if (dashRemain == 0) - { - dashIndex++; - if (dashIndex == pGC->numInDashList) - dashIndex = 0; - dashRemain = pDash[dashIndex]; - } - - leftFace->x = x1; - leftFace->y = y1; - leftFace->dx = dx; - leftFace->dy = dy; - leftFace->xa = rdy; - leftFace->ya = -rdx; - leftFace->k = k; - - rightFace->x = x2; - rightFace->y = y2; - rightFace->dx = -dx; - rightFace->dy = -dy; - rightFace->xa = -rdy; - rightFace->ya = rdx; - rightFace->k = k; - - *pDashIndex = dashIndex; - *pDashOffset = pDash[dashIndex] - dashRemain; -} - -void -miWideDash (DrawablePtr pDrawable, GCPtr pGC, - int mode, int npt, DDXPointPtr pPts) -{ - int x1, y1, x2, y2; - unsigned long pixel; - Bool projectLeft, projectRight; - LineFaceRec leftFace, rightFace, prevRightFace; - LineFaceRec firstFace; - int first; - int dashIndex, dashOffset; - int prevDashIndex; - SpanDataRec spanDataRec; - SpanDataPtr spanData; - Bool somethingDrawn = FALSE; - Bool selfJoin; - Bool endIsFg = FALSE, startIsFg = FALSE; - Bool firstIsFg = FALSE, prevIsFg = FALSE; - -#if 0 - /* XXX backward compatibility */ - if (pGC->lineWidth == 0) - { - miZeroDashLine (pDrawable, pGC, mode, npt, pPts); - return; - } -#endif - if (pGC->lineStyle == LineDoubleDash && - (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled)) - { - miWideLine (pDrawable, pGC, mode, npt, pPts); - return; - } - if (npt == 0) - return; - spanData = miSetupSpanData (pGC, &spanDataRec, npt); - x2 = pPts->x; - y2 = pPts->y; - first = TRUE; - selfJoin = FALSE; - if (mode == CoordModePrevious) - { - int nptTmp; - DDXPointPtr pPtsTmp; - - x1 = x2; - y1 = y2; - nptTmp = npt; - pPtsTmp = pPts + 1; - while (--nptTmp) - { - x1 += pPtsTmp->x; - y1 += pPtsTmp->y; - ++pPtsTmp; - } - if (x2 == x1 && y2 == y1) - selfJoin = TRUE; - } - else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) - { - selfJoin = TRUE; - } - projectLeft = pGC->capStyle == CapProjecting && !selfJoin; - projectRight = FALSE; - dashIndex = 0; - dashOffset = 0; - miStepDash ((int)pGC->dashOffset, &dashIndex, - pGC->dash, (int)pGC->numInDashList, &dashOffset); - while (--npt) - { - x1 = x2; - y1 = y2; - ++pPts; - x2 = pPts->x; - y2 = pPts->y; - if (mode == CoordModePrevious) - { - x2 += x1; - y2 += y1; - } - if (x1 != x2 || y1 != y2) - { - somethingDrawn = TRUE; - if (npt == 1 && pGC->capStyle == CapProjecting && - (!selfJoin || !firstIsFg)) - projectRight = TRUE; - prevDashIndex = dashIndex; - miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex, - x1, y1, x2, y2, - projectLeft, projectRight, &leftFace, &rightFace); - startIsFg = !(prevDashIndex & 1); - endIsFg = (dashIndex & 1) ^ (dashOffset != 0); - if (pGC->lineStyle == LineDoubleDash || startIsFg) - { - pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel; - if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) - { - if (first && selfJoin) - { - firstFace = leftFace; - firstIsFg = startIsFg; - } - else if (pGC->capStyle == CapRound) - miLineArc (pDrawable, pGC, pixel, spanData, - &leftFace, (LineFacePtr) NULL, - (double)0.0, (double)0.0, TRUE); - } - else - { - miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, - &prevRightFace); - } - } - prevRightFace = rightFace; - prevIsFg = endIsFg; - first = FALSE; - projectLeft = FALSE; - } - if (npt == 1 && somethingDrawn) - { - if (pGC->lineStyle == LineDoubleDash || endIsFg) - { - pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel; - if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) - { - miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, - &rightFace); - } - else - { - if (pGC->capStyle == CapRound) - miLineArc (pDrawable, pGC, pixel, spanData, - (LineFacePtr) NULL, &rightFace, - (double)0.0, (double)0.0, TRUE); - } - } - else - { - /* glue a cap to the start of the line if - * we're OnOffDash and ended on odd dash - */ - if (selfJoin && firstIsFg) - { - pixel = pGC->fgPixel; - if (pGC->capStyle == CapProjecting) - miLineProjectingCap (pDrawable, pGC, pixel, spanData, - &firstFace, TRUE, - (double)0.0, (double)0.0, TRUE); - else if (pGC->capStyle == CapRound) - miLineArc (pDrawable, pGC, pixel, spanData, - &firstFace, (LineFacePtr) NULL, - (double)0.0, (double)0.0, TRUE); - } - } - } - } - /* handle crock where all points are coincident */ - if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) - { - /* not the same as endIsFg computation above */ - pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; - switch (pGC->capStyle) { - case CapRound: - miLineArc (pDrawable, pGC, pixel, spanData, - (LineFacePtr) NULL, (LineFacePtr) NULL, - (double)x2, (double)y2, - FALSE); - break; - case CapProjecting: - x1 = pGC->lineWidth; - miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, - x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1); - break; - } - } - if (spanData) - miCleanupSpanData (pDrawable, pGC, spanData); -} +/*
+
+Copyright 1988, 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.
+
+*/
+
+/* Author: Keith Packard, MIT X Consortium */
+
+/*
+ * Mostly integer wideline code. Uses a technique similar to
+ * bresenham zero-width lines, except walks an X edge
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#ifdef _XOPEN_SOURCE
+#include <math.h>
+#else
+#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */
+#include <math.h>
+#undef _XOPEN_SOURCE
+#endif
+#include <X11/X.h>
+#include "windowstr.h"
+#include "gcstruct.h"
+#include "regionstr.h"
+#include "miwideline.h"
+#include "mi.h"
+
+static Bool
+InitSpans(Spans *spans, size_t nspans)
+{
+ spans->points = malloc(nspans * sizeof (*spans->points));
+ if (!spans->points)
+ return FALSE;
+ spans->widths = malloc(nspans * sizeof (*spans->widths));
+ if (!spans->widths)
+ {
+ free(spans->points);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * interface data to span-merging polygon filler
+ */
+
+typedef struct _SpanData {
+ SpanGroup fgGroup, bgGroup;
+} SpanDataRec, *SpanDataPtr;
+
+static void
+AppendSpanGroup(GCPtr pGC, unsigned long pixel, Spans *spanPtr, SpanDataPtr spanData)
+{
+ SpanGroup *group, *othergroup = NULL;
+ if (pixel == pGC->fgPixel)
+ {
+ group = &spanData->fgGroup;
+ if (pGC->lineStyle == LineDoubleDash)
+ othergroup = &spanData->bgGroup;
+ }
+ else
+ {
+ group = &spanData->bgGroup;
+ othergroup = &spanData->fgGroup;
+ }
+ miAppendSpans (group, othergroup, spanPtr);
+}
+
+
+static void miLineArc(DrawablePtr pDraw, GCPtr pGC,
+ unsigned long pixel, SpanDataPtr spanData,
+ LineFacePtr leftFace,
+ LineFacePtr rightFace,
+ double xorg, double yorg, Bool isInt);
+
+
+/*
+ * spans-based polygon filler
+ */
+
+static void
+fillSpans(DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, Spans *spans, SpanDataPtr spanData)
+{
+ if (!spanData)
+ {
+ ChangeGCVal oldPixel, tmpPixel;
+ oldPixel.val = pGC->fgPixel;
+ if (pixel != oldPixel.val)
+ {
+ tmpPixel.val = (XID)pixel;
+ ChangeGC (NullClient, pGC, GCForeground, &tmpPixel);
+ ValidateGC (pDrawable, pGC);
+ }
+ (*pGC->ops->FillSpans) (pDrawable, pGC, spans->count, spans->points, spans->widths, TRUE);
+ free(spans->widths);
+ free(spans->points);
+ if (pixel != oldPixel.val)
+ {
+ ChangeGC (NullClient, pGC, GCForeground, &oldPixel);
+ ValidateGC (pDrawable, pGC);
+ }
+ }
+ else
+ AppendSpanGroup (pGC, pixel, spans, spanData);
+}
+
+static void
+miFillPolyHelper (DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel,
+ SpanDataPtr spanData, int y, int overall_height,
+ PolyEdgePtr left, PolyEdgePtr right,
+ int left_count, int right_count)
+{
+ int left_x = 0, left_e = 0;
+ int left_stepx = 0;
+ int left_signdx = 0;
+ int left_dy = 0, left_dx = 0;
+
+ int right_x = 0, right_e = 0;
+ int right_stepx = 0;
+ int right_signdx = 0;
+ int right_dy = 0, right_dx = 0;
+
+ int height = 0;
+ int left_height = 0, right_height = 0;
+
+ DDXPointPtr ppt;
+ int *pwidth;
+ int xorg;
+ Spans spanRec;
+
+ if (!InitSpans(&spanRec, overall_height))
+ return;
+ ppt = spanRec.points;
+ pwidth = spanRec.widths;
+
+ xorg = 0;
+ if (pGC->miTranslate)
+ {
+ y += pDrawable->y;
+ xorg = pDrawable->x;
+ }
+ while ((left_count || left_height) &&
+ (right_count || right_height))
+ {
+ if (!left_height && left_count)
+ {
+ left_height = left->height;
+ left_x = left->x;
+ left_stepx = left->stepx;
+ left_signdx = left->signdx;
+ left_e = left->e;
+ left_dy = left->dy;
+ left_dx = left->dx;
+ --left_count;
+ ++left;
+ }
+
+ if (!right_height && right_count)
+ {
+ right_height = right->height;
+ right_x = right->x;
+ right_stepx = right->stepx;
+ right_signdx = right->signdx;
+ right_e = right->e;
+ right_dy = right->dy;
+ right_dx = right->dx;
+ --right_count;
+ ++right;
+ }
+
+ height = left_height;
+ if (height > right_height)
+ height = right_height;
+
+ left_height -= height;
+ right_height -= height;
+
+ while (--height >= 0)
+ {
+ if (right_x >= left_x)
+ {
+ ppt->y = y;
+ ppt->x = left_x + xorg;
+ ppt++;
+ *pwidth++ = right_x - left_x + 1;
+ }
+ y++;
+
+ left_x += left_stepx;
+ left_e += left_dx;
+ if (left_e > 0)
+ {
+ left_x += left_signdx;
+ left_e -= left_dy;
+ }
+
+ right_x += right_stepx;
+ right_e += right_dx;
+ if (right_e > 0)
+ {
+ right_x += right_signdx;
+ right_e -= right_dy;
+ }
+ }
+ }
+ spanRec.count = ppt - spanRec.points;
+ fillSpans (pDrawable, pGC, pixel, &spanRec, spanData);
+}
+
+static void
+miFillRectPolyHelper (
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ unsigned long pixel,
+ SpanDataPtr spanData,
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ DDXPointPtr ppt;
+ int *pwidth;
+ ChangeGCVal oldPixel, tmpPixel;
+ Spans spanRec;
+ xRectangle rect;
+
+ if (!spanData)
+ {
+ rect.x = x;
+ rect.y = y;
+ rect.width = w;
+ rect.height = h;
+ oldPixel.val = pGC->fgPixel;
+ if (pixel != oldPixel.val)
+ {
+ tmpPixel.val = (XID)pixel;
+ ChangeGC (NullClient, pGC, GCForeground, &tmpPixel);
+ ValidateGC (pDrawable, pGC);
+ }
+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect);
+ if (pixel != oldPixel.val)
+ {
+ ChangeGC (NullClient, pGC, GCForeground, &oldPixel);
+ ValidateGC (pDrawable, pGC);
+ }
+ }
+ else
+ {
+ if (!InitSpans(&spanRec, h))
+ return;
+ ppt = spanRec.points;
+ pwidth = spanRec.widths;
+
+ if (pGC->miTranslate)
+ {
+ y += pDrawable->y;
+ x += pDrawable->x;
+ }
+ while (h--)
+ {
+ ppt->x = x;
+ ppt->y = y;
+ ppt++;
+ *pwidth++ = w;
+ y++;
+ }
+ spanRec.count = ppt - spanRec.points;
+ AppendSpanGroup (pGC, pixel, &spanRec, spanData);
+ }
+}
+
+/* static */ int
+miPolyBuildEdge (
+ double x0,
+ double y0,
+ double k, /* x0 * dy - y0 * dx */
+ int dx,
+ int dy,
+ int xi,
+ int yi,
+ int left,
+ PolyEdgePtr edge)
+{
+ int x, y, e;
+ int xady;
+
+ if (dy < 0)
+ {
+ dy = -dy;
+ dx = -dx;
+ k = -k;
+ }
+
+#ifdef NOTDEF
+ {
+ double realk, kerror;
+ realk = x0 * dy - y0 * dx;
+ kerror = Fabs (realk - k);
+ if (kerror > .1)
+ printf ("realk: %g k: %g\n", realk, k);
+ }
+#endif
+ y = ICEIL (y0);
+ xady = ICEIL (k) + y * dx;
+
+ if (xady <= 0)
+ x = - (-xady / dy) - 1;
+ else
+ x = (xady - 1) / dy;
+
+ e = xady - x * dy;
+
+ if (dx >= 0)
+ {
+ edge->signdx = 1;
+ edge->stepx = dx / dy;
+ edge->dx = dx % dy;
+ }
+ else
+ {
+ edge->signdx = -1;
+ edge->stepx = - (-dx / dy);
+ edge->dx = -dx % dy;
+ e = dy - e + 1;
+ }
+ edge->dy = dy;
+ edge->x = x + left + xi;
+ edge->e = e - dy; /* bias to compare against 0 instead of dy */
+ return y + yi;
+}
+
+#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr)))
+
+/* static */ int
+miPolyBuildPoly (
+ PolyVertexPtr vertices,
+ PolySlopePtr slopes,
+ int count,
+ int xi,
+ int yi,
+ PolyEdgePtr left,
+ PolyEdgePtr right,
+ int *pnleft,
+ int *pnright,
+ int *h)
+{
+ int top, bottom;
+ double miny, maxy;
+ int i;
+ int j;
+ int clockwise;
+ int slopeoff;
+ int s;
+ int nright, nleft;
+ int y, lasty = 0, bottomy, topy = 0;
+
+ /* find the top of the polygon */
+ maxy = miny = vertices[0].y;
+ bottom = top = 0;
+ for (i = 1; i < count; i++)
+ {
+ if (vertices[i].y < miny)
+ {
+ top = i;
+ miny = vertices[i].y;
+ }
+ if (vertices[i].y >= maxy)
+ {
+ bottom = i;
+ maxy = vertices[i].y;
+ }
+ }
+ clockwise = 1;
+ slopeoff = 0;
+
+ i = top;
+ j = StepAround (top, -1, count);
+
+ if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx)
+ {
+ clockwise = -1;
+ slopeoff = -1;
+ }
+
+ bottomy = ICEIL (maxy) + yi;
+
+ nright = 0;
+
+ s = StepAround (top, slopeoff, count);
+ i = top;
+ while (i != bottom)
+ {
+ if (slopes[s].dy != 0)
+ {
+ y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
+ slopes[s].k,
+ slopes[s].dx, slopes[s].dy,
+ xi, yi, 0,
+ &right[nright]);
+ if (nright != 0)
+ right[nright-1].height = y - lasty;
+ else
+ topy = y;
+ nright++;
+ lasty = y;
+ }
+
+ i = StepAround (i, clockwise, count);
+ s = StepAround (s, clockwise, count);
+ }
+ if (nright != 0)
+ right[nright-1].height = bottomy - lasty;
+
+ if (slopeoff == 0)
+ slopeoff = -1;
+ else
+ slopeoff = 0;
+
+ nleft = 0;
+ s = StepAround (top, slopeoff, count);
+ i = top;
+ while (i != bottom)
+ {
+ if (slopes[s].dy != 0)
+ {
+ y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
+ slopes[s].k,
+ slopes[s].dx, slopes[s].dy, xi, yi, 1,
+ &left[nleft]);
+
+ if (nleft != 0)
+ left[nleft-1].height = y - lasty;
+ nleft++;
+ lasty = y;
+ }
+ i = StepAround (i, -clockwise, count);
+ s = StepAround (s, -clockwise, count);
+ }
+ if (nleft != 0)
+ left[nleft-1].height = bottomy - lasty;
+ *pnleft = nleft;
+ *pnright = nright;
+ *h = bottomy - topy;
+ return topy;
+}
+
+static void
+miLineOnePoint (
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ unsigned long pixel,
+ SpanDataPtr spanData,
+ int x,
+ int y)
+{
+ DDXPointRec pt;
+ int wid;
+ unsigned long oldPixel;
+
+ MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel);
+ if (pGC->fillStyle == FillSolid)
+ {
+ pt.x = x;
+ pt.y = y;
+ (*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt);
+ }
+ else
+ {
+ wid = 1;
+ if (pGC->miTranslate)
+ {
+ x += pDrawable->x;
+ y += pDrawable->y;
+ }
+ pt.x = x;
+ pt.y = y;
+ (*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE);
+ }
+ MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel);
+}
+
+static void
+miLineJoin (
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ unsigned long pixel,
+ SpanDataPtr spanData,
+ LineFacePtr pLeft,
+ LineFacePtr pRight)
+{
+ double mx = 0, my = 0;
+ double denom = 0.0;
+ PolyVertexRec vertices[4];
+ PolySlopeRec slopes[4];
+ int edgecount;
+ PolyEdgeRec left[4], right[4];
+ int nleft, nright;
+ int y, height;
+ int swapslopes;
+ int joinStyle = pGC->joinStyle;
+ int lw = pGC->lineWidth;
+
+ if (lw == 1 && !spanData) {
+ /* See if one of the lines will draw the joining pixel */
+ if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0))
+ return;
+ if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0))
+ return;
+ if (joinStyle != JoinRound) {
+ denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
+ if (denom == 0)
+ return; /* no join to draw */
+ }
+ if (joinStyle != JoinMiter) {
+ miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y);
+ return;
+ }
+ } else {
+ if (joinStyle == JoinRound)
+ {
+ miLineArc(pDrawable, pGC, pixel, spanData,
+ pLeft, pRight,
+ (double)0.0, (double)0.0, TRUE);
+ return;
+ }
+ denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
+ if (denom == 0.0)
+ return; /* no join to draw */
+ }
+
+ swapslopes = 0;
+ if (denom > 0)
+ {
+ pLeft->xa = -pLeft->xa;
+ pLeft->ya = -pLeft->ya;
+ pLeft->dx = -pLeft->dx;
+ pLeft->dy = -pLeft->dy;
+ }
+ else
+ {
+ swapslopes = 1;
+ pRight->xa = -pRight->xa;
+ pRight->ya = -pRight->ya;
+ pRight->dx = -pRight->dx;
+ pRight->dy = -pRight->dy;
+ }
+
+ vertices[0].x = pRight->xa;
+ vertices[0].y = pRight->ya;
+ slopes[0].dx = -pRight->dy;
+ slopes[0].dy = pRight->dx;
+ slopes[0].k = 0;
+
+ vertices[1].x = 0;
+ vertices[1].y = 0;
+ slopes[1].dx = pLeft->dy;
+ slopes[1].dy = -pLeft->dx;
+ slopes[1].k = 0;
+
+ vertices[2].x = pLeft->xa;
+ vertices[2].y = pLeft->ya;
+
+ if (joinStyle == JoinMiter)
+ {
+ my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
+ pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx )) /
+ denom;
+ if (pLeft->dy != 0)
+ {
+ mx = pLeft->xa + (my - pLeft->ya) *
+ (double) pLeft->dx / (double) pLeft->dy;
+ }
+ else
+ {
+ mx = pRight->xa + (my - pRight->ya) *
+ (double) pRight->dx / (double) pRight->dy;
+ }
+ /* check miter limit */
+ if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
+ joinStyle = JoinBevel;
+ }
+
+ if (joinStyle == JoinMiter)
+ {
+ slopes[2].dx = pLeft->dx;
+ slopes[2].dy = pLeft->dy;
+ slopes[2].k = pLeft->k;
+ if (swapslopes)
+ {
+ slopes[2].dx = -slopes[2].dx;
+ slopes[2].dy = -slopes[2].dy;
+ slopes[2].k = -slopes[2].k;
+ }
+ vertices[3].x = mx;
+ vertices[3].y = my;
+ slopes[3].dx = pRight->dx;
+ slopes[3].dy = pRight->dy;
+ slopes[3].k = pRight->k;
+ if (swapslopes)
+ {
+ slopes[3].dx = -slopes[3].dx;
+ slopes[3].dy = -slopes[3].dy;
+ slopes[3].k = -slopes[3].k;
+ }
+ edgecount = 4;
+ }
+ else
+ {
+ double scale, dx, dy, adx, ady;
+
+ adx = dx = pRight->xa - pLeft->xa;
+ ady = dy = pRight->ya - pLeft->ya;
+ if (adx < 0)
+ adx = -adx;
+ if (ady < 0)
+ ady = -ady;
+ scale = ady;
+ if (adx > ady)
+ scale = adx;
+ slopes[2].dx = (dx * 65536) / scale;
+ slopes[2].dy = (dy * 65536) / scale;
+ slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
+ (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
+ edgecount = 3;
+ }
+
+ y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
+ left, right, &nleft, &nright, &height);
+ miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright);
+}
+
+static int
+miLineArcI (
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int xorg,
+ int yorg,
+ DDXPointPtr points,
+ int *widths)
+{
+ DDXPointPtr tpts, bpts;
+ int *twids, *bwids;
+ int x, y, e, ex, slw;
+
+ tpts = points;
+ twids = widths;
+ if (pGC->miTranslate)
+ {
+ xorg += pDraw->x;
+ yorg += pDraw->y;
+ }
+ slw = pGC->lineWidth;
+ if (slw == 1)
+ {
+ tpts->x = xorg;
+ tpts->y = yorg;
+ *twids = 1;
+ return 1;
+ }
+ bpts = tpts + slw;
+ bwids = twids + slw;
+ y = (slw >> 1) + 1;
+ if (slw & 1)
+ e = - ((y << 2) + 3);
+ else
+ e = - (y << 3);
+ ex = -4;
+ x = 0;
+ while (y)
+ {
+ e += (y << 3) - 4;
+ while (e >= 0)
+ {
+ x++;
+ e += (ex = -((x << 3) + 4));
+ }
+ y--;
+ slw = (x << 1) + 1;
+ if ((e == ex) && (slw > 1))
+ slw--;
+ tpts->x = xorg - x;
+ tpts->y = yorg - y;
+ tpts++;
+ *twids++ = slw;
+ if ((y != 0) && ((slw > 1) || (e != ex)))
+ {
+ bpts--;
+ bpts->x = xorg - x;
+ bpts->y = yorg + y;
+ *--bwids = slw;
+ }
+ }
+ return (pGC->lineWidth);
+}
+
+#define CLIPSTEPEDGE(edgey,edge,edgeleft) \
+ if (ybase == edgey) \
+ { \
+ if (edgeleft) \
+ { \
+ if (edge->x > xcl) \
+ xcl = edge->x; \
+ } \
+ else \
+ { \
+ if (edge->x < xcr) \
+ xcr = edge->x; \
+ } \
+ edgey++; \
+ edge->x += edge->stepx; \
+ edge->e += edge->dx; \
+ if (edge->e > 0) \
+ { \
+ edge->x += edge->signdx; \
+ edge->e -= edge->dy; \
+ } \
+ }
+
+static int
+miLineArcD (
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ double xorg,
+ double yorg,
+ DDXPointPtr points,
+ int *widths,
+ PolyEdgePtr edge1,
+ int edgey1,
+ Bool edgeleft1,
+ PolyEdgePtr edge2,
+ int edgey2,
+ Bool edgeleft2)
+{
+ DDXPointPtr pts;
+ int *wids;
+ double radius, x0, y0, el, er, yk, xlk, xrk, k;
+ int xbase, ybase, y, boty, xl, xr, xcl, xcr;
+ int ymin, ymax;
+ Bool edge1IsMin, edge2IsMin;
+ int ymin1, ymin2;
+
+ pts = points;
+ wids = widths;
+ xbase = floor(xorg);
+ x0 = xorg - xbase;
+ ybase = ICEIL (yorg);
+ y0 = yorg - ybase;
+ if (pGC->miTranslate)
+ {
+ xbase += pDraw->x;
+ ybase += pDraw->y;
+ edge1->x += pDraw->x;
+ edge2->x += pDraw->x;
+ edgey1 += pDraw->y;
+ edgey2 += pDraw->y;
+ }
+ xlk = x0 + x0 + 1.0;
+ xrk = x0 + x0 - 1.0;
+ yk = y0 + y0 - 1.0;
+ radius = ((double)pGC->lineWidth) / 2.0;
+ y = floor(radius - y0 + 1.0);
+ ybase -= y;
+ ymin = ybase;
+ ymax = 65536;
+ edge1IsMin = FALSE;
+ ymin1 = edgey1;
+ if (edge1->dy >= 0)
+ {
+ if (!edge1->dy)
+ {
+ if (edgeleft1)
+ edge1IsMin = TRUE;
+ else
+ ymax = edgey1;
+ edgey1 = 65536;
+ }
+ else
+ {
+ if ((edge1->signdx < 0) == edgeleft1)
+ edge1IsMin = TRUE;
+ }
+ }
+ edge2IsMin = FALSE;
+ ymin2 = edgey2;
+ if (edge2->dy >= 0)
+ {
+ if (!edge2->dy)
+ {
+ if (edgeleft2)
+ edge2IsMin = TRUE;
+ else
+ ymax = edgey2;
+ edgey2 = 65536;
+ }
+ else
+ {
+ if ((edge2->signdx < 0) == edgeleft2)
+ edge2IsMin = TRUE;
+ }
+ }
+ if (edge1IsMin)
+ {
+ ymin = ymin1;
+ if (edge2IsMin && ymin1 > ymin2)
+ ymin = ymin2;
+ } else if (edge2IsMin)
+ ymin = ymin2;
+ el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
+ er = el + xrk;
+ xl = 1;
+ xr = 0;
+ if (x0 < 0.5)
+ {
+ xl = 0;
+ el -= xlk;
+ }
+ boty = (y0 < -0.5) ? 1 : 0;
+ if (ybase + y - boty > ymax)
+ boty = ymax - ybase - y;
+ while (y > boty)
+ {
+ k = (y << 1) + yk;
+ er += k;
+ while (er > 0.0)
+ {
+ xr++;
+ er += xrk - (xr << 1);
+ }
+ el += k;
+ while (el >= 0.0)
+ {
+ xl--;
+ el += (xl << 1) - xlk;
+ }
+ y--;
+ ybase++;
+ if (ybase < ymin)
+ continue;
+ xcl = xl + xbase;
+ xcr = xr + xbase;
+ CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
+ CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
+ if (xcr >= xcl)
+ {
+ pts->x = xcl;
+ pts->y = ybase;
+ pts++;
+ *wids++ = xcr - xcl + 1;
+ }
+ }
+ er = xrk - (xr << 1) - er;
+ el = (xl << 1) - xlk - el;
+ boty = floor(-y0 - radius + 1.0);
+ if (ybase + y - boty > ymax)
+ boty = ymax - ybase - y;
+ while (y > boty)
+ {
+ k = (y << 1) + yk;
+ er -= k;
+ while ((er >= 0.0) && (xr >= 0))
+ {
+ xr--;
+ er += xrk - (xr << 1);
+ }
+ el -= k;
+ while ((el > 0.0) && (xl <= 0))
+ {
+ xl++;
+ el += (xl << 1) - xlk;
+ }
+ y--;
+ ybase++;
+ if (ybase < ymin)
+ continue;
+ xcl = xl + xbase;
+ xcr = xr + xbase;
+ CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
+ CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
+ if (xcr >= xcl)
+ {
+ pts->x = xcl;
+ pts->y = ybase;
+ pts++;
+ *wids++ = xcr - xcl + 1;
+ }
+ }
+ return (pts - points);
+}
+
+static int
+miRoundJoinFace (LineFacePtr face, PolyEdgePtr edge, Bool *leftEdge)
+{
+ int y;
+ int dx, dy;
+ double xa, ya;
+ Bool left;
+
+ dx = -face->dy;
+ dy = face->dx;
+ xa = face->xa;
+ ya = face->ya;
+ left = 1;
+ if (ya > 0)
+ {
+ ya = 0.0;
+ xa = 0.0;
+ }
+ if (dy < 0 || (dy == 0 && dx > 0))
+ {
+ dx = -dx;
+ dy = -dy;
+ left = !left;
+ }
+ if (dx == 0 && dy == 0)
+ dy = 1;
+ if (dy == 0)
+ {
+ y = ICEIL (face->ya) + face->y;
+ edge->x = -32767;
+ edge->stepx = 0;
+ edge->signdx = 0;
+ edge->e = -1;
+ edge->dy = 0;
+ edge->dx = 0;
+ edge->height = 0;
+ }
+ else
+ {
+ y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge);
+ edge->height = 32767;
+ }
+ *leftEdge = !left;
+ return y;
+}
+
+void
+miRoundJoinClip (LineFacePtr pLeft, LineFacePtr pRight,
+ PolyEdgePtr edge1, PolyEdgePtr edge2,
+ int *y1, int *y2, Bool *left1, Bool *left2)
+{
+ double denom;
+
+ denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
+
+ if (denom >= 0)
+ {
+ pLeft->xa = -pLeft->xa;
+ pLeft->ya = -pLeft->ya;
+ }
+ else
+ {
+ pRight->xa = -pRight->xa;
+ pRight->ya = -pRight->ya;
+ }
+ *y1 = miRoundJoinFace (pLeft, edge1, left1);
+ *y2 = miRoundJoinFace (pRight, edge2, left2);
+}
+
+int
+miRoundCapClip (LineFacePtr face, Bool isInt, PolyEdgePtr edge, Bool *leftEdge)
+{
+ int y;
+ int dx, dy;
+ double xa, ya, k;
+ Bool left;
+
+ dx = -face->dy;
+ dy = face->dx;
+ xa = face->xa;
+ ya = face->ya;
+ k = 0.0;
+ if (!isInt)
+ k = face->k;
+ left = 1;
+ if (dy < 0 || (dy == 0 && dx > 0))
+ {
+ dx = -dx;
+ dy = -dy;
+ xa = -xa;
+ ya = -ya;
+ left = !left;
+ }
+ if (dx == 0 && dy == 0)
+ dy = 1;
+ if (dy == 0)
+ {
+ y = ICEIL (face->ya) + face->y;
+ edge->x = -32767;
+ edge->stepx = 0;
+ edge->signdx = 0;
+ edge->e = -1;
+ edge->dy = 0;
+ edge->dx = 0;
+ edge->height = 0;
+ }
+ else
+ {
+ y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge);
+ edge->height = 32767;
+ }
+ *leftEdge = !left;
+ return y;
+}
+
+static void
+miLineArc (
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ unsigned long pixel,
+ SpanDataPtr spanData,
+ LineFacePtr leftFace,
+ LineFacePtr rightFace,
+ double xorg,
+ double yorg,
+ Bool isInt)
+{
+ int xorgi = 0, yorgi = 0;
+ Spans spanRec;
+ int n;
+ PolyEdgeRec edge1, edge2;
+ int edgey1, edgey2;
+ Bool edgeleft1, edgeleft2;
+
+ if (isInt)
+ {
+ xorgi = leftFace ? leftFace->x : rightFace->x;
+ yorgi = leftFace ? leftFace->y : rightFace->y;
+ }
+ edgey1 = 65536;
+ edgey2 = 65536;
+ edge1.x = 0; /* not used, keep memory checkers happy */
+ edge1.dy = -1;
+ edge2.x = 0; /* not used, keep memory checkers happy */
+ edge2.dy = -1;
+ edgeleft1 = FALSE;
+ edgeleft2 = FALSE;
+ if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) &&
+ ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) ||
+ (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt)))
+ {
+ if (isInt)
+ {
+ xorg = (double) xorgi;
+ yorg = (double) yorgi;
+ }
+ if (leftFace && rightFace)
+ {
+ miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
+ &edgey1, &edgey2, &edgeleft1, &edgeleft2);
+ }
+ else if (leftFace)
+ {
+ edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
+ }
+ else if (rightFace)
+ {
+ edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
+ }
+ isInt = FALSE;
+ }
+ if (!InitSpans(&spanRec, pGC->lineWidth))
+ return;
+ if (isInt)
+ n = miLineArcI(pDraw, pGC, xorgi, yorgi, spanRec.points, spanRec.widths);
+ else
+ n = miLineArcD(pDraw, pGC, xorg, yorg, spanRec.points, spanRec.widths,
+ &edge1, edgey1, edgeleft1,
+ &edge2, edgey2, edgeleft2);
+ spanRec.count = n;
+ fillSpans (pDraw, pGC, pixel, &spanRec, spanData);
+}
+
+static void
+miLineProjectingCap (DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel,
+ SpanDataPtr spanData, LineFacePtr face, Bool isLeft,
+ double xorg, double yorg, Bool isInt)
+{
+ int xorgi = 0, yorgi = 0;
+ int lw;
+ PolyEdgeRec lefts[2], rights[2];
+ int lefty, righty, topy, bottomy;
+ PolyEdgePtr left, right;
+ PolyEdgePtr top, bottom;
+ double xa,ya;
+ double k;
+ double xap, yap;
+ int dx, dy;
+ double projectXoff, projectYoff;
+ double maxy;
+ int finaly;
+
+ if (isInt)
+ {
+ xorgi = face->x;
+ yorgi = face->y;
+ }
+ lw = pGC->lineWidth;
+ dx = face->dx;
+ dy = face->dy;
+ k = face->k;
+ if (dy == 0)
+ {
+ lefts[0].height = lw;
+ lefts[0].x = xorgi;
+ if (isLeft)
+ lefts[0].x -= (lw >> 1);
+ lefts[0].stepx = 0;
+ lefts[0].signdx = 1;
+ lefts[0].e = -lw;
+ lefts[0].dx = 0;
+ lefts[0].dy = lw;
+ rights[0].height = lw;
+ rights[0].x = xorgi;
+ if (!isLeft)
+ rights[0].x += ((lw + 1) >> 1);
+ rights[0].stepx = 0;
+ rights[0].signdx = 1;
+ rights[0].e = -lw;
+ rights[0].dx = 0;
+ rights[0].dy = lw;
+ miFillPolyHelper (pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw,
+ lefts, rights, 1, 1);
+ }
+ else if (dx == 0)
+ {
+ if (dy < 0) {
+ dy = -dy;
+ isLeft = !isLeft;
+ }
+ topy = yorgi;
+ bottomy = yorgi + dy;
+ if (isLeft)
+ topy -= (lw >> 1);
+ else
+ bottomy += (lw >> 1);
+ lefts[0].height = bottomy - topy;
+ lefts[0].x = xorgi - (lw >> 1);
+ lefts[0].stepx = 0;
+ lefts[0].signdx = 1;
+ lefts[0].e = -dy;
+ lefts[0].dx = dx;
+ lefts[0].dy = dy;
+
+ rights[0].height = bottomy - topy;
+ rights[0].x = lefts[0].x + (lw-1);
+ rights[0].stepx = 0;
+ rights[0].signdx = 1;
+ rights[0].e = -dy;
+ rights[0].dx = dx;
+ rights[0].dy = dy;
+ miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, bottomy - topy, lefts, rights, 1, 1);
+ }
+ else
+ {
+ xa = face->xa;
+ ya = face->ya;
+ projectXoff = -ya;
+ projectYoff = xa;
+ if (dx < 0)
+ {
+ right = &rights[1];
+ left = &lefts[0];
+ top = &rights[0];
+ bottom = &lefts[1];
+ }
+ else
+ {
+ right = &rights[0];
+ left = &lefts[1];
+ top = &lefts[0];
+ bottom = &rights[1];
+ }
+ if (isLeft)
+ {
+ righty = miPolyBuildEdge (xa, ya,
+ k, dx, dy, xorgi, yorgi, 0, right);
+
+ xa = -xa;
+ ya = -ya;
+ k = -k;
+ lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
+ k, dx, dy, xorgi, yorgi, 1, left);
+ if (dx > 0)
+ {
+ ya = -ya;
+ xa = -xa;
+ }
+ xap = xa - projectXoff;
+ yap = ya - projectYoff;
+ topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
+ -dy, dx, xorgi, yorgi, dx > 0, top);
+ bottomy = miPolyBuildEdge (xa, ya,
+ 0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom);
+ maxy = -ya;
+ }
+ else
+ {
+ righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
+ k, dx, dy, xorgi, yorgi, 0, right);
+
+ xa = -xa;
+ ya = -ya;
+ k = -k;
+ lefty = miPolyBuildEdge (xa, ya,
+ k, dx, dy, xorgi, yorgi, 1, left);
+ if (dx > 0)
+ {
+ ya = -ya;
+ xa = -xa;
+ }
+ xap = xa - projectXoff;
+ yap = ya - projectYoff;
+ topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top);
+ bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
+ -dy, dx, xorgi, xorgi, dx < 0, bottom);
+ maxy = -ya + projectYoff;
+ }
+ finaly = ICEIL(maxy) + yorgi;
+ if (dx < 0)
+ {
+ left->height = bottomy - lefty;
+ right->height = finaly - righty;
+ top->height = righty - topy;
+ }
+ else
+ {
+ right->height = bottomy - righty;
+ left->height = finaly - lefty;
+ top->height = lefty - topy;
+ }
+ bottom->height = finaly - bottomy;
+ miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy,
+ bottom->height + bottomy - topy, lefts, rights, 2, 2);
+ }
+}
+
+static void
+miWideSegment (
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ unsigned long pixel,
+ SpanDataPtr spanData,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ Bool projectLeft,
+ Bool projectRight,
+ LineFacePtr leftFace,
+ LineFacePtr rightFace)
+{
+ double l, L, r;
+ double xa, ya;
+ double projectXoff = 0.0, projectYoff = 0.0;
+ double k;
+ double maxy;
+ int x, y;
+ int dx, dy;
+ int finaly;
+ PolyEdgePtr left, right;
+ PolyEdgePtr top, bottom;
+ int lefty, righty, topy, bottomy;
+ int signdx;
+ PolyEdgeRec lefts[2], rights[2];
+ LineFacePtr tface;
+ int lw = pGC->lineWidth;
+
+ /* draw top-to-bottom always */
+ if (y2 < y1 || (y2 == y1 && x2 < x1))
+ {
+ x = x1;
+ x1 = x2;
+ x2 = x;
+
+ y = y1;
+ y1 = y2;
+ y2 = y;
+
+ x = projectLeft;
+ projectLeft = projectRight;
+ projectRight = x;
+
+ tface = leftFace;
+ leftFace = rightFace;
+ rightFace = tface;
+ }
+
+ dy = y2 - y1;
+ signdx = 1;
+ dx = x2 - x1;
+ if (dx < 0)
+ signdx = -1;
+
+ leftFace->x = x1;
+ leftFace->y = y1;
+ leftFace->dx = dx;
+ leftFace->dy = dy;
+
+ rightFace->x = x2;
+ rightFace->y = y2;
+ rightFace->dx = -dx;
+ rightFace->dy = -dy;
+
+ if (dy == 0)
+ {
+ rightFace->xa = 0;
+ rightFace->ya = (double) lw / 2.0;
+ rightFace->k = -(double) (lw * dx) / 2.0;
+ leftFace->xa = 0;
+ leftFace->ya = -rightFace->ya;
+ leftFace->k = rightFace->k;
+ x = x1;
+ if (projectLeft)
+ x -= (lw >> 1);
+ y = y1 - (lw >> 1);
+ dx = x2 - x;
+ if (projectRight)
+ dx += ((lw + 1) >> 1);
+ dy = lw;
+ miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
+ x, y, dx, dy);
+ }
+ else if (dx == 0)
+ {
+ leftFace->xa = (double) lw / 2.0;
+ leftFace->ya = 0;
+ leftFace->k = (double) (lw * dy) / 2.0;
+ rightFace->xa = -leftFace->xa;
+ rightFace->ya = 0;
+ rightFace->k = leftFace->k;
+ y = y1;
+ if (projectLeft)
+ y -= lw >> 1;
+ x = x1 - (lw >> 1);
+ dy = y2 - y;
+ if (projectRight)
+ dy += ((lw + 1) >> 1);
+ dx = lw;
+ miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
+ x, y, dx, dy);
+ }
+ else
+ {
+ l = ((double) lw) / 2.0;
+ L = hypot ((double) dx, (double) dy);
+
+ if (dx < 0)
+ {
+ right = &rights[1];
+ left = &lefts[0];
+ top = &rights[0];
+ bottom = &lefts[1];
+ }
+ else
+ {
+ right = &rights[0];
+ left = &lefts[1];
+ top = &lefts[0];
+ bottom = &rights[1];
+ }
+ r = l / L;
+
+ /* coord of upper bound at integral y */
+ ya = -r * dx;
+ xa = r * dy;
+
+ if (projectLeft | projectRight)
+ {
+ projectXoff = -ya;
+ projectYoff = xa;
+ }
+
+ /* xa * dy - ya * dx */
+ k = l * L;
+
+ leftFace->xa = xa;
+ leftFace->ya = ya;
+ leftFace->k = k;
+ rightFace->xa = -xa;
+ rightFace->ya = -ya;
+ rightFace->k = k;
+
+ if (projectLeft)
+ righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
+ k, dx, dy, x1, y1, 0, right);
+ else
+ righty = miPolyBuildEdge (xa, ya,
+ k, dx, dy, x1, y1, 0, right);
+
+ /* coord of lower bound at integral y */
+ ya = -ya;
+ xa = -xa;
+
+ /* xa * dy - ya * dx */
+ k = - k;
+
+ if (projectLeft)
+ lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
+ k, dx, dy, x1, y1, 1, left);
+ else
+ lefty = miPolyBuildEdge (xa, ya,
+ k, dx, dy, x1, y1, 1, left);
+
+ /* coord of top face at integral y */
+
+ if (signdx > 0)
+ {
+ ya = -ya;
+ xa = -xa;
+ }
+
+ if (projectLeft)
+ {
+ double xap = xa - projectXoff;
+ double yap = ya - projectYoff;
+ topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
+ -dy, dx, x1, y1, dx > 0, top);
+ }
+ else
+ topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top);
+
+ /* coord of bottom face at integral y */
+
+ if (projectRight)
+ {
+ double xap = xa + projectXoff;
+ double yap = ya + projectYoff;
+ bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
+ -dy, dx, x2, y2, dx < 0, bottom);
+ maxy = -ya + projectYoff;
+ }
+ else
+ {
+ bottomy = miPolyBuildEdge (xa, ya,
+ 0.0, -dy, dx, x2, y2, dx < 0, bottom);
+ maxy = -ya;
+ }
+
+ finaly = ICEIL (maxy) + y2;
+
+ if (dx < 0)
+ {
+ left->height = bottomy - lefty;
+ right->height = finaly - righty;
+ top->height = righty - topy;
+ }
+ else
+ {
+ right->height = bottomy - righty;
+ left->height = finaly - lefty;
+ top->height = lefty - topy;
+ }
+ bottom->height = finaly - bottomy;
+ miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy,
+ bottom->height + bottomy - topy, lefts, rights, 2, 2);
+ }
+}
+
+static SpanDataPtr
+miSetupSpanData (GCPtr pGC, SpanDataPtr spanData, int npt)
+{
+ if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop(pGC->alu))
+ return (SpanDataPtr) NULL;
+ if (pGC->lineStyle == LineDoubleDash)
+ miInitSpanGroup (&spanData->bgGroup);
+ miInitSpanGroup (&spanData->fgGroup);
+ return spanData;
+}
+
+static void
+miCleanupSpanData (DrawablePtr pDrawable, GCPtr pGC, SpanDataPtr spanData)
+{
+ if (pGC->lineStyle == LineDoubleDash)
+ {
+ ChangeGCVal oldPixel, pixel;
+ pixel.val = pGC->bgPixel;
+ oldPixel.val = pGC->fgPixel;
+ if (pixel.val != oldPixel.val)
+ {
+ ChangeGC (NullClient, pGC, GCForeground, &pixel);
+ ValidateGC (pDrawable, pGC);
+ }
+ miFillUniqueSpanGroup (pDrawable, pGC, &spanData->bgGroup);
+ miFreeSpanGroup (&spanData->bgGroup);
+ if (pixel.val != oldPixel.val)
+ {
+ ChangeGC (NullClient, pGC, GCForeground, &oldPixel);
+ ValidateGC (pDrawable, pGC);
+ }
+ }
+ miFillUniqueSpanGroup (pDrawable, pGC, &spanData->fgGroup);
+ miFreeSpanGroup (&spanData->fgGroup);
+}
+
+void
+miWideLine (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pPts)
+{
+ int x1, y1, x2, y2;
+ SpanDataRec spanDataRec;
+ SpanDataPtr spanData;
+ long pixel;
+ Bool projectLeft, projectRight;
+ LineFaceRec leftFace, rightFace, prevRightFace;
+ LineFaceRec firstFace;
+ int first;
+ Bool somethingDrawn = FALSE;
+ Bool selfJoin;
+
+ spanData = miSetupSpanData (pGC, &spanDataRec, npt);
+ pixel = pGC->fgPixel;
+ x2 = pPts->x;
+ y2 = pPts->y;
+ first = TRUE;
+ selfJoin = FALSE;
+ if (npt > 1)
+ {
+ if (mode == CoordModePrevious)
+ {
+ int nptTmp;
+ DDXPointPtr pPtsTmp;
+
+ x1 = x2;
+ y1 = y2;
+ nptTmp = npt;
+ pPtsTmp = pPts + 1;
+ while (--nptTmp)
+ {
+ x1 += pPtsTmp->x;
+ y1 += pPtsTmp->y;
+ ++pPtsTmp;
+ }
+ if (x2 == x1 && y2 == y1)
+ selfJoin = TRUE;
+ }
+ else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y)
+ {
+ selfJoin = TRUE;
+ }
+ }
+ projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
+ projectRight = FALSE;
+ while (--npt)
+ {
+ x1 = x2;
+ y1 = y2;
+ ++pPts;
+ x2 = pPts->x;
+ y2 = pPts->y;
+ if (mode == CoordModePrevious)
+ {
+ x2 += x1;
+ y2 += y1;
+ }
+ if (x1 != x2 || y1 != y2)
+ {
+ somethingDrawn = TRUE;
+ if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin)
+ projectRight = TRUE;
+ miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2,
+ projectLeft, projectRight, &leftFace, &rightFace);
+ if (first)
+ {
+ if (selfJoin)
+ firstFace = leftFace;
+ else if (pGC->capStyle == CapRound)
+ {
+ if (pGC->lineWidth == 1 && !spanData)
+ miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1);
+ else
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ &leftFace, (LineFacePtr) NULL,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ }
+ else
+ {
+ miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace,
+ &prevRightFace);
+ }
+ prevRightFace = rightFace;
+ first = FALSE;
+ projectLeft = FALSE;
+ }
+ if (npt == 1 && somethingDrawn)
+ {
+ if (selfJoin)
+ miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace,
+ &rightFace);
+ else if (pGC->capStyle == CapRound)
+ {
+ if (pGC->lineWidth == 1 && !spanData)
+ miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2);
+ else
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ (LineFacePtr) NULL, &rightFace,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ }
+ }
+ /* handle crock where all points are coincedent */
+ if (!somethingDrawn)
+ {
+ projectLeft = pGC->capStyle == CapProjecting;
+ miWideSegment (pDrawable, pGC, pixel, spanData,
+ x2, y2, x2, y2, projectLeft, projectLeft,
+ &leftFace, &rightFace);
+ if (pGC->capStyle == CapRound)
+ {
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ &leftFace, (LineFacePtr) NULL,
+ (double)0.0, (double)0.0,
+ TRUE);
+ rightFace.dx = -1; /* sleezy hack to make it work */
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ (LineFacePtr) NULL, &rightFace,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ }
+ if (spanData)
+ miCleanupSpanData (pDrawable, pGC, spanData);
+}
+
+#define V_TOP 0
+#define V_RIGHT 1
+#define V_BOTTOM 2
+#define V_LEFT 3
+
+static void
+miWideDashSegment (
+ DrawablePtr pDrawable,
+ GCPtr pGC,
+ SpanDataPtr spanData,
+ int *pDashOffset,
+ int *pDashIndex,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ Bool projectLeft,
+ Bool projectRight,
+ LineFacePtr leftFace,
+ LineFacePtr rightFace)
+{
+ int dashIndex, dashRemain;
+ unsigned char *pDash;
+ double L, l;
+ double k;
+ PolyVertexRec vertices[4];
+ PolyVertexRec saveRight, saveBottom;
+ PolySlopeRec slopes[4];
+ PolyEdgeRec left[2], right[2];
+ LineFaceRec lcapFace, rcapFace;
+ int nleft, nright;
+ int h;
+ int y;
+ int dy, dx;
+ unsigned long pixel;
+ double LRemain;
+ double r;
+ double rdx, rdy;
+ double dashDx, dashDy;
+ double saveK = 0.0;
+ Bool first = TRUE;
+ double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0;
+ unsigned long fgPixel, bgPixel;
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+ dashIndex = *pDashIndex;
+ pDash = pGC->dash;
+ dashRemain = pDash[dashIndex] - *pDashOffset;
+ fgPixel = pGC->fgPixel;
+ bgPixel = pGC->bgPixel;
+ if (pGC->fillStyle == FillOpaqueStippled ||
+ pGC->fillStyle == FillTiled)
+ {
+ bgPixel = fgPixel;
+ }
+
+ l = ((double) pGC->lineWidth) / 2.0;
+ if (dx == 0)
+ {
+ L = dy;
+ rdx = 0;
+ rdy = l;
+ if (dy < 0)
+ {
+ L = -dy;
+ rdy = -l;
+ }
+ }
+ else if (dy == 0)
+ {
+ L = dx;
+ rdx = l;
+ rdy = 0;
+ if (dx < 0)
+ {
+ L = -dx;
+ rdx = -l;
+ }
+ }
+ else
+ {
+ L = hypot ((double) dx, (double) dy);
+ r = l / L;
+
+ rdx = r * dx;
+ rdy = r * dy;
+ }
+ k = l * L;
+ LRemain = L;
+ /* All position comments are relative to a line with dx and dy > 0,
+ * but the code does not depend on this */
+ /* top */
+ slopes[V_TOP].dx = dx;
+ slopes[V_TOP].dy = dy;
+ slopes[V_TOP].k = k;
+ /* right */
+ slopes[V_RIGHT].dx = -dy;
+ slopes[V_RIGHT].dy = dx;
+ slopes[V_RIGHT].k = 0;
+ /* bottom */
+ slopes[V_BOTTOM].dx = -dx;
+ slopes[V_BOTTOM].dy = -dy;
+ slopes[V_BOTTOM].k = k;
+ /* left */
+ slopes[V_LEFT].dx = dy;
+ slopes[V_LEFT].dy = -dx;
+ slopes[V_LEFT].k = 0;
+
+ /* preload the start coordinates */
+ vertices[V_RIGHT].x = vertices[V_TOP].x = rdy;
+ vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx;
+
+ vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy;
+ vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx;
+
+ if (projectLeft)
+ {
+ vertices[V_TOP].x -= rdx;
+ vertices[V_TOP].y -= rdy;
+
+ vertices[V_LEFT].x -= rdx;
+ vertices[V_LEFT].y -= rdy;
+
+ slopes[V_LEFT].k = rdx * dx + rdy * dy;
+ }
+
+ lcenterx = x1;
+ lcentery = y1;
+
+ if (pGC->capStyle == CapRound)
+ {
+ lcapFace.dx = dx;
+ lcapFace.dy = dy;
+ lcapFace.x = x1;
+ lcapFace.y = y1;
+
+ rcapFace.dx = -dx;
+ rcapFace.dy = -dy;
+ rcapFace.x = x1;
+ rcapFace.y = y1;
+ }
+ while (LRemain > dashRemain)
+ {
+ dashDx = (dashRemain * dx) / L;
+ dashDy = (dashRemain * dy) / L;
+
+ rcenterx = lcenterx + dashDx;
+ rcentery = lcentery + dashDy;
+
+ vertices[V_RIGHT].x += dashDx;
+ vertices[V_RIGHT].y += dashDy;
+
+ vertices[V_BOTTOM].x += dashDx;
+ vertices[V_BOTTOM].y += dashDy;
+
+ slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy;
+
+ if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))
+ {
+ if (pGC->lineStyle == LineOnOffDash &&
+ pGC->capStyle == CapProjecting)
+ {
+ saveRight = vertices[V_RIGHT];
+ saveBottom = vertices[V_BOTTOM];
+ saveK = slopes[V_RIGHT].k;
+
+ if (!first)
+ {
+ vertices[V_TOP].x -= rdx;
+ vertices[V_TOP].y -= rdy;
+
+ vertices[V_LEFT].x -= rdx;
+ vertices[V_LEFT].y -= rdy;
+
+ slopes[V_LEFT].k = vertices[V_LEFT].x *
+ slopes[V_LEFT].dy -
+ vertices[V_LEFT].y *
+ slopes[V_LEFT].dx;
+ }
+
+ vertices[V_RIGHT].x += rdx;
+ vertices[V_RIGHT].y += rdy;
+
+ vertices[V_BOTTOM].x += rdx;
+ vertices[V_BOTTOM].y += rdy;
+
+ slopes[V_RIGHT].k = vertices[V_RIGHT].x *
+ slopes[V_RIGHT].dy -
+ vertices[V_RIGHT].y *
+ slopes[V_RIGHT].dx;
+ }
+ y = miPolyBuildPoly (vertices, slopes, 4, x1, y1,
+ left, right, &nleft, &nright, &h);
+ pixel = (dashIndex & 1) ? bgPixel : fgPixel;
+ miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright);
+
+ if (pGC->lineStyle == LineOnOffDash)
+ {
+ switch (pGC->capStyle)
+ {
+ case CapProjecting:
+ vertices[V_BOTTOM] = saveBottom;
+ vertices[V_RIGHT] = saveRight;
+ slopes[V_RIGHT].k = saveK;
+ break;
+ case CapRound:
+ if (!first)
+ {
+ if (dx < 0)
+ {
+ lcapFace.xa = -vertices[V_LEFT].x;
+ lcapFace.ya = -vertices[V_LEFT].y;
+ lcapFace.k = slopes[V_LEFT].k;
+ }
+ else
+ {
+ lcapFace.xa = vertices[V_TOP].x;
+ lcapFace.ya = vertices[V_TOP].y;
+ lcapFace.k = -slopes[V_LEFT].k;
+ }
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ &lcapFace, (LineFacePtr) NULL,
+ lcenterx, lcentery, FALSE);
+ }
+ if (dx < 0)
+ {
+ rcapFace.xa = vertices[V_BOTTOM].x;
+ rcapFace.ya = vertices[V_BOTTOM].y;
+ rcapFace.k = slopes[V_RIGHT].k;
+ }
+ else
+ {
+ rcapFace.xa = -vertices[V_RIGHT].x;
+ rcapFace.ya = -vertices[V_RIGHT].y;
+ rcapFace.k = -slopes[V_RIGHT].k;
+ }
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ (LineFacePtr) NULL, &rcapFace,
+ rcenterx, rcentery, FALSE);
+ break;
+ }
+ }
+ }
+ LRemain -= dashRemain;
+ ++dashIndex;
+ if (dashIndex == pGC->numInDashList)
+ dashIndex = 0;
+ dashRemain = pDash[dashIndex];
+
+ lcenterx = rcenterx;
+ lcentery = rcentery;
+
+ vertices[V_TOP] = vertices[V_RIGHT];
+ vertices[V_LEFT] = vertices[V_BOTTOM];
+ slopes[V_LEFT].k = -slopes[V_RIGHT].k;
+ first = FALSE;
+ }
+
+ if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))
+ {
+ vertices[V_TOP].x -= dx;
+ vertices[V_TOP].y -= dy;
+
+ vertices[V_LEFT].x -= dx;
+ vertices[V_LEFT].y -= dy;
+
+ vertices[V_RIGHT].x = rdy;
+ vertices[V_RIGHT].y = -rdx;
+
+ vertices[V_BOTTOM].x = -rdy;
+ vertices[V_BOTTOM].y = rdx;
+
+
+ if (projectRight)
+ {
+ vertices[V_RIGHT].x += rdx;
+ vertices[V_RIGHT].y += rdy;
+
+ vertices[V_BOTTOM].x += rdx;
+ vertices[V_BOTTOM].y += rdy;
+ slopes[V_RIGHT].k = vertices[V_RIGHT].x *
+ slopes[V_RIGHT].dy -
+ vertices[V_RIGHT].y *
+ slopes[V_RIGHT].dx;
+ }
+ else
+ slopes[V_RIGHT].k = 0;
+
+ if (!first && pGC->lineStyle == LineOnOffDash &&
+ pGC->capStyle == CapProjecting)
+ {
+ vertices[V_TOP].x -= rdx;
+ vertices[V_TOP].y -= rdy;
+
+ vertices[V_LEFT].x -= rdx;
+ vertices[V_LEFT].y -= rdy;
+ slopes[V_LEFT].k = vertices[V_LEFT].x *
+ slopes[V_LEFT].dy -
+ vertices[V_LEFT].y *
+ slopes[V_LEFT].dx;
+ }
+ else
+ slopes[V_LEFT].k += dx * dx + dy * dy;
+
+
+ y = miPolyBuildPoly (vertices, slopes, 4, x2, y2,
+ left, right, &nleft, &nright, &h);
+
+ pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
+ miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright);
+ if (!first && pGC->lineStyle == LineOnOffDash &&
+ pGC->capStyle == CapRound)
+ {
+ lcapFace.x = x2;
+ lcapFace.y = y2;
+ if (dx < 0)
+ {
+ lcapFace.xa = -vertices[V_LEFT].x;
+ lcapFace.ya = -vertices[V_LEFT].y;
+ lcapFace.k = slopes[V_LEFT].k;
+ }
+ else
+ {
+ lcapFace.xa = vertices[V_TOP].x;
+ lcapFace.ya = vertices[V_TOP].y;
+ lcapFace.k = -slopes[V_LEFT].k;
+ }
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ &lcapFace, (LineFacePtr) NULL,
+ rcenterx, rcentery, FALSE);
+ }
+ }
+ dashRemain = ((double) dashRemain) - LRemain;
+ if (dashRemain == 0)
+ {
+ dashIndex++;
+ if (dashIndex == pGC->numInDashList)
+ dashIndex = 0;
+ dashRemain = pDash[dashIndex];
+ }
+
+ leftFace->x = x1;
+ leftFace->y = y1;
+ leftFace->dx = dx;
+ leftFace->dy = dy;
+ leftFace->xa = rdy;
+ leftFace->ya = -rdx;
+ leftFace->k = k;
+
+ rightFace->x = x2;
+ rightFace->y = y2;
+ rightFace->dx = -dx;
+ rightFace->dy = -dy;
+ rightFace->xa = -rdy;
+ rightFace->ya = rdx;
+ rightFace->k = k;
+
+ *pDashIndex = dashIndex;
+ *pDashOffset = pDash[dashIndex] - dashRemain;
+}
+
+void
+miWideDash (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pPts)
+{
+ int x1, y1, x2, y2;
+ unsigned long pixel;
+ Bool projectLeft, projectRight;
+ LineFaceRec leftFace, rightFace, prevRightFace;
+ LineFaceRec firstFace;
+ int first;
+ int dashIndex, dashOffset;
+ int prevDashIndex;
+ SpanDataRec spanDataRec;
+ SpanDataPtr spanData;
+ Bool somethingDrawn = FALSE;
+ Bool selfJoin;
+ Bool endIsFg = FALSE, startIsFg = FALSE;
+ Bool firstIsFg = FALSE, prevIsFg = FALSE;
+
+#if 0
+ /* XXX backward compatibility */
+ if (pGC->lineWidth == 0)
+ {
+ miZeroDashLine (pDrawable, pGC, mode, npt, pPts);
+ return;
+ }
+#endif
+ if (pGC->lineStyle == LineDoubleDash &&
+ (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled))
+ {
+ miWideLine (pDrawable, pGC, mode, npt, pPts);
+ return;
+ }
+ if (npt == 0)
+ return;
+ spanData = miSetupSpanData (pGC, &spanDataRec, npt);
+ x2 = pPts->x;
+ y2 = pPts->y;
+ first = TRUE;
+ selfJoin = FALSE;
+ if (mode == CoordModePrevious)
+ {
+ int nptTmp;
+ DDXPointPtr pPtsTmp;
+
+ x1 = x2;
+ y1 = y2;
+ nptTmp = npt;
+ pPtsTmp = pPts + 1;
+ while (--nptTmp)
+ {
+ x1 += pPtsTmp->x;
+ y1 += pPtsTmp->y;
+ ++pPtsTmp;
+ }
+ if (x2 == x1 && y2 == y1)
+ selfJoin = TRUE;
+ }
+ else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y)
+ {
+ selfJoin = TRUE;
+ }
+ projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
+ projectRight = FALSE;
+ dashIndex = 0;
+ dashOffset = 0;
+ miStepDash ((int)pGC->dashOffset, &dashIndex,
+ pGC->dash, (int)pGC->numInDashList, &dashOffset);
+ while (--npt)
+ {
+ x1 = x2;
+ y1 = y2;
+ ++pPts;
+ x2 = pPts->x;
+ y2 = pPts->y;
+ if (mode == CoordModePrevious)
+ {
+ x2 += x1;
+ y2 += y1;
+ }
+ if (x1 != x2 || y1 != y2)
+ {
+ somethingDrawn = TRUE;
+ if (npt == 1 && pGC->capStyle == CapProjecting &&
+ (!selfJoin || !firstIsFg))
+ projectRight = TRUE;
+ prevDashIndex = dashIndex;
+ miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex,
+ x1, y1, x2, y2,
+ projectLeft, projectRight, &leftFace, &rightFace);
+ startIsFg = !(prevDashIndex & 1);
+ endIsFg = (dashIndex & 1) ^ (dashOffset != 0);
+ if (pGC->lineStyle == LineDoubleDash || startIsFg)
+ {
+ pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel;
+ if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg))
+ {
+ if (first && selfJoin)
+ {
+ firstFace = leftFace;
+ firstIsFg = startIsFg;
+ }
+ else if (pGC->capStyle == CapRound)
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ &leftFace, (LineFacePtr) NULL,
+ (double)0.0, (double)0.0, TRUE);
+ }
+ else
+ {
+ miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace,
+ &prevRightFace);
+ }
+ }
+ prevRightFace = rightFace;
+ prevIsFg = endIsFg;
+ first = FALSE;
+ projectLeft = FALSE;
+ }
+ if (npt == 1 && somethingDrawn)
+ {
+ if (pGC->lineStyle == LineDoubleDash || endIsFg)
+ {
+ pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel;
+ if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg))
+ {
+ miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace,
+ &rightFace);
+ }
+ else
+ {
+ if (pGC->capStyle == CapRound)
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ (LineFacePtr) NULL, &rightFace,
+ (double)0.0, (double)0.0, TRUE);
+ }
+ }
+ else
+ {
+ /* glue a cap to the start of the line if
+ * we're OnOffDash and ended on odd dash
+ */
+ if (selfJoin && firstIsFg)
+ {
+ pixel = pGC->fgPixel;
+ if (pGC->capStyle == CapProjecting)
+ miLineProjectingCap (pDrawable, pGC, pixel, spanData,
+ &firstFace, TRUE,
+ (double)0.0, (double)0.0, TRUE);
+ else if (pGC->capStyle == CapRound)
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ &firstFace, (LineFacePtr) NULL,
+ (double)0.0, (double)0.0, TRUE);
+ }
+ }
+ }
+ }
+ /* handle crock where all points are coincident */
+ if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)))
+ {
+ /* not the same as endIsFg computation above */
+ pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
+ switch (pGC->capStyle) {
+ case CapRound:
+ miLineArc (pDrawable, pGC, pixel, spanData,
+ (LineFacePtr) NULL, (LineFacePtr) NULL,
+ (double)x2, (double)y2,
+ FALSE);
+ break;
+ case CapProjecting:
+ x1 = pGC->lineWidth;
+ miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
+ x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1);
+ break;
+ }
+ }
+ if (spanData)
+ miCleanupSpanData (pDrawable, pGC, spanData);
+}
diff --git a/xorg-server/mi/miwideline.h b/xorg-server/mi/miwideline.h index 1665ebfb1..05d026a38 100644 --- a/xorg-server/mi/miwideline.h +++ b/xorg-server/mi/miwideline.h @@ -1,116 +1,120 @@ -/* - -Copyright 1988, 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. - -*/ - -/* Author: Keith Packard, MIT X Consortium */ - -#include "mispans.h" -#include "mifpoly.h" /* for ICEIL */ - -/* - * Polygon edge description for integer wide-line routines - */ - -typedef struct _PolyEdge { - int height; /* number of scanlines to process */ - int x; /* starting x coordinate */ - int stepx; /* fixed integral dx */ - int signdx; /* variable dx sign */ - int e; /* initial error term */ - int dy; - int dx; -} PolyEdgeRec, *PolyEdgePtr; - -#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - miter limit constant */ - -/* - * types for general polygon routines - */ - -typedef struct _PolyVertex { - double x, y; -} PolyVertexRec, *PolyVertexPtr; - -typedef struct _PolySlope { - int dx, dy; - double k; /* x0 * dy - y0 * dx */ -} PolySlopeRec, *PolySlopePtr; - -/* - * Line face description for caps/joins - */ - -typedef struct _LineFace { - double xa, ya; - int dx, dy; - int x, y; - double k; -} LineFaceRec, *LineFacePtr; - -/* - * macros for polygon fillers - */ - -#define MILINESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \ - oldPixel = pGC->fgPixel; \ - if (pixel != oldPixel) { \ - DoChangeGC (pGC, GCForeground, (XID *) &pixel, FALSE); \ - ValidateGC (pDrawable, pGC); \ - } \ -} -#define MILINERESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \ - if (pixel != oldPixel) { \ - DoChangeGC (pGC, GCForeground, (XID *) &oldPixel, FALSE); \ - ValidateGC (pDrawable, pGC); \ - } \ -} - -extern _X_EXPORT void miRoundJoinClip( - LineFacePtr /*pLeft*/, - LineFacePtr /*pRight*/, - PolyEdgePtr /*edge1*/, - PolyEdgePtr /*edge2*/, - int * /*y1*/, - int * /*y2*/, - Bool * /*left1*/, - Bool * /*left2*/ -); - -extern _X_EXPORT int miRoundCapClip( - LineFacePtr /*face*/, - Bool /*isInt*/, - PolyEdgePtr /*edge*/, - Bool * /*leftEdge*/ -); - -extern _X_EXPORT int miPolyBuildEdge(double x0, double y0, double k, int dx, int dy, - int xi, int yi, int left, PolyEdgePtr edge); -extern _X_EXPORT int miPolyBuildPoly(PolyVertexPtr vertices, PolySlopePtr slopes, - int count, int xi, int yi, PolyEdgePtr left, - PolyEdgePtr right, int *pnleft, int *pnright, - int *h); - +/*
+
+Copyright 1988, 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.
+
+*/
+
+/* Author: Keith Packard, MIT X Consortium */
+
+#include "mispans.h"
+#include "mifpoly.h" /* for ICEIL */
+
+/*
+ * Polygon edge description for integer wide-line routines
+ */
+
+typedef struct _PolyEdge {
+ int height; /* number of scanlines to process */
+ int x; /* starting x coordinate */
+ int stepx; /* fixed integral dx */
+ int signdx; /* variable dx sign */
+ int e; /* initial error term */
+ int dy;
+ int dx;
+} PolyEdgeRec, *PolyEdgePtr;
+
+#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - miter limit constant */
+
+/*
+ * types for general polygon routines
+ */
+
+typedef struct _PolyVertex {
+ double x, y;
+} PolyVertexRec, *PolyVertexPtr;
+
+typedef struct _PolySlope {
+ int dx, dy;
+ double k; /* x0 * dy - y0 * dx */
+} PolySlopeRec, *PolySlopePtr;
+
+/*
+ * Line face description for caps/joins
+ */
+
+typedef struct _LineFace {
+ double xa, ya;
+ int dx, dy;
+ int x, y;
+ double k;
+} LineFaceRec, *LineFacePtr;
+
+/*
+ * macros for polygon fillers
+ */
+
+#define MILINESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \
+ oldPixel = pGC->fgPixel; \
+ if (pixel != oldPixel) { \
+ ChangeGCVal gcval; \
+ gcval.val = pixel; \
+ ChangeGC (NullClient, pGC, GCForeground, &gcval); \
+ ValidateGC (pDrawable, pGC); \
+ } \
+}
+#define MILINERESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \
+ if (pixel != oldPixel) { \
+ ChangeGCVal gcval; \
+ gcval.val = oldPixel; \
+ ChangeGC (NullClient, pGC, GCForeground, &gcval); \
+ ValidateGC (pDrawable, pGC); \
+ } \
+}
+
+extern _X_EXPORT void miRoundJoinClip(
+ LineFacePtr /*pLeft*/,
+ LineFacePtr /*pRight*/,
+ PolyEdgePtr /*edge1*/,
+ PolyEdgePtr /*edge2*/,
+ int * /*y1*/,
+ int * /*y2*/,
+ Bool * /*left1*/,
+ Bool * /*left2*/
+);
+
+extern _X_EXPORT int miRoundCapClip(
+ LineFacePtr /*face*/,
+ Bool /*isInt*/,
+ PolyEdgePtr /*edge*/,
+ Bool * /*leftEdge*/
+);
+
+extern _X_EXPORT int miPolyBuildEdge(double x0, double y0, double k, int dx, int dy,
+ int xi, int yi, int left, PolyEdgePtr edge);
+extern _X_EXPORT int miPolyBuildPoly(PolyVertexPtr vertices, PolySlopePtr slopes,
+ int count, int xi, int yi, PolyEdgePtr left,
+ PolyEdgePtr right, int *pnleft, int *pnright,
+ int *h);
+
diff --git a/xorg-server/mi/miwindow.c b/xorg-server/mi/miwindow.c index c2333938e..479085787 100644 --- a/xorg-server/mi/miwindow.c +++ b/xorg-server/mi/miwindow.c @@ -1,836 +1,836 @@ - -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <X11/X.h> -#include "regionstr.h" -#include "region.h" -#include "mi.h" -#include "windowstr.h" -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "mivalidate.h" - -void -miClearToBackground(WindowPtr pWin, - int x, int y, int w, int h, - Bool generateExposures) -{ - BoxRec box; - RegionRec reg; - RegionPtr pBSReg = NullRegion; - ScreenPtr pScreen; - BoxPtr extents; - int x1, y1, x2, y2; - - /* compute everything using ints to avoid overflow */ - - x1 = pWin->drawable.x + x; - y1 = pWin->drawable.y + y; - if (w) - x2 = x1 + (int) w; - else - x2 = x1 + (int) pWin->drawable.width - (int) x; - if (h) - y2 = y1 + h; - else - y2 = y1 + (int) pWin->drawable.height - (int) y; - - extents = &pWin->clipList.extents; - - /* clip the resulting rectangle to the window clipList extents. This - * makes sure that the result will fit in a box, given that the - * screen is < 32768 on a side. - */ - - if (x1 < extents->x1) - x1 = extents->x1; - if (x2 > extents->x2) - x2 = extents->x2; - if (y1 < extents->y1) - y1 = extents->y1; - if (y2 > extents->y2) - y2 = extents->y2; - - if (x2 <= x1 || y2 <= y1) - { - x2 = x1 = 0; - y2 = y1 = 0; - } - - box.x1 = x1; - box.x2 = x2; - box.y1 = y1; - box.y2 = y2; - - pScreen = pWin->drawable.pScreen; - REGION_INIT(pScreen, ®, &box, 1); - - REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); - if (generateExposures) - (*pScreen->WindowExposures)(pWin, ®, pBSReg); - else if (pWin->backgroundState != None) - miPaintWindow(pWin, ®, PW_BACKGROUND); - REGION_UNINIT(pScreen, ®); - if (pBSReg) - REGION_DESTROY(pScreen, pBSReg); -} - -void -miMarkWindow(WindowPtr pWin) -{ - ValidatePtr val; - - if (pWin->valdata) - return; - val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); - val->before.oldAbsCorner.x = pWin->drawable.x; - val->before.oldAbsCorner.y = pWin->drawable.y; - val->before.borderVisible = NullRegion; - val->before.resized = FALSE; - pWin->valdata = val; -} - -Bool -miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin) -{ - BoxPtr box; - WindowPtr pChild, pLast; - Bool anyMarked = FALSE; - MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; - ScreenPtr pScreen; - - pScreen = pWin->drawable.pScreen; - - /* single layered systems are easy */ - if (ppLayerWin) *ppLayerWin = pWin; - - if (pWin == pFirst) - { - /* Blindly mark pWin and all of its inferiors. This is a slight - * overkill if there are mapped windows that outside pWin's border, - * but it's better than wasting time on RectIn checks. - */ - pChild = pWin; - while (1) - { - if (pChild->viewable) - { - if (REGION_BROKEN (pScreen, &pChild->winSize)) - SetWinSize (pChild); - if (REGION_BROKEN (pScreen, &pChild->borderSize)) - SetBorderSize (pChild); - (* MarkWindow)(pChild); - if (pChild->firstChild) - { - pChild = pChild->firstChild; - continue; - } - } - while (!pChild->nextSib && (pChild != pWin)) - pChild = pChild->parent; - if (pChild == pWin) - break; - pChild = pChild->nextSib; - } - anyMarked = TRUE; - pFirst = pFirst->nextSib; - } - if ( (pChild = pFirst) ) - { - box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); - pLast = pChild->parent->lastChild; - while (1) - { - if (pChild->viewable) - { - if (REGION_BROKEN (pScreen, &pChild->winSize)) - SetWinSize (pChild); - if (REGION_BROKEN (pScreen, &pChild->borderSize)) - SetBorderSize (pChild); - if (RECT_IN_REGION(pScreen, &pChild->borderSize, box)) - { - (* MarkWindow)(pChild); - anyMarked = TRUE; - if (pChild->firstChild) - { - pChild = pChild->firstChild; - continue; - } - } - } - while (!pChild->nextSib && (pChild != pLast)) - pChild = pChild->parent; - if (pChild == pLast) - break; - pChild = pChild->nextSib; - } - } - if (anyMarked) - (* MarkWindow)(pWin->parent); - return anyMarked; -} - -/***** - * miHandleValidateExposures(pWin) - * starting at pWin, draw background in any windows that have exposure - * regions, translate the regions, restore any backing store, - * and then send any regions still exposed to the client - *****/ -void -miHandleValidateExposures(WindowPtr pWin) -{ - WindowPtr pChild; - ValidatePtr val; - ScreenPtr pScreen; - WindowExposuresProcPtr WindowExposures; - - pScreen = pWin->drawable.pScreen; - - pChild = pWin; - WindowExposures = pChild->drawable.pScreen->WindowExposures; - while (1) - { - if ( (val = pChild->valdata) ) - { - if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) - miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER); - REGION_UNINIT(pScreen, &val->after.borderExposed); - (*WindowExposures)(pChild, &val->after.exposed, NullRegion); - REGION_UNINIT(pScreen, &val->after.exposed); - xfree(val); - pChild->valdata = NULL; - if (pChild->firstChild) - { - pChild = pChild->firstChild; - continue; - } - } - while (!pChild->nextSib && (pChild != pWin)) - pChild = pChild->parent; - if (pChild == pWin) - break; - pChild = pChild->nextSib; - } -} - -void -miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind) -{ - WindowPtr pParent; - Bool WasViewable = (Bool)(pWin->viewable); - short bw; - RegionPtr oldRegion = NULL; - DDXPointRec oldpt; - Bool anyMarked = FALSE; - ScreenPtr pScreen; - WindowPtr windowToValidate; - WindowPtr pLayerWin; - - /* if this is a root window, can't be moved */ - if (!(pParent = pWin->parent)) - return ; - pScreen = pWin->drawable.pScreen; - bw = wBorderWidth (pWin); - - oldpt.x = pWin->drawable.x; - oldpt.y = pWin->drawable.y; - if (WasViewable) - { - oldRegion = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, oldRegion, &pWin->borderClip); - anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); - } - pWin->origin.x = x + (int)bw; - pWin->origin.y = y + (int)bw; - x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; - y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; - - SetWinSize (pWin); - SetBorderSize (pWin); - - (*pScreen->PositionWindow)(pWin, x, y); - - windowToValidate = MoveWindowInStack(pWin, pNextSib); - - ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); - - if (WasViewable) - { - if (pLayerWin == pWin) - anyMarked |= (*pScreen->MarkOverlappedWindows) - (pWin, windowToValidate, NULL); - else - anyMarked |= (*pScreen->MarkOverlappedWindows) - (pWin, pLayerWin, NULL); - - - if (anyMarked) - { - (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); - (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); - REGION_DESTROY(pScreen, oldRegion); - /* XXX need to retile border if ParentRelative origin */ - (*pScreen->HandleExposures)(pLayerWin->parent); - } - if (anyMarked && pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); - } - if (pWin->realized) - WindowsRestructured (); -} - - -/* - * pValid is a region of the screen which has been - * successfully copied -- recomputed exposed regions for affected windows - */ - -static int -miRecomputeExposures ( - WindowPtr pWin, - pointer value) /* must conform to VisitWindowProcPtr */ -{ - ScreenPtr pScreen; - RegionPtr pValid = (RegionPtr)value; - - if (pWin->valdata) - { -#ifdef COMPOSITE - /* - * Redirected windows are not affected by parent window - * gravity manipulations, so don't recompute their - * exposed areas here. - */ - if (pWin->redirectDraw != RedirectDrawNone) - return WT_DONTWALKCHILDREN; -#endif - pScreen = pWin->drawable.pScreen; - /* - * compute exposed regions of this window - */ - REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, - &pWin->clipList, pValid); - /* - * compute exposed regions of the border - */ - REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, - &pWin->borderClip, &pWin->winSize); - REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, - &pWin->valdata->after.borderExposed, pValid); - return WT_WALKCHILDREN; - } - return WT_NOMATCH; -} - -void -miSlideAndSizeWindow(WindowPtr pWin, - int x, int y, - unsigned int w, unsigned int h, - WindowPtr pSib) -{ - WindowPtr pParent; - Bool WasViewable = (Bool)(pWin->viewable); - unsigned short width = pWin->drawable.width, - height = pWin->drawable.height; - short oldx = pWin->drawable.x, - oldy = pWin->drawable.y; - int bw = wBorderWidth (pWin); - short dw, dh; - DDXPointRec oldpt; - RegionPtr oldRegion = NULL; - Bool anyMarked = FALSE; - ScreenPtr pScreen; - WindowPtr pFirstChange; - WindowPtr pChild; - RegionPtr gravitate[StaticGravity + 1]; - unsigned g; - int nx, ny; /* destination x,y */ - int newx, newy; /* new inner window position */ - RegionPtr pRegion = NULL; - RegionPtr destClip; /* portions of destination already written */ - RegionPtr oldWinClip = NULL; /* old clip list for window */ - RegionPtr borderVisible = NullRegion; /* visible area of the border */ - Bool shrunk = FALSE; /* shrunk in an inner dimension */ - Bool moved = FALSE; /* window position changed */ - WindowPtr pLayerWin; - - /* if this is a root window, can't be resized */ - if (!(pParent = pWin->parent)) - return ; - - pScreen = pWin->drawable.pScreen; - newx = pParent->drawable.x + x + bw; - newy = pParent->drawable.y + y + bw; - if (WasViewable) - { - anyMarked = FALSE; - /* - * save the visible region of the window - */ - oldRegion = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, oldRegion, &pWin->winSize); - - /* - * categorize child windows into regions to be moved - */ - for (g = 0; g <= StaticGravity; g++) - gravitate[g] = (RegionPtr) NULL; - for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) - { - g = pChild->winGravity; - if (g != UnmapGravity) - { - if (!gravitate[g]) - gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); - REGION_UNION(pScreen, gravitate[g], - gravitate[g], &pChild->borderClip); - } - else - { - UnmapWindow(pChild, TRUE); - anyMarked = TRUE; - } - } - anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, - &pLayerWin); - - oldWinClip = NULL; - if (pWin->bitGravity != ForgetGravity) - { - oldWinClip = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, oldWinClip, &pWin->clipList); - } - /* - * if the window is changing size, borderExposed - * can't be computed correctly without some help. - */ - if (pWin->drawable.height > h || pWin->drawable.width > w) - shrunk = TRUE; - - if (newx != oldx || newy != oldy) - moved = TRUE; - - if ((pWin->drawable.height != h || pWin->drawable.width != w) && - HasBorder (pWin)) - { - borderVisible = REGION_CREATE(pScreen, NullBox, 1); - /* for tiled borders, we punt and draw the whole thing */ - if (pWin->borderIsPixel || !moved) - { - if (shrunk || moved) - REGION_SUBTRACT(pScreen, borderVisible, - &pWin->borderClip, - &pWin->winSize); - else - REGION_COPY(pScreen, borderVisible, - &pWin->borderClip); - } - } - } - pWin->origin.x = x + bw; - pWin->origin.y = y + bw; - pWin->drawable.height = h; - pWin->drawable.width = w; - - x = pWin->drawable.x = newx; - y = pWin->drawable.y = newy; - - SetWinSize (pWin); - SetBorderSize (pWin); - - dw = (int)w - (int)width; - dh = (int)h - (int)height; - ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); - - /* let the hardware adjust background and border pixmaps, if any */ - (*pScreen->PositionWindow)(pWin, x, y); - - pFirstChange = MoveWindowInStack(pWin, pSib); - - if (WasViewable) - { - pRegion = REGION_CREATE(pScreen, NullBox, 1); - - if (pLayerWin == pWin) - anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, - NULL); - else - anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, - NULL); - - if (pWin->valdata) - { - pWin->valdata->before.resized = TRUE; - pWin->valdata->before.borderVisible = borderVisible; - } - - - if (anyMarked) - (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); - /* - * the entire window is trashed unless bitGravity - * recovers portions of it - */ - REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); - } - - GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); - - if (WasViewable) - { - /* avoid the border */ - if (HasBorder (pWin)) - { - int offx, offy, dx, dy; - - /* kruft to avoid double translates for each gravity */ - offx = 0; - offy = 0; - for (g = 0; g <= StaticGravity; g++) - { - if (!gravitate[g]) - continue; - - /* align winSize to gravitate[g]. - * winSize is in new coordinates, - * gravitate[g] is still in old coordinates */ - GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); - - dx = (oldx - nx) - offx; - dy = (oldy - ny) - offy; - if (dx || dy) - { - REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); - offx += dx; - offy += dy; - } - REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], - &pWin->winSize); - } - /* get winSize back where it belongs */ - if (offx || offy) - REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); - } - /* - * add screen bits to the appropriate bucket - */ - - if (oldWinClip) - { - /* - * clip to new clipList - */ - REGION_COPY(pScreen, pRegion, oldWinClip); - REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); - REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); - /* - * don't step on any gravity bits which will be copied after this - * region. Note -- this assumes that the regions will be copied - * in gravity order. - */ - for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) - { - if (gravitate[g]) - REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, - gravitate[g]); - } - REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); - g = pWin->bitGravity; - if (!gravitate[g]) - gravitate[g] = oldWinClip; - else - { - REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); - REGION_DESTROY(pScreen, oldWinClip); - } - } - - /* - * move the bits on the screen - */ - - destClip = NULL; - - for (g = 0; g <= StaticGravity; g++) - { - if (!gravitate[g]) - continue; - - GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); - - oldpt.x = oldx + (x - nx); - oldpt.y = oldy + (y - ny); - - /* Note that gravitate[g] is *translated* by CopyWindow */ - - /* only copy the remaining useful bits */ - - REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); - - /* clip to not overwrite already copied areas */ - - if (destClip) { - REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); - REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); - REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); - } - - /* and move those bits */ - - if (oldpt.x != x || oldpt.y != y -#ifdef COMPOSITE - || pWin->redirectDraw -#endif - ) - { - (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); - } - - /* remove any overwritten bits from the remaining useful bits */ - - REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); - - /* - * recompute exposed regions of child windows - */ - - for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) - { - if (pChild->winGravity != g) - continue; - REGION_INTERSECT(pScreen, pRegion, - &pChild->borderClip, gravitate[g]); - TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); - } - - /* - * remove the successfully copied regions of the - * window from its exposed region - */ - - if (g == pWin->bitGravity) - REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, - &pWin->valdata->after.exposed, gravitate[g]); - if (!destClip) - destClip = gravitate[g]; - else - { - REGION_UNION(pScreen, destClip, destClip, gravitate[g]); - REGION_DESTROY(pScreen, gravitate[g]); - } - } - - REGION_DESTROY(pScreen, oldRegion); - REGION_DESTROY(pScreen, pRegion); - if (destClip) - REGION_DESTROY(pScreen, destClip); - if (anyMarked) - (*pScreen->HandleExposures)(pLayerWin->parent); - if (anyMarked && pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, - VTOther); - } - if (pWin->realized) - WindowsRestructured (); -} - -WindowPtr -miGetLayerWindow(WindowPtr pWin) -{ - return pWin->firstChild; -} - -/****** - * - * miSetShape - * The border/window shape has changed. Recompute winSize/borderSize - * and send appropriate exposure events - */ - -void -miSetShape(WindowPtr pWin) -{ - Bool WasViewable = (Bool)(pWin->viewable); - ScreenPtr pScreen = pWin->drawable.pScreen; - Bool anyMarked = FALSE; - WindowPtr pLayerWin; - - if (WasViewable) - { - anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, - &pLayerWin); - if (pWin->valdata) - { - if (HasBorder (pWin)) - { - RegionPtr borderVisible; - - borderVisible = REGION_CREATE(pScreen, NullBox, 1); - REGION_SUBTRACT(pScreen, borderVisible, - &pWin->borderClip, &pWin->winSize); - pWin->valdata->before.borderVisible = borderVisible; - } - pWin->valdata->before.resized = TRUE; - } - } - - SetWinSize (pWin); - SetBorderSize (pWin); - - ResizeChildrenWinSize(pWin, 0, 0, 0, 0); - - if (WasViewable) - { - anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, - NULL); - - - if (anyMarked) - (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); - } - - if (WasViewable) - { - if (anyMarked) - (*pScreen->HandleExposures)(pLayerWin->parent); - if (anyMarked && pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); - } - if (pWin->realized) - WindowsRestructured (); - CheckCursorConfinement(pWin); -} - -/* Keeps the same inside(!) origin */ - -void -miChangeBorderWidth(WindowPtr pWin, unsigned int width) -{ - int oldwidth; - Bool anyMarked = FALSE; - ScreenPtr pScreen; - Bool WasViewable = (Bool)(pWin->viewable); - Bool HadBorder; - WindowPtr pLayerWin; - - oldwidth = wBorderWidth (pWin); - if (oldwidth == width) - return; - HadBorder = HasBorder(pWin); - pScreen = pWin->drawable.pScreen; - if (WasViewable && width < oldwidth) - anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); - - pWin->borderWidth = width; - SetBorderSize (pWin); - - if (WasViewable) - { - if (width > oldwidth) - { - anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, - &pLayerWin); - /* - * save the old border visible region to correctly compute - * borderExposed. - */ - if (pWin->valdata && HadBorder) - { - RegionPtr borderVisible; - borderVisible = REGION_CREATE(pScreen, NULL, 1); - REGION_SUBTRACT(pScreen, borderVisible, - &pWin->borderClip, &pWin->winSize); - pWin->valdata->before.borderVisible = borderVisible; - } - } - - if (anyMarked) - { - (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); - (*pScreen->HandleExposures)(pLayerWin->parent); - } - if (anyMarked && pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, - VTOther); - } - if (pWin->realized) - WindowsRestructured (); -} - -void -miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure) -{ - if ((pChild != pWin) || fromConfigure) - { - REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); - if (pChild->drawable.pScreen->ClipNotify) - (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); - REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); - } -} - -void -miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) -{ - ScreenPtr pScreen; - WindowPtr pChild; - - pScreen = pWin->drawable.pScreen; - - for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) - { - if (pChild->drawable.depth == depth) - REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip); - - if (pChild->firstChild) - miSegregateChildren(pChild, pReg, depth); - } -} +
+/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <X11/X.h>
+#include "regionstr.h"
+#include "region.h"
+#include "mi.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "mivalidate.h"
+
+void
+miClearToBackground(WindowPtr pWin,
+ int x, int y, int w, int h,
+ Bool generateExposures)
+{
+ BoxRec box;
+ RegionRec reg;
+ RegionPtr pBSReg = NullRegion;
+ ScreenPtr pScreen;
+ BoxPtr extents;
+ int x1, y1, x2, y2;
+
+ /* compute everything using ints to avoid overflow */
+
+ x1 = pWin->drawable.x + x;
+ y1 = pWin->drawable.y + y;
+ if (w)
+ x2 = x1 + (int) w;
+ else
+ x2 = x1 + (int) pWin->drawable.width - (int) x;
+ if (h)
+ y2 = y1 + h;
+ else
+ y2 = y1 + (int) pWin->drawable.height - (int) y;
+
+ extents = &pWin->clipList.extents;
+
+ /* clip the resulting rectangle to the window clipList extents. This
+ * makes sure that the result will fit in a box, given that the
+ * screen is < 32768 on a side.
+ */
+
+ if (x1 < extents->x1)
+ x1 = extents->x1;
+ if (x2 > extents->x2)
+ x2 = extents->x2;
+ if (y1 < extents->y1)
+ y1 = extents->y1;
+ if (y2 > extents->y2)
+ y2 = extents->y2;
+
+ if (x2 <= x1 || y2 <= y1)
+ {
+ x2 = x1 = 0;
+ y2 = y1 = 0;
+ }
+
+ box.x1 = x1;
+ box.x2 = x2;
+ box.y1 = y1;
+ box.y2 = y2;
+
+ pScreen = pWin->drawable.pScreen;
+ REGION_INIT(pScreen, ®, &box, 1);
+
+ REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, ®, pBSReg);
+ else if (pWin->backgroundState != None)
+ miPaintWindow(pWin, ®, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, ®);
+ if (pBSReg)
+ REGION_DESTROY(pScreen, pBSReg);
+}
+
+void
+miMarkWindow(WindowPtr pWin)
+{
+ ValidatePtr val;
+
+ if (pWin->valdata)
+ return;
+ val = (ValidatePtr)xnfalloc(sizeof(ValidateRec));
+ val->before.oldAbsCorner.x = pWin->drawable.x;
+ val->before.oldAbsCorner.y = pWin->drawable.y;
+ val->before.borderVisible = NullRegion;
+ val->before.resized = FALSE;
+ pWin->valdata = val;
+}
+
+Bool
+miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
+{
+ BoxPtr box;
+ WindowPtr pChild, pLast;
+ Bool anyMarked = FALSE;
+ MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow;
+ ScreenPtr pScreen;
+
+ pScreen = pWin->drawable.pScreen;
+
+ /* single layered systems are easy */
+ if (ppLayerWin) *ppLayerWin = pWin;
+
+ if (pWin == pFirst)
+ {
+ /* Blindly mark pWin and all of its inferiors. This is a slight
+ * overkill if there are mapped windows that outside pWin's border,
+ * but it's better than wasting time on RectIn checks.
+ */
+ pChild = pWin;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ if (REGION_BROKEN (pScreen, &pChild->winSize))
+ SetWinSize (pChild);
+ if (REGION_BROKEN (pScreen, &pChild->borderSize))
+ SetBorderSize (pChild);
+ (* MarkWindow)(pChild);
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+ anyMarked = TRUE;
+ pFirst = pFirst->nextSib;
+ }
+ if ( (pChild = pFirst) )
+ {
+ box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize);
+ pLast = pChild->parent->lastChild;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ if (REGION_BROKEN (pScreen, &pChild->winSize))
+ SetWinSize (pChild);
+ if (REGION_BROKEN (pScreen, &pChild->borderSize))
+ SetBorderSize (pChild);
+ if (RECT_IN_REGION(pScreen, &pChild->borderSize, box))
+ {
+ (* MarkWindow)(pChild);
+ anyMarked = TRUE;
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ }
+ while (!pChild->nextSib && (pChild != pLast))
+ pChild = pChild->parent;
+ if (pChild == pLast)
+ break;
+ pChild = pChild->nextSib;
+ }
+ }
+ if (anyMarked)
+ (* MarkWindow)(pWin->parent);
+ return anyMarked;
+}
+
+/*****
+ * miHandleValidateExposures(pWin)
+ * starting at pWin, draw background in any windows that have exposure
+ * regions, translate the regions, restore any backing store,
+ * and then send any regions still exposed to the client
+ *****/
+void
+miHandleValidateExposures(WindowPtr pWin)
+{
+ WindowPtr pChild;
+ ValidatePtr val;
+ ScreenPtr pScreen;
+ WindowExposuresProcPtr WindowExposures;
+
+ pScreen = pWin->drawable.pScreen;
+
+ pChild = pWin;
+ WindowExposures = pChild->drawable.pScreen->WindowExposures;
+ while (1)
+ {
+ if ( (val = pChild->valdata) )
+ {
+ if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed))
+ miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
+ REGION_UNINIT(pScreen, &val->after.borderExposed);
+ (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
+ REGION_UNINIT(pScreen, &val->after.exposed);
+ free(val);
+ pChild->valdata = NULL;
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+void
+miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
+{
+ WindowPtr pParent;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ short bw;
+ RegionPtr oldRegion = NULL;
+ DDXPointRec oldpt;
+ Bool anyMarked = FALSE;
+ ScreenPtr pScreen;
+ WindowPtr windowToValidate;
+ WindowPtr pLayerWin;
+
+ /* if this is a root window, can't be moved */
+ if (!(pParent = pWin->parent))
+ return ;
+ pScreen = pWin->drawable.pScreen;
+ bw = wBorderWidth (pWin);
+
+ oldpt.x = pWin->drawable.x;
+ oldpt.y = pWin->drawable.y;
+ if (WasViewable)
+ {
+ oldRegion = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, oldRegion, &pWin->borderClip);
+ anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
+ }
+ pWin->origin.x = x + (int)bw;
+ pWin->origin.y = y + (int)bw;
+ x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
+ y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
+
+ SetWinSize (pWin);
+ SetBorderSize (pWin);
+
+ (*pScreen->PositionWindow)(pWin, x, y);
+
+ windowToValidate = MoveWindowInStack(pWin, pNextSib);
+
+ ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
+
+ if (WasViewable)
+ {
+ if (pLayerWin == pWin)
+ anyMarked |= (*pScreen->MarkOverlappedWindows)
+ (pWin, windowToValidate, NULL);
+ else
+ anyMarked |= (*pScreen->MarkOverlappedWindows)
+ (pWin, pLayerWin, NULL);
+
+
+ if (anyMarked)
+ {
+ (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind);
+ (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion);
+ REGION_DESTROY(pScreen, oldRegion);
+ /* XXX need to retile border if ParentRelative origin */
+ (*pScreen->HandleExposures)(pLayerWin->parent);
+ }
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+}
+
+
+/*
+ * pValid is a region of the screen which has been
+ * successfully copied -- recomputed exposed regions for affected windows
+ */
+
+static int
+miRecomputeExposures (
+ WindowPtr pWin,
+ pointer value) /* must conform to VisitWindowProcPtr */
+{
+ ScreenPtr pScreen;
+ RegionPtr pValid = (RegionPtr)value;
+
+ if (pWin->valdata)
+ {
+#ifdef COMPOSITE
+ /*
+ * Redirected windows are not affected by parent window
+ * gravity manipulations, so don't recompute their
+ * exposed areas here.
+ */
+ if (pWin->redirectDraw != RedirectDrawNone)
+ return WT_DONTWALKCHILDREN;
+#endif
+ pScreen = pWin->drawable.pScreen;
+ /*
+ * compute exposed regions of this window
+ */
+ REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
+ &pWin->clipList, pValid);
+ /*
+ * compute exposed regions of the border
+ */
+ REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
+ &pWin->borderClip, &pWin->winSize);
+ REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
+ &pWin->valdata->after.borderExposed, pValid);
+ return WT_WALKCHILDREN;
+ }
+ return WT_NOMATCH;
+}
+
+void
+miSlideAndSizeWindow(WindowPtr pWin,
+ int x, int y,
+ unsigned int w, unsigned int h,
+ WindowPtr pSib)
+{
+ WindowPtr pParent;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ unsigned short width = pWin->drawable.width,
+ height = pWin->drawable.height;
+ short oldx = pWin->drawable.x,
+ oldy = pWin->drawable.y;
+ int bw = wBorderWidth (pWin);
+ short dw, dh;
+ DDXPointRec oldpt;
+ RegionPtr oldRegion = NULL;
+ Bool anyMarked = FALSE;
+ ScreenPtr pScreen;
+ WindowPtr pFirstChange;
+ WindowPtr pChild;
+ RegionPtr gravitate[StaticGravity + 1];
+ unsigned g;
+ int nx, ny; /* destination x,y */
+ int newx, newy; /* new inner window position */
+ RegionPtr pRegion = NULL;
+ RegionPtr destClip; /* portions of destination already written */
+ RegionPtr oldWinClip = NULL; /* old clip list for window */
+ RegionPtr borderVisible = NullRegion; /* visible area of the border */
+ Bool shrunk = FALSE; /* shrunk in an inner dimension */
+ Bool moved = FALSE; /* window position changed */
+ WindowPtr pLayerWin;
+
+ /* if this is a root window, can't be resized */
+ if (!(pParent = pWin->parent))
+ return ;
+
+ pScreen = pWin->drawable.pScreen;
+ newx = pParent->drawable.x + x + bw;
+ newy = pParent->drawable.y + y + bw;
+ if (WasViewable)
+ {
+ anyMarked = FALSE;
+ /*
+ * save the visible region of the window
+ */
+ oldRegion = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, oldRegion, &pWin->winSize);
+
+ /*
+ * categorize child windows into regions to be moved
+ */
+ for (g = 0; g <= StaticGravity; g++)
+ gravitate[g] = (RegionPtr) NULL;
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ g = pChild->winGravity;
+ if (g != UnmapGravity)
+ {
+ if (!gravitate[g])
+ gravitate[g] = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_UNION(pScreen, gravitate[g],
+ gravitate[g], &pChild->borderClip);
+ }
+ else
+ {
+ UnmapWindow(pChild, TRUE);
+ anyMarked = TRUE;
+ }
+ }
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
+ &pLayerWin);
+
+ oldWinClip = NULL;
+ if (pWin->bitGravity != ForgetGravity)
+ {
+ oldWinClip = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, oldWinClip, &pWin->clipList);
+ }
+ /*
+ * if the window is changing size, borderExposed
+ * can't be computed correctly without some help.
+ */
+ if (pWin->drawable.height > h || pWin->drawable.width > w)
+ shrunk = TRUE;
+
+ if (newx != oldx || newy != oldy)
+ moved = TRUE;
+
+ if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
+ HasBorder (pWin))
+ {
+ borderVisible = REGION_CREATE(pScreen, NullBox, 1);
+ /* for tiled borders, we punt and draw the whole thing */
+ if (pWin->borderIsPixel || !moved)
+ {
+ if (shrunk || moved)
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip,
+ &pWin->winSize);
+ else
+ REGION_COPY(pScreen, borderVisible,
+ &pWin->borderClip);
+ }
+ }
+ }
+ pWin->origin.x = x + bw;
+ pWin->origin.y = y + bw;
+ pWin->drawable.height = h;
+ pWin->drawable.width = w;
+
+ x = pWin->drawable.x = newx;
+ y = pWin->drawable.y = newy;
+
+ SetWinSize (pWin);
+ SetBorderSize (pWin);
+
+ dw = (int)w - (int)width;
+ dh = (int)h - (int)height;
+ ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
+
+ /* let the hardware adjust background and border pixmaps, if any */
+ (*pScreen->PositionWindow)(pWin, x, y);
+
+ pFirstChange = MoveWindowInStack(pWin, pSib);
+
+ if (WasViewable)
+ {
+ pRegion = REGION_CREATE(pScreen, NullBox, 1);
+
+ if (pLayerWin == pWin)
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
+ NULL);
+ else
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
+ NULL);
+
+ if (pWin->valdata)
+ {
+ pWin->valdata->before.resized = TRUE;
+ pWin->valdata->before.borderVisible = borderVisible;
+ }
+
+
+ if (anyMarked)
+ (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther);
+ /*
+ * the entire window is trashed unless bitGravity
+ * recovers portions of it
+ */
+ REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList);
+ }
+
+ GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
+
+ if (WasViewable)
+ {
+ /* avoid the border */
+ if (HasBorder (pWin))
+ {
+ int offx, offy, dx, dy;
+
+ /* kruft to avoid double translates for each gravity */
+ offx = 0;
+ offy = 0;
+ for (g = 0; g <= StaticGravity; g++)
+ {
+ if (!gravitate[g])
+ continue;
+
+ /* align winSize to gravitate[g].
+ * winSize is in new coordinates,
+ * gravitate[g] is still in old coordinates */
+ GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
+
+ dx = (oldx - nx) - offx;
+ dy = (oldy - ny) - offy;
+ if (dx || dy)
+ {
+ REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy);
+ offx += dx;
+ offy += dy;
+ }
+ REGION_INTERSECT(pScreen, gravitate[g], gravitate[g],
+ &pWin->winSize);
+ }
+ /* get winSize back where it belongs */
+ if (offx || offy)
+ REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy);
+ }
+ /*
+ * add screen bits to the appropriate bucket
+ */
+
+ if (oldWinClip)
+ {
+ /*
+ * clip to new clipList
+ */
+ REGION_COPY(pScreen, pRegion, oldWinClip);
+ REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy);
+ REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList);
+ /*
+ * don't step on any gravity bits which will be copied after this
+ * region. Note -- this assumes that the regions will be copied
+ * in gravity order.
+ */
+ for (g = pWin->bitGravity + 1; g <= StaticGravity; g++)
+ {
+ if (gravitate[g])
+ REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip,
+ gravitate[g]);
+ }
+ REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny);
+ g = pWin->bitGravity;
+ if (!gravitate[g])
+ gravitate[g] = oldWinClip;
+ else
+ {
+ REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip);
+ REGION_DESTROY(pScreen, oldWinClip);
+ }
+ }
+
+ /*
+ * move the bits on the screen
+ */
+
+ destClip = NULL;
+
+ for (g = 0; g <= StaticGravity; g++)
+ {
+ if (!gravitate[g])
+ continue;
+
+ GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
+
+ oldpt.x = oldx + (x - nx);
+ oldpt.y = oldy + (y - ny);
+
+ /* Note that gravitate[g] is *translated* by CopyWindow */
+
+ /* only copy the remaining useful bits */
+
+ REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion);
+
+ /* clip to not overwrite already copied areas */
+
+ if (destClip) {
+ REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y);
+ REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip);
+ REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y);
+ }
+
+ /* and move those bits */
+
+ if (oldpt.x != x || oldpt.y != y
+#ifdef COMPOSITE
+ || pWin->redirectDraw
+#endif
+ )
+ {
+ (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]);
+ }
+
+ /* remove any overwritten bits from the remaining useful bits */
+
+ REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]);
+
+ /*
+ * recompute exposed regions of child windows
+ */
+
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ if (pChild->winGravity != g)
+ continue;
+ REGION_INTERSECT(pScreen, pRegion,
+ &pChild->borderClip, gravitate[g]);
+ TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion);
+ }
+
+ /*
+ * remove the successfully copied regions of the
+ * window from its exposed region
+ */
+
+ if (g == pWin->bitGravity)
+ REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
+ &pWin->valdata->after.exposed, gravitate[g]);
+ if (!destClip)
+ destClip = gravitate[g];
+ else
+ {
+ REGION_UNION(pScreen, destClip, destClip, gravitate[g]);
+ REGION_DESTROY(pScreen, gravitate[g]);
+ }
+ }
+
+ REGION_DESTROY(pScreen, oldRegion);
+ REGION_DESTROY(pScreen, pRegion);
+ if (destClip)
+ REGION_DESTROY(pScreen, destClip);
+ if (anyMarked)
+ (*pScreen->HandleExposures)(pLayerWin->parent);
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange,
+ VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+}
+
+WindowPtr
+miGetLayerWindow(WindowPtr pWin)
+{
+ return pWin->firstChild;
+}
+
+/******
+ *
+ * miSetShape
+ * The border/window shape has changed. Recompute winSize/borderSize
+ * and send appropriate exposure events
+ */
+
+void
+miSetShape(WindowPtr pWin)
+{
+ Bool WasViewable = (Bool)(pWin->viewable);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ Bool anyMarked = FALSE;
+ WindowPtr pLayerWin;
+
+ if (WasViewable)
+ {
+ anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
+ &pLayerWin);
+ if (pWin->valdata)
+ {
+ if (HasBorder (pWin))
+ {
+ RegionPtr borderVisible;
+
+ borderVisible = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ }
+ pWin->valdata->before.resized = TRUE;
+ }
+ }
+
+ SetWinSize (pWin);
+ SetBorderSize (pWin);
+
+ ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
+
+ if (WasViewable)
+ {
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
+ NULL);
+
+
+ if (anyMarked)
+ (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther);
+ }
+
+ if (WasViewable)
+ {
+ if (anyMarked)
+ (*pScreen->HandleExposures)(pLayerWin->parent);
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+ CheckCursorConfinement(pWin);
+}
+
+/* Keeps the same inside(!) origin */
+
+void
+miChangeBorderWidth(WindowPtr pWin, unsigned int width)
+{
+ int oldwidth;
+ Bool anyMarked = FALSE;
+ ScreenPtr pScreen;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ Bool HadBorder;
+ WindowPtr pLayerWin;
+
+ oldwidth = wBorderWidth (pWin);
+ if (oldwidth == width)
+ return;
+ HadBorder = HasBorder(pWin);
+ pScreen = pWin->drawable.pScreen;
+ if (WasViewable && width < oldwidth)
+ anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
+
+ pWin->borderWidth = width;
+ SetBorderSize (pWin);
+
+ if (WasViewable)
+ {
+ if (width > oldwidth)
+ {
+ anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
+ &pLayerWin);
+ /*
+ * save the old border visible region to correctly compute
+ * borderExposed.
+ */
+ if (pWin->valdata && HadBorder)
+ {
+ RegionPtr borderVisible;
+ borderVisible = REGION_CREATE(pScreen, NULL, 1);
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ }
+ }
+
+ if (anyMarked)
+ {
+ (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
+ (*pScreen->HandleExposures)(pLayerWin->parent);
+ }
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin,
+ VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+}
+
+void
+miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure)
+{
+ if ((pChild != pWin) || fromConfigure)
+ {
+ REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList);
+ if (pChild->drawable.pScreen->ClipNotify)
+ (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
+ REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip);
+ }
+}
+
+void
+miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
+{
+ ScreenPtr pScreen;
+ WindowPtr pChild;
+
+ pScreen = pWin->drawable.pScreen;
+
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ if (pChild->drawable.depth == depth)
+ REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip);
+
+ if (pChild->firstChild)
+ miSegregateChildren(pChild, pReg, depth);
+ }
+}
diff --git a/xorg-server/mi/mizerarc.c b/xorg-server/mi/mizerarc.c index ad84c0123..713d0bd04 100644 --- a/xorg-server/mi/mizerarc.c +++ b/xorg-server/mi/mizerarc.c @@ -1,844 +1,848 @@ -/************************************************************ - -Copyright 1989, 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. - -Author: Bob Scheifler, MIT X Consortium - -********************************************************/ - - -/* Derived from: - * "Algorithm for drawing ellipses or hyperbolae with a digital plotter" - * by M. L. V. Pitteway - * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289 - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <math.h> -#include <X11/X.h> -#include <X11/Xprotostr.h> -#include "regionstr.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "mi.h" -#include "mizerarc.h" - -#define FULLCIRCLE (360 * 64) -#define OCTANT (45 * 64) -#define QUADRANT (90 * 64) -#define HALFCIRCLE (180 * 64) -#define QUADRANT3 (270 * 64) - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define Dsin(d) ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \ - ((d) == HALFCIRCLE ? 0.0 : \ - ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0)))))) - -#define Dcos(d) ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \ - ((d) == HALFCIRCLE ? -1.0 : \ - ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0)))))) - -#define EPSILON45 64 - -typedef struct { - int skipStart; - int haveStart; - DDXPointRec startPt; - int haveLast; - int skipLast; - DDXPointRec endPt; - int dashIndex; - int dashOffset; - int dashIndexInit; - int dashOffsetInit; -} DashInfo; - -static miZeroArcPtRec oob = {65536, 65536, 0}; - -/* - * (x - l)^2 / (W/2)^2 + (y + H/2)^2 / (H/2)^2 = 1 - * - * where l is either 0 or .5 - * - * alpha = 4(W^2) - * beta = 4(H^2) - * gamma = 0 - * u = 2(W^2)H - * v = 4(H^2)l - * k = -4(H^2)(l^2) - * - */ - -Bool -miZeroArcSetup(xArc *arc, miZeroArcRec *info, Bool ok360) -{ - int l; - int angle1, angle2; - int startseg, endseg; - int startAngle, endAngle; - int i, overlap; - miZeroArcPtRec start, end; - - l = arc->width & 1; - if (arc->width == arc->height) - { - info->alpha = 4; - info->beta = 4; - info->k1 = -8; - info->k3 = -16; - info->b = 12; - info->a = (arc->width << 2) - 12; - info->d = 17 - (arc->width << 1); - if (l) - { - info->b -= 4; - info->a += 4; - info->d -= 7; - } - } - else if (!arc->width || !arc->height) - { - info->alpha = 0; - info->beta = 0; - info->k1 = 0; - info->k3 = 0; - info->a = -(int)arc->height; - info->b = 0; - info->d = -1; - } - else - { - /* initial conditions */ - info->alpha = (arc->width * arc->width) << 2; - info->beta = (arc->height * arc->height) << 2; - info->k1 = info->beta << 1; - info->k3 = info->k1 + (info->alpha << 1); - info->b = l ? 0 : -info->beta; - info->a = info->alpha * arc->height; - info->d = info->b - (info->a >> 1) - (info->alpha >> 2); - if (l) - info->d -= info->beta >> 2; - info->a -= info->b; - /* take first step, d < 0 always */ - info->b -= info->k1; - info->a += info->k1; - info->d += info->b; - /* octant change, b < 0 always */ - info->k1 = -info->k1; - info->k3 = -info->k3; - info->b = -info->b; - info->d = info->b - info->a - info->d; - info->a = info->a - (info->b << 1); - } - info->dx = 1; - info->dy = 0; - info->w = (arc->width + 1) >> 1; - info->h = arc->height >> 1; - info->xorg = arc->x + (arc->width >> 1); - info->yorg = arc->y; - info->xorgo = info->xorg + l; - info->yorgo = info->yorg + arc->height; - if (!arc->width) - { - if (!arc->height) - { - info->x = 0; - info->y = 0; - info->initialMask = 0; - info->startAngle = 0; - info->endAngle = 0; - info->start = oob; - info->end = oob; - return FALSE; - } - info->x = 0; - info->y = 1; - } - else - { - info->x = 1; - info->y = 0; - } - angle1 = arc->angle1; - angle2 = arc->angle2; - if ((angle1 == 0) && (angle2 >= FULLCIRCLE)) - { - startAngle = 0; - endAngle = 0; - } - else - { - if (angle2 > FULLCIRCLE) - angle2 = FULLCIRCLE; - else if (angle2 < -FULLCIRCLE) - angle2 = -FULLCIRCLE; - if (angle2 < 0) - { - startAngle = angle1 + angle2; - endAngle = angle1; - } - else - { - startAngle = angle1; - endAngle = angle1 + angle2; - } - if (startAngle < 0) - startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; - if (startAngle >= FULLCIRCLE) - startAngle = startAngle % FULLCIRCLE; - if (endAngle < 0) - endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE; - if (endAngle >= FULLCIRCLE) - endAngle = endAngle % FULLCIRCLE; - } - info->startAngle = startAngle; - info->endAngle = endAngle; - if (ok360 && (startAngle == endAngle) && arc->angle2 && - arc->width && arc->height) - { - info->initialMask = 0xf; - info->start = oob; - info->end = oob; - return TRUE; - } - startseg = startAngle / OCTANT; - if (!arc->height || (((startseg + 1) & 2) && arc->width)) - { - start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0); - if (start.x < 0) - start.x = -start.x; - start.y = -1; - } - else - { - start.y = Dsin(startAngle) * (arc->height / 2.0); - if (start.y < 0) - start.y = -start.y; - start.y = info->h - start.y; - start.x = 65536; - } - endseg = endAngle / OCTANT; - if (!arc->height || (((endseg + 1) & 2) && arc->width)) - { - end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0); - if (end.x < 0) - end.x = -end.x; - end.y = -1; - } - else - { - end.y = Dsin(endAngle) * (arc->height / 2.0); - if (end.y < 0) - end.y = -end.y; - end.y = info->h - end.y; - end.x = 65536; - } - info->firstx = start.x; - info->firsty = start.y; - info->initialMask = 0; - overlap = arc->angle2 && (endAngle <= startAngle); - for (i = 0; i < 4; i++) - { - if (overlap ? - ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) : - ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle))) - info->initialMask |= (1 << i); - } - start.mask = info->initialMask; - end.mask = info->initialMask; - startseg >>= 1; - endseg >>= 1; - overlap = overlap && (endseg == startseg); - if (start.x != end.x || start.y != end.y || !overlap) - { - if (startseg & 1) - { - if (!overlap) - info->initialMask &= ~(1 << startseg); - if (start.x > end.x || start.y > end.y) - end.mask &= ~(1 << startseg); - } - else - { - start.mask &= ~(1 << startseg); - if (((start.x < end.x || start.y < end.y) || - (start.x == end.x && start.y == end.y && (endseg & 1))) && - !overlap) - end.mask &= ~(1 << startseg); - } - if (endseg & 1) - { - end.mask &= ~(1 << endseg); - if (((start.x > end.x || start.y > end.y) || - (start.x == end.x && start.y == end.y && !(startseg & 1))) && - !overlap) - start.mask &= ~(1 << endseg); - } - else - { - if (!overlap) - info->initialMask &= ~(1 << endseg); - if (start.x < end.x || start.y < end.y) - start.mask &= ~(1 << endseg); - } - } - /* take care of case when start and stop are both near 45 */ - /* handle here rather than adding extra code to pixelization loops */ - if (startAngle && - ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0))) - { - i = (startAngle + OCTANT) % OCTANT; - if (i < EPSILON45 || i > OCTANT - EPSILON45) - { - i = (endAngle + OCTANT) % OCTANT; - if (i < EPSILON45 || i > OCTANT - EPSILON45) - { - if (start.y < 0) - { - i = Dsin(startAngle) * (arc->height / 2.0); - if (i < 0) - i = -i; - if (info->h - i == end.y) - start.mask = end.mask; - } - else - { - i = Dsin(endAngle) * (arc->height / 2.0); - if (i < 0) - i = -i; - if (info->h - i == start.y) - end.mask = start.mask; - } - } - } - } - if (startseg & 1) - { - info->start = start; - info->end = oob; - } - else - { - info->end = start; - info->start = oob; - } - if (endseg & 1) - { - info->altend = end; - if (info->altend.x < info->end.x || info->altend.y < info->end.y) - { - miZeroArcPtRec tmp; - tmp = info->altend; - info->altend = info->end; - info->end = tmp; - } - info->altstart = oob; - } - else - { - info->altstart = end; - if (info->altstart.x < info->start.x || - info->altstart.y < info->start.y) - { - miZeroArcPtRec tmp; - tmp = info->altstart; - info->altstart = info->start; - info->start = tmp; - } - info->altend = oob; - } - if (!info->start.x || !info->start.y) - { - info->initialMask = info->start.mask; - info->start = info->altstart; - } - if (!arc->width && (arc->height == 1)) - { - /* kludge! */ - info->initialMask |= info->end.mask; - info->initialMask |= info->initialMask << 1; - info->end.x = 0; - info->end.mask = 0; - } - return FALSE; -} - -#define Pixelate(xval,yval) \ - { \ - pts->x = xval; \ - pts->y = yval; \ - pts++; \ - } - -#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval); - -static DDXPointPtr -miZeroArcPts(xArc *arc, DDXPointPtr pts) -{ - miZeroArcRec info; - int x, y, a, b, d, mask; - int k1, k3, dx, dy; - Bool do360; - - do360 = miZeroArcSetup(arc, &info, TRUE); - MIARCSETUP(); - mask = info.initialMask; - if (!(arc->width & 1)) - { - DoPix(1, info.xorgo, info.yorg); - DoPix(3, info.xorgo, info.yorgo); - } - if (!info.end.x || !info.end.y) - { - mask = info.end.mask; - info.end = info.altend; - } - if (do360 && (arc->width == arc->height) && !(arc->width & 1)) - { - int yorgh = info.yorg + info.h; - int xorghp = info.xorg + info.h; - int xorghn = info.xorg - info.h; - - while (1) - { - Pixelate(info.xorg + x, info.yorg + y); - Pixelate(info.xorg - x, info.yorg + y); - Pixelate(info.xorg - x, info.yorgo - y); - Pixelate(info.xorg + x, info.yorgo - y); - if (a < 0) - break; - Pixelate(xorghp - y, yorgh - x); - Pixelate(xorghn + y, yorgh - x); - Pixelate(xorghn + y, yorgh + x); - Pixelate(xorghp - y, yorgh + x); - MIARCCIRCLESTEP(;); - } - if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y) - pts -= 4; - x = info.w; - y = info.h; - } - else if (do360) - { - while (y < info.h || x < info.w) - { - MIARCOCTANTSHIFT(;); - Pixelate(info.xorg + x, info.yorg + y); - Pixelate(info.xorgo - x, info.yorg + y); - Pixelate(info.xorgo - x, info.yorgo - y); - Pixelate(info.xorg + x, info.yorgo - y); - MIARCSTEP(;,;); - } - } - else - { - while (y < info.h || x < info.w) - { - MIARCOCTANTSHIFT(;); - if ((x == info.start.x) || (y == info.start.y)) - { - mask = info.start.mask; - info.start = info.altstart; - } - DoPix(0, info.xorg + x, info.yorg + y); - DoPix(1, info.xorgo - x, info.yorg + y); - DoPix(2, info.xorgo - x, info.yorgo - y); - DoPix(3, info.xorg + x, info.yorgo - y); - if ((x == info.end.x) || (y == info.end.y)) - { - mask = info.end.mask; - info.end = info.altend; - } - MIARCSTEP(;,;); - } - } - if ((x == info.start.x) || (y == info.start.y)) - mask = info.start.mask; - DoPix(0, info.xorg + x, info.yorg + y); - DoPix(2, info.xorgo - x, info.yorgo - y); - if (arc->height & 1) - { - DoPix(1, info.xorgo - x, info.yorg + y); - DoPix(3, info.xorg + x, info.yorgo - y); - } - return pts; -} - -#undef DoPix -#define DoPix(idx,xval,yval) \ - if (mask & (1 << idx)) \ - { \ - arcPts[idx]->x = xval; \ - arcPts[idx]->y = yval; \ - arcPts[idx]++; \ - } - -static void -miZeroArcDashPts( - GCPtr pGC, - xArc *arc, - DashInfo *dinfo, - DDXPointPtr points, - int maxPts, - DDXPointPtr *evenPts, - DDXPointPtr *oddPts ) -{ - miZeroArcRec info; - int x, y, a, b, d, mask; - int k1, k3, dx, dy; - int dashRemaining; - DDXPointPtr arcPts[4]; - DDXPointPtr startPts[5], endPts[5]; - int deltas[5]; - DDXPointPtr startPt, pt, lastPt, pts; - int i, j, delta, ptsdelta, seg, startseg; - - for (i = 0; i < 4; i++) - arcPts[i] = points + (i * maxPts); - (void)miZeroArcSetup(arc, &info, FALSE); - MIARCSETUP(); - mask = info.initialMask; - startseg = info.startAngle / QUADRANT; - startPt = arcPts[startseg]; - if (!(arc->width & 1)) - { - DoPix(1, info.xorgo, info.yorg); - DoPix(3, info.xorgo, info.yorgo); - } - if (!info.end.x || !info.end.y) - { - mask = info.end.mask; - info.end = info.altend; - } - while (y < info.h || x < info.w) - { - MIARCOCTANTSHIFT(;); - if ((x == info.firstx) || (y == info.firsty)) - startPt = arcPts[startseg]; - if ((x == info.start.x) || (y == info.start.y)) - { - mask = info.start.mask; - info.start = info.altstart; - } - DoPix(0, info.xorg + x, info.yorg + y); - DoPix(1, info.xorgo - x, info.yorg + y); - DoPix(2, info.xorgo - x, info.yorgo - y); - DoPix(3, info.xorg + x, info.yorgo - y); - if ((x == info.end.x) || (y == info.end.y)) - { - mask = info.end.mask; - info.end = info.altend; - } - MIARCSTEP(;,;); - } - if ((x == info.firstx) || (y == info.firsty)) - startPt = arcPts[startseg]; - if ((x == info.start.x) || (y == info.start.y)) - mask = info.start.mask; - DoPix(0, info.xorg + x, info.yorg + y); - DoPix(2, info.xorgo - x, info.yorgo - y); - if (arc->height & 1) - { - DoPix(1, info.xorgo - x, info.yorg + y); - DoPix(3, info.xorg + x, info.yorgo - y); - } - for (i = 0; i < 4; i++) - { - seg = (startseg + i) & 3; - pt = points + (seg * maxPts); - if (seg & 1) - { - startPts[i] = pt; - endPts[i] = arcPts[seg]; - deltas[i] = 1; - } - else - { - startPts[i] = arcPts[seg] - 1; - endPts[i] = pt - 1; - deltas[i] = -1; - } - } - startPts[4] = startPts[0]; - endPts[4] = startPt; - startPts[0] = startPt; - if (startseg & 1) - { - if (startPts[4] != endPts[4]) - endPts[4]--; - deltas[4] = 1; - } - else - { - if (startPts[0] > startPts[4]) - startPts[0]--; - if (startPts[4] < endPts[4]) - endPts[4]--; - deltas[4] = -1; - } - if (arc->angle2 < 0) - { - DDXPointPtr tmps, tmpe; - int tmpd; - - tmpd = deltas[0]; - tmps = startPts[0] - tmpd; - tmpe = endPts[0] - tmpd; - startPts[0] = endPts[4] - deltas[4]; - endPts[0] = startPts[4] - deltas[4]; - deltas[0] = -deltas[4]; - startPts[4] = tmpe; - endPts[4] = tmps; - deltas[4] = -tmpd; - tmpd = deltas[1]; - tmps = startPts[1] - tmpd; - tmpe = endPts[1] - tmpd; - startPts[1] = endPts[3] - deltas[3]; - endPts[1] = startPts[3] - deltas[3]; - deltas[1] = -deltas[3]; - startPts[3] = tmpe; - endPts[3] = tmps; - deltas[3] = -tmpd; - tmps = startPts[2] - deltas[2]; - startPts[2] = endPts[2] - deltas[2]; - endPts[2] = tmps; - deltas[2] = -deltas[2]; - } - for (i = 0; i < 5 && startPts[i] == endPts[i]; i++) - ; - if (i == 5) - return; - pt = startPts[i]; - for (j = 4; startPts[j] == endPts[j]; j--) - ; - lastPt = endPts[j] - deltas[j]; - if (dinfo->haveLast && - (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y)) - { - startPts[i] += deltas[i]; - } - else - { - dinfo->dashIndex = dinfo->dashIndexInit; - dinfo->dashOffset = dinfo->dashOffsetInit; - } - if (!dinfo->skipStart && (info.startAngle != info.endAngle)) - { - dinfo->startPt = *pt; - dinfo->haveStart = TRUE; - } - else if (!dinfo->skipLast && dinfo->haveStart && - (lastPt->x == dinfo->startPt.x) && - (lastPt->y == dinfo->startPt.y) && - (lastPt != startPts[i])) - endPts[j] = lastPt; - if (info.startAngle != info.endAngle) - { - dinfo->haveLast = TRUE; - dinfo->endPt = *lastPt; - } - dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset; - for (i = 0; i < 5; i++) - { - pt = startPts[i]; - lastPt = endPts[i]; - delta = deltas[i]; - while (pt != lastPt) - { - if (dinfo->dashIndex & 1) - { - pts = *oddPts; - ptsdelta = -1; - } - else - { - pts = *evenPts; - ptsdelta = 1; - } - while ((pt != lastPt) && --dashRemaining >= 0) - { - *pts = *pt; - pts += ptsdelta; - pt += delta; - } - if (dinfo->dashIndex & 1) - *oddPts = pts; - else - *evenPts = pts; - if (dashRemaining <= 0) - { - if (++(dinfo->dashIndex) == pGC->numInDashList) - dinfo->dashIndex = 0; - dashRemaining = pGC->dash[dinfo->dashIndex]; - } - } - } - dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining; -} - -void -miZeroPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) -{ - int maxPts = 0; - int n, maxw = 0; - xArc *arc; - int i; - DDXPointPtr points, pts, oddPts = NULL; - DDXPointPtr pt; - int numPts; - Bool dospans; - int *widths = NULL; - XID fgPixel = pGC->fgPixel; - DashInfo dinfo; - - for (arc = parcs, i = narcs; --i >= 0; arc++) - { - if (!miCanZeroArc(arc)) - miPolyArc(pDraw, pGC, 1, arc); - else - { - if (arc->width > arc->height) - n = arc->width + (arc->height >> 1); - else - n = arc->height + (arc->width >> 1); - if (n > maxPts) - maxPts = n; - } - } - if (!maxPts) - return; - numPts = maxPts << 2; - dospans = (pGC->fillStyle != FillSolid); - if (dospans) - { - widths = xalloc(sizeof(int) * numPts); - if (!widths) - return; - maxw = 0; - } - if (pGC->lineStyle != LineSolid) - { - numPts <<= 1; - dinfo.haveStart = FALSE; - dinfo.skipStart = FALSE; - dinfo.haveLast = FALSE; - dinfo.dashIndexInit = 0; - dinfo.dashOffsetInit = 0; - miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit, - (unsigned char *) pGC->dash, (int)pGC->numInDashList, - &dinfo.dashOffsetInit); - } - points = xalloc(sizeof(DDXPointRec) * numPts); - if (!points) - { - if (dospans) - { - xfree(widths); - } - return; - } - for (arc = parcs, i = narcs; --i >= 0; arc++) - { - if (miCanZeroArc(arc)) - { - if (pGC->lineStyle == LineSolid) - pts = miZeroArcPts(arc, points); - else - { - pts = points; - oddPts = &points[(numPts >> 1) - 1]; - dinfo.skipLast = i; - miZeroArcDashPts(pGC, arc, &dinfo, - oddPts + 1, maxPts, &pts, &oddPts); - dinfo.skipStart = TRUE; - } - n = pts - points; - if (!dospans) - (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points); - else - { - if (n > maxw) - { - while (maxw < n) - widths[maxw++] = 1; - } - if (pGC->miTranslate) - { - for (pt = points; pt != pts; pt++) - { - pt->x += pDraw->x; - pt->y += pDraw->y; - } - } - (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE); - } - if (pGC->lineStyle != LineDoubleDash) - continue; - if ((pGC->fillStyle == FillSolid) || - (pGC->fillStyle == FillStippled)) - { - DoChangeGC(pGC, GCForeground, (XID *)&pGC->bgPixel, 0); - ValidateGC(pDraw, pGC); - } - pts = &points[numPts >> 1]; - oddPts++; - n = pts - oddPts; - if (!dospans) - (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts); - else - { - if (n > maxw) - { - while (maxw < n) - widths[maxw++] = 1; - } - if (pGC->miTranslate) - { - for (pt = oddPts; pt != pts; pt++) - { - pt->x += pDraw->x; - pt->y += pDraw->y; - } - } - (*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE); - } - if ((pGC->fillStyle == FillSolid) || - (pGC->fillStyle == FillStippled)) - { - DoChangeGC(pGC, GCForeground, &fgPixel, 0); - ValidateGC(pDraw, pGC); - } - } - } - xfree(points); - if (dospans) - { - xfree(widths); - } -} +/************************************************************
+
+Copyright 1989, 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.
+
+Author: Bob Scheifler, MIT X Consortium
+
+********************************************************/
+
+
+/* Derived from:
+ * "Algorithm for drawing ellipses or hyperbolae with a digital plotter"
+ * by M. L. V. Pitteway
+ * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <math.h>
+#include <X11/X.h>
+#include <X11/Xprotostr.h>
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "mi.h"
+#include "mizerarc.h"
+
+#define FULLCIRCLE (360 * 64)
+#define OCTANT (45 * 64)
+#define QUADRANT (90 * 64)
+#define HALFCIRCLE (180 * 64)
+#define QUADRANT3 (270 * 64)
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define Dsin(d) ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \
+ ((d) == HALFCIRCLE ? 0.0 : \
+ ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0))))))
+
+#define Dcos(d) ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \
+ ((d) == HALFCIRCLE ? -1.0 : \
+ ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0))))))
+
+#define EPSILON45 64
+
+typedef struct {
+ int skipStart;
+ int haveStart;
+ DDXPointRec startPt;
+ int haveLast;
+ int skipLast;
+ DDXPointRec endPt;
+ int dashIndex;
+ int dashOffset;
+ int dashIndexInit;
+ int dashOffsetInit;
+} DashInfo;
+
+static miZeroArcPtRec oob = {65536, 65536, 0};
+
+/*
+ * (x - l)^2 / (W/2)^2 + (y + H/2)^2 / (H/2)^2 = 1
+ *
+ * where l is either 0 or .5
+ *
+ * alpha = 4(W^2)
+ * beta = 4(H^2)
+ * gamma = 0
+ * u = 2(W^2)H
+ * v = 4(H^2)l
+ * k = -4(H^2)(l^2)
+ *
+ */
+
+Bool
+miZeroArcSetup(xArc *arc, miZeroArcRec *info, Bool ok360)
+{
+ int l;
+ int angle1, angle2;
+ int startseg, endseg;
+ int startAngle, endAngle;
+ int i, overlap;
+ miZeroArcPtRec start, end;
+
+ l = arc->width & 1;
+ if (arc->width == arc->height)
+ {
+ info->alpha = 4;
+ info->beta = 4;
+ info->k1 = -8;
+ info->k3 = -16;
+ info->b = 12;
+ info->a = (arc->width << 2) - 12;
+ info->d = 17 - (arc->width << 1);
+ if (l)
+ {
+ info->b -= 4;
+ info->a += 4;
+ info->d -= 7;
+ }
+ }
+ else if (!arc->width || !arc->height)
+ {
+ info->alpha = 0;
+ info->beta = 0;
+ info->k1 = 0;
+ info->k3 = 0;
+ info->a = -(int)arc->height;
+ info->b = 0;
+ info->d = -1;
+ }
+ else
+ {
+ /* initial conditions */
+ info->alpha = (arc->width * arc->width) << 2;
+ info->beta = (arc->height * arc->height) << 2;
+ info->k1 = info->beta << 1;
+ info->k3 = info->k1 + (info->alpha << 1);
+ info->b = l ? 0 : -info->beta;
+ info->a = info->alpha * arc->height;
+ info->d = info->b - (info->a >> 1) - (info->alpha >> 2);
+ if (l)
+ info->d -= info->beta >> 2;
+ info->a -= info->b;
+ /* take first step, d < 0 always */
+ info->b -= info->k1;
+ info->a += info->k1;
+ info->d += info->b;
+ /* octant change, b < 0 always */
+ info->k1 = -info->k1;
+ info->k3 = -info->k3;
+ info->b = -info->b;
+ info->d = info->b - info->a - info->d;
+ info->a = info->a - (info->b << 1);
+ }
+ info->dx = 1;
+ info->dy = 0;
+ info->w = (arc->width + 1) >> 1;
+ info->h = arc->height >> 1;
+ info->xorg = arc->x + (arc->width >> 1);
+ info->yorg = arc->y;
+ info->xorgo = info->xorg + l;
+ info->yorgo = info->yorg + arc->height;
+ if (!arc->width)
+ {
+ if (!arc->height)
+ {
+ info->x = 0;
+ info->y = 0;
+ info->initialMask = 0;
+ info->startAngle = 0;
+ info->endAngle = 0;
+ info->start = oob;
+ info->end = oob;
+ return FALSE;
+ }
+ info->x = 0;
+ info->y = 1;
+ }
+ else
+ {
+ info->x = 1;
+ info->y = 0;
+ }
+ angle1 = arc->angle1;
+ angle2 = arc->angle2;
+ if ((angle1 == 0) && (angle2 >= FULLCIRCLE))
+ {
+ startAngle = 0;
+ endAngle = 0;
+ }
+ else
+ {
+ if (angle2 > FULLCIRCLE)
+ angle2 = FULLCIRCLE;
+ else if (angle2 < -FULLCIRCLE)
+ angle2 = -FULLCIRCLE;
+ if (angle2 < 0)
+ {
+ startAngle = angle1 + angle2;
+ endAngle = angle1;
+ }
+ else
+ {
+ startAngle = angle1;
+ endAngle = angle1 + angle2;
+ }
+ if (startAngle < 0)
+ startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
+ if (startAngle >= FULLCIRCLE)
+ startAngle = startAngle % FULLCIRCLE;
+ if (endAngle < 0)
+ endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
+ if (endAngle >= FULLCIRCLE)
+ endAngle = endAngle % FULLCIRCLE;
+ }
+ info->startAngle = startAngle;
+ info->endAngle = endAngle;
+ if (ok360 && (startAngle == endAngle) && arc->angle2 &&
+ arc->width && arc->height)
+ {
+ info->initialMask = 0xf;
+ info->start = oob;
+ info->end = oob;
+ return TRUE;
+ }
+ startseg = startAngle / OCTANT;
+ if (!arc->height || (((startseg + 1) & 2) && arc->width))
+ {
+ start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0);
+ if (start.x < 0)
+ start.x = -start.x;
+ start.y = -1;
+ }
+ else
+ {
+ start.y = Dsin(startAngle) * (arc->height / 2.0);
+ if (start.y < 0)
+ start.y = -start.y;
+ start.y = info->h - start.y;
+ start.x = 65536;
+ }
+ endseg = endAngle / OCTANT;
+ if (!arc->height || (((endseg + 1) & 2) && arc->width))
+ {
+ end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0);
+ if (end.x < 0)
+ end.x = -end.x;
+ end.y = -1;
+ }
+ else
+ {
+ end.y = Dsin(endAngle) * (arc->height / 2.0);
+ if (end.y < 0)
+ end.y = -end.y;
+ end.y = info->h - end.y;
+ end.x = 65536;
+ }
+ info->firstx = start.x;
+ info->firsty = start.y;
+ info->initialMask = 0;
+ overlap = arc->angle2 && (endAngle <= startAngle);
+ for (i = 0; i < 4; i++)
+ {
+ if (overlap ?
+ ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) :
+ ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle)))
+ info->initialMask |= (1 << i);
+ }
+ start.mask = info->initialMask;
+ end.mask = info->initialMask;
+ startseg >>= 1;
+ endseg >>= 1;
+ overlap = overlap && (endseg == startseg);
+ if (start.x != end.x || start.y != end.y || !overlap)
+ {
+ if (startseg & 1)
+ {
+ if (!overlap)
+ info->initialMask &= ~(1 << startseg);
+ if (start.x > end.x || start.y > end.y)
+ end.mask &= ~(1 << startseg);
+ }
+ else
+ {
+ start.mask &= ~(1 << startseg);
+ if (((start.x < end.x || start.y < end.y) ||
+ (start.x == end.x && start.y == end.y && (endseg & 1))) &&
+ !overlap)
+ end.mask &= ~(1 << startseg);
+ }
+ if (endseg & 1)
+ {
+ end.mask &= ~(1 << endseg);
+ if (((start.x > end.x || start.y > end.y) ||
+ (start.x == end.x && start.y == end.y && !(startseg & 1))) &&
+ !overlap)
+ start.mask &= ~(1 << endseg);
+ }
+ else
+ {
+ if (!overlap)
+ info->initialMask &= ~(1 << endseg);
+ if (start.x < end.x || start.y < end.y)
+ start.mask &= ~(1 << endseg);
+ }
+ }
+ /* take care of case when start and stop are both near 45 */
+ /* handle here rather than adding extra code to pixelization loops */
+ if (startAngle &&
+ ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0)))
+ {
+ i = (startAngle + OCTANT) % OCTANT;
+ if (i < EPSILON45 || i > OCTANT - EPSILON45)
+ {
+ i = (endAngle + OCTANT) % OCTANT;
+ if (i < EPSILON45 || i > OCTANT - EPSILON45)
+ {
+ if (start.y < 0)
+ {
+ i = Dsin(startAngle) * (arc->height / 2.0);
+ if (i < 0)
+ i = -i;
+ if (info->h - i == end.y)
+ start.mask = end.mask;
+ }
+ else
+ {
+ i = Dsin(endAngle) * (arc->height / 2.0);
+ if (i < 0)
+ i = -i;
+ if (info->h - i == start.y)
+ end.mask = start.mask;
+ }
+ }
+ }
+ }
+ if (startseg & 1)
+ {
+ info->start = start;
+ info->end = oob;
+ }
+ else
+ {
+ info->end = start;
+ info->start = oob;
+ }
+ if (endseg & 1)
+ {
+ info->altend = end;
+ if (info->altend.x < info->end.x || info->altend.y < info->end.y)
+ {
+ miZeroArcPtRec tmp;
+ tmp = info->altend;
+ info->altend = info->end;
+ info->end = tmp;
+ }
+ info->altstart = oob;
+ }
+ else
+ {
+ info->altstart = end;
+ if (info->altstart.x < info->start.x ||
+ info->altstart.y < info->start.y)
+ {
+ miZeroArcPtRec tmp;
+ tmp = info->altstart;
+ info->altstart = info->start;
+ info->start = tmp;
+ }
+ info->altend = oob;
+ }
+ if (!info->start.x || !info->start.y)
+ {
+ info->initialMask = info->start.mask;
+ info->start = info->altstart;
+ }
+ if (!arc->width && (arc->height == 1))
+ {
+ /* kludge! */
+ info->initialMask |= info->end.mask;
+ info->initialMask |= info->initialMask << 1;
+ info->end.x = 0;
+ info->end.mask = 0;
+ }
+ return FALSE;
+}
+
+#define Pixelate(xval,yval) \
+ { \
+ pts->x = xval; \
+ pts->y = yval; \
+ pts++; \
+ }
+
+#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval);
+
+static DDXPointPtr
+miZeroArcPts(xArc *arc, DDXPointPtr pts)
+{
+ miZeroArcRec info;
+ int x, y, a, b, d, mask;
+ int k1, k3, dx, dy;
+ Bool do360;
+
+ do360 = miZeroArcSetup(arc, &info, TRUE);
+ MIARCSETUP();
+ mask = info.initialMask;
+ if (!(arc->width & 1))
+ {
+ DoPix(1, info.xorgo, info.yorg);
+ DoPix(3, info.xorgo, info.yorgo);
+ }
+ if (!info.end.x || !info.end.y)
+ {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ if (do360 && (arc->width == arc->height) && !(arc->width & 1))
+ {
+ int yorgh = info.yorg + info.h;
+ int xorghp = info.xorg + info.h;
+ int xorghn = info.xorg - info.h;
+
+ while (1)
+ {
+ Pixelate(info.xorg + x, info.yorg + y);
+ Pixelate(info.xorg - x, info.yorg + y);
+ Pixelate(info.xorg - x, info.yorgo - y);
+ Pixelate(info.xorg + x, info.yorgo - y);
+ if (a < 0)
+ break;
+ Pixelate(xorghp - y, yorgh - x);
+ Pixelate(xorghn + y, yorgh - x);
+ Pixelate(xorghn + y, yorgh + x);
+ Pixelate(xorghp - y, yorgh + x);
+ MIARCCIRCLESTEP(;);
+ }
+ if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y)
+ pts -= 4;
+ x = info.w;
+ y = info.h;
+ }
+ else if (do360)
+ {
+ while (y < info.h || x < info.w)
+ {
+ MIARCOCTANTSHIFT(;);
+ Pixelate(info.xorg + x, info.yorg + y);
+ Pixelate(info.xorgo - x, info.yorg + y);
+ Pixelate(info.xorgo - x, info.yorgo - y);
+ Pixelate(info.xorg + x, info.yorgo - y);
+ MIARCSTEP(;,;);
+ }
+ }
+ else
+ {
+ while (y < info.h || x < info.w)
+ {
+ MIARCOCTANTSHIFT(;);
+ if ((x == info.start.x) || (y == info.start.y))
+ {
+ mask = info.start.mask;
+ info.start = info.altstart;
+ }
+ DoPix(0, info.xorg + x, info.yorg + y);
+ DoPix(1, info.xorgo - x, info.yorg + y);
+ DoPix(2, info.xorgo - x, info.yorgo - y);
+ DoPix(3, info.xorg + x, info.yorgo - y);
+ if ((x == info.end.x) || (y == info.end.y))
+ {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ MIARCSTEP(;,;);
+ }
+ }
+ if ((x == info.start.x) || (y == info.start.y))
+ mask = info.start.mask;
+ DoPix(0, info.xorg + x, info.yorg + y);
+ DoPix(2, info.xorgo - x, info.yorgo - y);
+ if (arc->height & 1)
+ {
+ DoPix(1, info.xorgo - x, info.yorg + y);
+ DoPix(3, info.xorg + x, info.yorgo - y);
+ }
+ return pts;
+}
+
+#undef DoPix
+#define DoPix(idx,xval,yval) \
+ if (mask & (1 << idx)) \
+ { \
+ arcPts[idx]->x = xval; \
+ arcPts[idx]->y = yval; \
+ arcPts[idx]++; \
+ }
+
+static void
+miZeroArcDashPts(
+ GCPtr pGC,
+ xArc *arc,
+ DashInfo *dinfo,
+ DDXPointPtr points,
+ int maxPts,
+ DDXPointPtr *evenPts,
+ DDXPointPtr *oddPts )
+{
+ miZeroArcRec info;
+ int x, y, a, b, d, mask;
+ int k1, k3, dx, dy;
+ int dashRemaining;
+ DDXPointPtr arcPts[4];
+ DDXPointPtr startPts[5], endPts[5];
+ int deltas[5];
+ DDXPointPtr startPt, pt, lastPt, pts;
+ int i, j, delta, ptsdelta, seg, startseg;
+
+ for (i = 0; i < 4; i++)
+ arcPts[i] = points + (i * maxPts);
+ (void)miZeroArcSetup(arc, &info, FALSE);
+ MIARCSETUP();
+ mask = info.initialMask;
+ startseg = info.startAngle / QUADRANT;
+ startPt = arcPts[startseg];
+ if (!(arc->width & 1))
+ {
+ DoPix(1, info.xorgo, info.yorg);
+ DoPix(3, info.xorgo, info.yorgo);
+ }
+ if (!info.end.x || !info.end.y)
+ {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ while (y < info.h || x < info.w)
+ {
+ MIARCOCTANTSHIFT(;);
+ if ((x == info.firstx) || (y == info.firsty))
+ startPt = arcPts[startseg];
+ if ((x == info.start.x) || (y == info.start.y))
+ {
+ mask = info.start.mask;
+ info.start = info.altstart;
+ }
+ DoPix(0, info.xorg + x, info.yorg + y);
+ DoPix(1, info.xorgo - x, info.yorg + y);
+ DoPix(2, info.xorgo - x, info.yorgo - y);
+ DoPix(3, info.xorg + x, info.yorgo - y);
+ if ((x == info.end.x) || (y == info.end.y))
+ {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ MIARCSTEP(;,;);
+ }
+ if ((x == info.firstx) || (y == info.firsty))
+ startPt = arcPts[startseg];
+ if ((x == info.start.x) || (y == info.start.y))
+ mask = info.start.mask;
+ DoPix(0, info.xorg + x, info.yorg + y);
+ DoPix(2, info.xorgo - x, info.yorgo - y);
+ if (arc->height & 1)
+ {
+ DoPix(1, info.xorgo - x, info.yorg + y);
+ DoPix(3, info.xorg + x, info.yorgo - y);
+ }
+ for (i = 0; i < 4; i++)
+ {
+ seg = (startseg + i) & 3;
+ pt = points + (seg * maxPts);
+ if (seg & 1)
+ {
+ startPts[i] = pt;
+ endPts[i] = arcPts[seg];
+ deltas[i] = 1;
+ }
+ else
+ {
+ startPts[i] = arcPts[seg] - 1;
+ endPts[i] = pt - 1;
+ deltas[i] = -1;
+ }
+ }
+ startPts[4] = startPts[0];
+ endPts[4] = startPt;
+ startPts[0] = startPt;
+ if (startseg & 1)
+ {
+ if (startPts[4] != endPts[4])
+ endPts[4]--;
+ deltas[4] = 1;
+ }
+ else
+ {
+ if (startPts[0] > startPts[4])
+ startPts[0]--;
+ if (startPts[4] < endPts[4])
+ endPts[4]--;
+ deltas[4] = -1;
+ }
+ if (arc->angle2 < 0)
+ {
+ DDXPointPtr tmps, tmpe;
+ int tmpd;
+
+ tmpd = deltas[0];
+ tmps = startPts[0] - tmpd;
+ tmpe = endPts[0] - tmpd;
+ startPts[0] = endPts[4] - deltas[4];
+ endPts[0] = startPts[4] - deltas[4];
+ deltas[0] = -deltas[4];
+ startPts[4] = tmpe;
+ endPts[4] = tmps;
+ deltas[4] = -tmpd;
+ tmpd = deltas[1];
+ tmps = startPts[1] - tmpd;
+ tmpe = endPts[1] - tmpd;
+ startPts[1] = endPts[3] - deltas[3];
+ endPts[1] = startPts[3] - deltas[3];
+ deltas[1] = -deltas[3];
+ startPts[3] = tmpe;
+ endPts[3] = tmps;
+ deltas[3] = -tmpd;
+ tmps = startPts[2] - deltas[2];
+ startPts[2] = endPts[2] - deltas[2];
+ endPts[2] = tmps;
+ deltas[2] = -deltas[2];
+ }
+ for (i = 0; i < 5 && startPts[i] == endPts[i]; i++)
+ ;
+ if (i == 5)
+ return;
+ pt = startPts[i];
+ for (j = 4; startPts[j] == endPts[j]; j--)
+ ;
+ lastPt = endPts[j] - deltas[j];
+ if (dinfo->haveLast &&
+ (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y))
+ {
+ startPts[i] += deltas[i];
+ }
+ else
+ {
+ dinfo->dashIndex = dinfo->dashIndexInit;
+ dinfo->dashOffset = dinfo->dashOffsetInit;
+ }
+ if (!dinfo->skipStart && (info.startAngle != info.endAngle))
+ {
+ dinfo->startPt = *pt;
+ dinfo->haveStart = TRUE;
+ }
+ else if (!dinfo->skipLast && dinfo->haveStart &&
+ (lastPt->x == dinfo->startPt.x) &&
+ (lastPt->y == dinfo->startPt.y) &&
+ (lastPt != startPts[i]))
+ endPts[j] = lastPt;
+ if (info.startAngle != info.endAngle)
+ {
+ dinfo->haveLast = TRUE;
+ dinfo->endPt = *lastPt;
+ }
+ dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
+ for (i = 0; i < 5; i++)
+ {
+ pt = startPts[i];
+ lastPt = endPts[i];
+ delta = deltas[i];
+ while (pt != lastPt)
+ {
+ if (dinfo->dashIndex & 1)
+ {
+ pts = *oddPts;
+ ptsdelta = -1;
+ }
+ else
+ {
+ pts = *evenPts;
+ ptsdelta = 1;
+ }
+ while ((pt != lastPt) && --dashRemaining >= 0)
+ {
+ *pts = *pt;
+ pts += ptsdelta;
+ pt += delta;
+ }
+ if (dinfo->dashIndex & 1)
+ *oddPts = pts;
+ else
+ *evenPts = pts;
+ if (dashRemaining <= 0)
+ {
+ if (++(dinfo->dashIndex) == pGC->numInDashList)
+ dinfo->dashIndex = 0;
+ dashRemaining = pGC->dash[dinfo->dashIndex];
+ }
+ }
+ }
+ dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
+}
+
+void
+miZeroPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
+{
+ int maxPts = 0;
+ int n, maxw = 0;
+ xArc *arc;
+ int i;
+ DDXPointPtr points, pts, oddPts = NULL;
+ DDXPointPtr pt;
+ int numPts;
+ Bool dospans;
+ int *widths = NULL;
+ XID fgPixel = pGC->fgPixel;
+ DashInfo dinfo;
+
+ for (arc = parcs, i = narcs; --i >= 0; arc++)
+ {
+ if (!miCanZeroArc(arc))
+ miPolyArc(pDraw, pGC, 1, arc);
+ else
+ {
+ if (arc->width > arc->height)
+ n = arc->width + (arc->height >> 1);
+ else
+ n = arc->height + (arc->width >> 1);
+ if (n > maxPts)
+ maxPts = n;
+ }
+ }
+ if (!maxPts)
+ return;
+ numPts = maxPts << 2;
+ dospans = (pGC->fillStyle != FillSolid);
+ if (dospans)
+ {
+ widths = malloc(sizeof(int) * numPts);
+ if (!widths)
+ return;
+ maxw = 0;
+ }
+ if (pGC->lineStyle != LineSolid)
+ {
+ numPts <<= 1;
+ dinfo.haveStart = FALSE;
+ dinfo.skipStart = FALSE;
+ dinfo.haveLast = FALSE;
+ dinfo.dashIndexInit = 0;
+ dinfo.dashOffsetInit = 0;
+ miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit,
+ (unsigned char *) pGC->dash, (int)pGC->numInDashList,
+ &dinfo.dashOffsetInit);
+ }
+ points = malloc(sizeof(DDXPointRec) * numPts);
+ if (!points)
+ {
+ if (dospans)
+ {
+ free(widths);
+ }
+ return;
+ }
+ for (arc = parcs, i = narcs; --i >= 0; arc++)
+ {
+ if (miCanZeroArc(arc))
+ {
+ if (pGC->lineStyle == LineSolid)
+ pts = miZeroArcPts(arc, points);
+ else
+ {
+ pts = points;
+ oddPts = &points[(numPts >> 1) - 1];
+ dinfo.skipLast = i;
+ miZeroArcDashPts(pGC, arc, &dinfo,
+ oddPts + 1, maxPts, &pts, &oddPts);
+ dinfo.skipStart = TRUE;
+ }
+ n = pts - points;
+ if (!dospans)
+ (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points);
+ else
+ {
+ if (n > maxw)
+ {
+ while (maxw < n)
+ widths[maxw++] = 1;
+ }
+ if (pGC->miTranslate)
+ {
+ for (pt = points; pt != pts; pt++)
+ {
+ pt->x += pDraw->x;
+ pt->y += pDraw->y;
+ }
+ }
+ (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE);
+ }
+ if (pGC->lineStyle != LineDoubleDash)
+ continue;
+ if ((pGC->fillStyle == FillSolid) ||
+ (pGC->fillStyle == FillStippled))
+ {
+ ChangeGCVal gcval;
+ gcval.val = pGC->bgPixel;
+ ChangeGC(NullClient, pGC, GCForeground, &gcval);
+ ValidateGC(pDraw, pGC);
+ }
+ pts = &points[numPts >> 1];
+ oddPts++;
+ n = pts - oddPts;
+ if (!dospans)
+ (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts);
+ else
+ {
+ if (n > maxw)
+ {
+ while (maxw < n)
+ widths[maxw++] = 1;
+ }
+ if (pGC->miTranslate)
+ {
+ for (pt = oddPts; pt != pts; pt++)
+ {
+ pt->x += pDraw->x;
+ pt->y += pDraw->y;
+ }
+ }
+ (*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE);
+ }
+ if ((pGC->fillStyle == FillSolid) ||
+ (pGC->fillStyle == FillStippled))
+ {
+ ChangeGCVal gcval;
+ gcval.val = fgPixel;
+ ChangeGC(NullClient, pGC, GCForeground, &gcval);
+ ValidateGC(pDraw, pGC);
+ }
+ }
+ }
+ free(points);
+ if (dospans)
+ {
+ free(widths);
+ }
+}
diff --git a/xorg-server/mi/mizerline.c b/xorg-server/mi/mizerline.c index 46e2e2adc..d37e1cc96 100644 --- a/xorg-server/mi/mizerline.c +++ b/xorg-server/mi/mizerline.c @@ -1,379 +1,379 @@ -/*********************************************************** - -Copyright 1987, 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. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 <X11/X.h> - -#include "misc.h" -#include "scrnintstr.h" -#include "gcstruct.h" -#include "windowstr.h" -#include "pixmap.h" -#include "mi.h" -#include "miline.h" - -/* Draw lineSolid, fillStyle-independent zero width lines. - * - * Must keep X and Y coordinates in "ints" at least until after they're - * translated and clipped to accomodate CoordModePrevious lines with very - * large coordinates. - * - * Draws the same pixels regardless of sign(dx) or sign(dy). - * - * Ken Whaley - * - */ - -/* largest positive value that can fit into a component of a point. - * Assumes that the point structure is {type x, y;} where type is - * a signed type. - */ -#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1) - -#define MI_OUTPUT_POINT(xx, yy)\ -{\ - if ( !new_span && yy == current_y)\ - {\ - if (xx < spans->x)\ - spans->x = xx;\ - ++*widths;\ - }\ - else\ - {\ - ++Nspans;\ - ++spans;\ - ++widths;\ - spans->x = xx;\ - spans->y = yy;\ - *widths = 1;\ - current_y = yy;\ - new_span = FALSE;\ - }\ -} - -void -miZeroLine( - DrawablePtr pDraw, - GCPtr pGC, - int mode, /* Origin or Previous */ - int npt, /* number of points */ - DDXPointPtr pptInit) -{ - int Nspans, current_y = 0; - DDXPointPtr ppt; - DDXPointPtr pspanInit, spans; - int *pwidthInit, *widths, list_len; - int xleft, ytop, xright, ybottom; - int new_x1, new_y1, new_x2, new_y2; - int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart; - int oc1, oc2; - int result; - int pt1_clipped, pt2_clipped = 0; - Bool new_span; - int signdx, signdy; - int clipdx, clipdy; - int width, height; - int adx, ady; - int octant; - unsigned int bias = miGetZeroLineBias(pDraw->pScreen); - int e, e1, e2, e3; /* Bresenham error terms */ - int length; /* length of lines == # of pixels on major axis */ - - xleft = pDraw->x; - ytop = pDraw->y; - xright = pDraw->x + pDraw->width - 1; - ybottom = pDraw->y + pDraw->height - 1; - - if (!pGC->miTranslate) - { - /* do everything in drawable-relative coordinates */ - xleft = 0; - ytop = 0; - xright -= pDraw->x; - ybottom -= pDraw->y; - } - - /* it doesn't matter whether we're in drawable or screen coordinates, - * FillSpans simply cannot take starting coordinates outside of the - * range of a DDXPointRec component. - */ - if (xright > MAX_COORDINATE) - xright = MAX_COORDINATE; - if (ybottom > MAX_COORDINATE) - ybottom = MAX_COORDINATE; - - /* since we're clipping to the drawable's boundaries & coordinate - * space boundaries, we're guaranteed that the larger of width/height - * is the longest span we'll need to output - */ - width = xright - xleft + 1; - height = ybottom - ytop + 1; - list_len = (height >= width) ? height : width; - pspanInit = xalloc(list_len * sizeof(DDXPointRec)); - pwidthInit = xalloc(list_len * sizeof(int)); - if (!pspanInit || !pwidthInit) - return; - - Nspans = 0; - new_span = TRUE; - spans = pspanInit - 1; - widths = pwidthInit - 1; - ppt = pptInit; - - xstart = ppt->x; - ystart = ppt->y; - if (pGC->miTranslate) - { - xstart += pDraw->x; - ystart += pDraw->y; - } - - /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify - * iteration logic - */ - x2 = xstart; - y2 = ystart; - oc2 = 0; - MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); - - while (--npt > 0) - { - if (Nspans > 0) - (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, - pwidthInit, FALSE); - Nspans = 0; - new_span = TRUE; - spans = pspanInit - 1; - widths = pwidthInit - 1; - - x1 = x2; - y1 = y2; - oc1 = oc2; - ++ppt; - - x2 = ppt->x; - y2 = ppt->y; - if (pGC->miTranslate && (mode != CoordModePrevious)) - { - x2 += pDraw->x; - y2 += pDraw->y; - } - else if (mode == CoordModePrevious) - { - x2 += x1; - y2 += y1; - } - - oc2 = 0; - MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); - - CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); - - if (adx > ady) - { - e1 = ady << 1; - e2 = e1 - (adx << 1); - e = e1 - adx; - length = adx; /* don't draw endpoint in main loop */ - - FIXUP_ERROR(e, octant, bias); - - new_x1 = x1; - new_y1 = y1; - new_x2 = x2; - new_y2 = y2; - pt1_clipped = 0; - pt2_clipped = 0; - - if ((oc1 | oc2) != 0) - { - result = miZeroClipLine(xleft, ytop, xright, ybottom, - &new_x1, &new_y1, &new_x2, &new_y2, - adx, ady, - &pt1_clipped, &pt2_clipped, - octant, bias, oc1, oc2); - if (result == -1) - continue; - - length = abs(new_x2 - new_x1); - - /* if we've clipped the endpoint, always draw the full length - * of the segment, because then the capstyle doesn't matter - */ - if (pt2_clipped) - length++; - - if (pt1_clipped) - { - /* must calculate new error terms */ - clipdx = abs(new_x1 - x1); - clipdy = abs(new_y1 - y1); - e += (clipdy * e2) + ((clipdx - clipdy) * e1); - } - } - - /* draw the segment */ - - x = new_x1; - y = new_y1; - - e3 = e2 - e1; - e = e - e1; - - while (length--) - { - MI_OUTPUT_POINT(x, y); - e += e1; - if (e >= 0) - { - y += signdy; - e += e3; - } - x += signdx; - } - } - else /* Y major line */ - { - e1 = adx << 1; - e2 = e1 - (ady << 1); - e = e1 - ady; - length = ady; /* don't draw endpoint in main loop */ - - SetYMajorOctant(octant); - FIXUP_ERROR(e, octant, bias); - - new_x1 = x1; - new_y1 = y1; - new_x2 = x2; - new_y2 = y2; - pt1_clipped = 0; - pt2_clipped = 0; - - if ((oc1 | oc2) != 0) - { - result = miZeroClipLine(xleft, ytop, xright, ybottom, - &new_x1, &new_y1, &new_x2, &new_y2, - adx, ady, - &pt1_clipped, &pt2_clipped, - octant, bias, oc1, oc2); - if (result == -1) - continue; - - length = abs(new_y2 - new_y1); - - /* if we've clipped the endpoint, always draw the full length - * of the segment, because then the capstyle doesn't matter - */ - if (pt2_clipped) - length++; - - if (pt1_clipped) - { - /* must calculate new error terms */ - clipdx = abs(new_x1 - x1); - clipdy = abs(new_y1 - y1); - e += (clipdx * e2) + ((clipdy - clipdx) * e1); - } - } - - /* draw the segment */ - - x = new_x1; - y = new_y1; - - e3 = e2 - e1; - e = e - e1; - - while (length--) - { - MI_OUTPUT_POINT(x, y); - e += e1; - if (e >= 0) - { - x += signdx; - e += e3; - } - y += signdy; - } - } - } - - /* only do the capnotlast check on the last segment - * and only if the endpoint wasn't clipped. And then, if the last - * point is the same as the first point, do not draw it, unless the - * line is degenerate - */ - if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) && - (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1))) - { - MI_OUTPUT_POINT(x, y); - } - - if (Nspans > 0) - (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, - pwidthInit, FALSE); - - xfree(pwidthInit); - xfree(pspanInit); -} - -void -miZeroDashLine( - DrawablePtr dst, - GCPtr pgc, - int mode, - int nptInit, /* number of points in polyline */ - DDXPointRec *pptInit /* points in the polyline */ - ) -{ - /* XXX kludge until real zero-width dash code is written */ - pgc->lineWidth = 1; - miWideDash (dst, pgc, mode, nptInit, pptInit); - pgc->lineWidth = 0; -} +/***********************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 <X11/X.h>
+
+#include "misc.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "pixmap.h"
+#include "mi.h"
+#include "miline.h"
+
+/* Draw lineSolid, fillStyle-independent zero width lines.
+ *
+ * Must keep X and Y coordinates in "ints" at least until after they're
+ * translated and clipped to accomodate CoordModePrevious lines with very
+ * large coordinates.
+ *
+ * Draws the same pixels regardless of sign(dx) or sign(dy).
+ *
+ * Ken Whaley
+ *
+ */
+
+/* largest positive value that can fit into a component of a point.
+ * Assumes that the point structure is {type x, y;} where type is
+ * a signed type.
+ */
+#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1)
+
+#define MI_OUTPUT_POINT(xx, yy)\
+{\
+ if ( !new_span && yy == current_y)\
+ {\
+ if (xx < spans->x)\
+ spans->x = xx;\
+ ++*widths;\
+ }\
+ else\
+ {\
+ ++Nspans;\
+ ++spans;\
+ ++widths;\
+ spans->x = xx;\
+ spans->y = yy;\
+ *widths = 1;\
+ current_y = yy;\
+ new_span = FALSE;\
+ }\
+}
+
+void
+miZeroLine(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode, /* Origin or Previous */
+ int npt, /* number of points */
+ DDXPointPtr pptInit)
+{
+ int Nspans, current_y = 0;
+ DDXPointPtr ppt;
+ DDXPointPtr pspanInit, spans;
+ int *pwidthInit, *widths, list_len;
+ int xleft, ytop, xright, ybottom;
+ int new_x1, new_y1, new_x2, new_y2;
+ int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart;
+ int oc1, oc2;
+ int result;
+ int pt1_clipped, pt2_clipped = 0;
+ Bool new_span;
+ int signdx, signdy;
+ int clipdx, clipdy;
+ int width, height;
+ int adx, ady;
+ int octant;
+ unsigned int bias = miGetZeroLineBias(pDraw->pScreen);
+ int e, e1, e2, e3; /* Bresenham error terms */
+ int length; /* length of lines == # of pixels on major axis */
+
+ xleft = pDraw->x;
+ ytop = pDraw->y;
+ xright = pDraw->x + pDraw->width - 1;
+ ybottom = pDraw->y + pDraw->height - 1;
+
+ if (!pGC->miTranslate)
+ {
+ /* do everything in drawable-relative coordinates */
+ xleft = 0;
+ ytop = 0;
+ xright -= pDraw->x;
+ ybottom -= pDraw->y;
+ }
+
+ /* it doesn't matter whether we're in drawable or screen coordinates,
+ * FillSpans simply cannot take starting coordinates outside of the
+ * range of a DDXPointRec component.
+ */
+ if (xright > MAX_COORDINATE)
+ xright = MAX_COORDINATE;
+ if (ybottom > MAX_COORDINATE)
+ ybottom = MAX_COORDINATE;
+
+ /* since we're clipping to the drawable's boundaries & coordinate
+ * space boundaries, we're guaranteed that the larger of width/height
+ * is the longest span we'll need to output
+ */
+ width = xright - xleft + 1;
+ height = ybottom - ytop + 1;
+ list_len = (height >= width) ? height : width;
+ pspanInit = malloc(list_len * sizeof(DDXPointRec));
+ pwidthInit = malloc(list_len * sizeof(int));
+ if (!pspanInit || !pwidthInit)
+ return;
+
+ Nspans = 0;
+ new_span = TRUE;
+ spans = pspanInit - 1;
+ widths = pwidthInit - 1;
+ ppt = pptInit;
+
+ xstart = ppt->x;
+ ystart = ppt->y;
+ if (pGC->miTranslate)
+ {
+ xstart += pDraw->x;
+ ystart += pDraw->y;
+ }
+
+ /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify
+ * iteration logic
+ */
+ x2 = xstart;
+ y2 = ystart;
+ oc2 = 0;
+ MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
+
+ while (--npt > 0)
+ {
+ if (Nspans > 0)
+ (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
+ pwidthInit, FALSE);
+ Nspans = 0;
+ new_span = TRUE;
+ spans = pspanInit - 1;
+ widths = pwidthInit - 1;
+
+ x1 = x2;
+ y1 = y2;
+ oc1 = oc2;
+ ++ppt;
+
+ x2 = ppt->x;
+ y2 = ppt->y;
+ if (pGC->miTranslate && (mode != CoordModePrevious))
+ {
+ x2 += pDraw->x;
+ y2 += pDraw->y;
+ }
+ else if (mode == CoordModePrevious)
+ {
+ x2 += x1;
+ y2 += y1;
+ }
+
+ oc2 = 0;
+ MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
+
+ CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
+
+ if (adx > ady)
+ {
+ e1 = ady << 1;
+ e2 = e1 - (adx << 1);
+ e = e1 - adx;
+ length = adx; /* don't draw endpoint in main loop */
+
+ FIXUP_ERROR(e, octant, bias);
+
+ new_x1 = x1;
+ new_y1 = y1;
+ new_x2 = x2;
+ new_y2 = y2;
+ pt1_clipped = 0;
+ pt2_clipped = 0;
+
+ if ((oc1 | oc2) != 0)
+ {
+ result = miZeroClipLine(xleft, ytop, xright, ybottom,
+ &new_x1, &new_y1, &new_x2, &new_y2,
+ adx, ady,
+ &pt1_clipped, &pt2_clipped,
+ octant, bias, oc1, oc2);
+ if (result == -1)
+ continue;
+
+ length = abs(new_x2 - new_x1);
+
+ /* if we've clipped the endpoint, always draw the full length
+ * of the segment, because then the capstyle doesn't matter
+ */
+ if (pt2_clipped)
+ length++;
+
+ if (pt1_clipped)
+ {
+ /* must calculate new error terms */
+ clipdx = abs(new_x1 - x1);
+ clipdy = abs(new_y1 - y1);
+ e += (clipdy * e2) + ((clipdx - clipdy) * e1);
+ }
+ }
+
+ /* draw the segment */
+
+ x = new_x1;
+ y = new_y1;
+
+ e3 = e2 - e1;
+ e = e - e1;
+
+ while (length--)
+ {
+ MI_OUTPUT_POINT(x, y);
+ e += e1;
+ if (e >= 0)
+ {
+ y += signdy;
+ e += e3;
+ }
+ x += signdx;
+ }
+ }
+ else /* Y major line */
+ {
+ e1 = adx << 1;
+ e2 = e1 - (ady << 1);
+ e = e1 - ady;
+ length = ady; /* don't draw endpoint in main loop */
+
+ SetYMajorOctant(octant);
+ FIXUP_ERROR(e, octant, bias);
+
+ new_x1 = x1;
+ new_y1 = y1;
+ new_x2 = x2;
+ new_y2 = y2;
+ pt1_clipped = 0;
+ pt2_clipped = 0;
+
+ if ((oc1 | oc2) != 0)
+ {
+ result = miZeroClipLine(xleft, ytop, xright, ybottom,
+ &new_x1, &new_y1, &new_x2, &new_y2,
+ adx, ady,
+ &pt1_clipped, &pt2_clipped,
+ octant, bias, oc1, oc2);
+ if (result == -1)
+ continue;
+
+ length = abs(new_y2 - new_y1);
+
+ /* if we've clipped the endpoint, always draw the full length
+ * of the segment, because then the capstyle doesn't matter
+ */
+ if (pt2_clipped)
+ length++;
+
+ if (pt1_clipped)
+ {
+ /* must calculate new error terms */
+ clipdx = abs(new_x1 - x1);
+ clipdy = abs(new_y1 - y1);
+ e += (clipdx * e2) + ((clipdy - clipdx) * e1);
+ }
+ }
+
+ /* draw the segment */
+
+ x = new_x1;
+ y = new_y1;
+
+ e3 = e2 - e1;
+ e = e - e1;
+
+ while (length--)
+ {
+ MI_OUTPUT_POINT(x, y);
+ e += e1;
+ if (e >= 0)
+ {
+ x += signdx;
+ e += e3;
+ }
+ y += signdy;
+ }
+ }
+ }
+
+ /* only do the capnotlast check on the last segment
+ * and only if the endpoint wasn't clipped. And then, if the last
+ * point is the same as the first point, do not draw it, unless the
+ * line is degenerate
+ */
+ if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) &&
+ (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1)))
+ {
+ MI_OUTPUT_POINT(x, y);
+ }
+
+ if (Nspans > 0)
+ (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
+ pwidthInit, FALSE);
+
+ free(pwidthInit);
+ free(pspanInit);
+}
+
+void
+miZeroDashLine(
+ DrawablePtr dst,
+ GCPtr pgc,
+ int mode,
+ int nptInit, /* number of points in polyline */
+ DDXPointRec *pptInit /* points in the polyline */
+ )
+{
+ /* XXX kludge until real zero-width dash code is written */
+ pgc->lineWidth = 1;
+ miWideDash (dst, pgc, mode, nptInit, pptInit);
+ pgc->lineWidth = 0;
+}
|