aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/mi
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-05-15 16:28:11 +0000
committermarha <marha@users.sourceforge.net>2010-05-15 16:28:11 +0000
commitc38dead3ea7e177728d90cd815cf4eead0c9f534 (patch)
treeb809dba1dc9013bb1e67a5ee388f2dd217dc0f88 /xorg-server/mi
parent6083a94d68878c9ad5f59b28bd07e4738e9fb7b4 (diff)
downloadvcxsrv-c38dead3ea7e177728d90cd815cf4eead0c9f534.tar.gz
vcxsrv-c38dead3ea7e177728d90cd815cf4eead0c9f534.tar.bz2
vcxsrv-c38dead3ea7e177728d90cd815cf4eead0c9f534.zip
xserver git update 15/5/2010
Diffstat (limited to 'xorg-server/mi')
-rw-r--r--xorg-server/mi/miarc.c102
-rw-r--r--xorg-server/mi/mibitblt.c1661
-rw-r--r--xorg-server/mi/micmap.c1332
-rw-r--r--xorg-server/mi/micopy.c708
-rw-r--r--xorg-server/mi/midispcur.c1748
-rw-r--r--xorg-server/mi/mieq.c4
-rw-r--r--xorg-server/mi/miexpose.c1399
-rw-r--r--xorg-server/mi/mifillarc.c1596
-rw-r--r--xorg-server/mi/mifillrct.c286
-rw-r--r--xorg-server/mi/mifpolycon.c560
-rw-r--r--xorg-server/mi/migc.c510
-rw-r--r--xorg-server/mi/miglblt.c516
-rw-r--r--xorg-server/mi/mioverlay.c3896
-rw-r--r--xorg-server/mi/mipointer.c1172
-rw-r--r--xorg-server/mi/mipolycon.c494
-rw-r--r--xorg-server/mi/mipolygen.c460
-rw-r--r--xorg-server/mi/mipolypnt.c250
-rw-r--r--xorg-server/mi/mipolyrect.c374
-rw-r--r--xorg-server/mi/mipolyutil.c770
-rw-r--r--xorg-server/mi/mipushpxl.c542
-rw-r--r--xorg-server/mi/miregion.c3690
-rw-r--r--xorg-server/mi/miscrinit.c625
-rw-r--r--xorg-server/mi/mispans.c1058
-rw-r--r--xorg-server/mi/misprite.c2230
-rw-r--r--xorg-server/mi/miwideline.c4453
-rw-r--r--xorg-server/mi/miwideline.h236
-rw-r--r--xorg-server/mi/miwindow.c1672
-rw-r--r--xorg-server/mi/mizerarc.c1692
-rw-r--r--xorg-server/mi/mizerline.c758
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, &reg, &box, 1);
-
- REGION_INTERSECT(pScreen, &reg, &reg, clipList);
- if (generateExposures)
- (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
- else if (pWin->backgroundState != None)
- miPaintWindow(pWin, &reg, PW_BACKGROUND);
- REGION_UNINIT(pScreen, &reg);
- 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, &reg, &box, 1);
+
+ REGION_INTERSECT(pScreen, &reg, &reg, clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
+ else if (pWin->backgroundState != None)
+ miPaintWindow(pWin, &reg, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, &reg);
+ 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, &reg, &box, 1);
-
- REGION_INTERSECT(pScreen, &reg, &reg, &pWin->clipList);
- if (generateExposures)
- (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
- else if (pWin->backgroundState != None)
- miPaintWindow(pWin, &reg, PW_BACKGROUND);
- REGION_UNINIT(pScreen, &reg);
- 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, &reg, &box, 1);
+
+ REGION_INTERSECT(pScreen, &reg, &reg, &pWin->clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
+ else if (pWin->backgroundState != None)
+ miPaintWindow(pWin, &reg, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, &reg);
+ 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;
+}