RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler) (10/10/87)
Date: Tue, 6 Oct 87 15:35:08 PDT
From: Geoff Kuenning <bilbo.geoff@CS.UCLA.EDU>
VERSION:
X11 release 1
SYNOPSIS:
miClipSpans doesn't check all boxes if !fSorted
DESCRIPTION:
The code for fSorted == FALSE in miClipSpans appears to have
been erroneously copied from the fSorted == TRUE code, and
breaks out of the loop before checking all boxes. This can
cause clipping errors.
REPEAT-BY:
Build a server that uses miClipSpans, and run ico in a window
that has lots of partial overlaps, so that it has lots of
clip boxes. Note that the icosahedron often disappears.
FIX:
in server/ddx/mi/miregion.c, replace the RCS header with
/* $Header: miregion.c,v 1.28 87/10/08 13:48:14 rws Exp $ */
and replace miClipSpans with the following (sending entire
thing is smaller than the diffs) (for an RT server with a
broken hc, you may have to play with ++s):
int
miClipSpans(prgnDst, ppt, pwidth, nspans, pptNew, pwidthNew, fSorted)
RegionPtr prgnDst;
register DDXPointPtr ppt;
register int *pwidth;
int nspans;
register DDXPointPtr pptNew;
int *pwidthNew;
int fSorted;
{
register BoxPtr pbox, pboxLast;
BoxPtr pboxTest;
register DDXPointPtr pptLast;
int yMax;
int *pwidthNewThatWeWerePassed; /* the vengeance
of Xerox! */
pptLast = ppt + nspans;
pboxTest = prgnDst->rects;
pboxLast = pboxTest + prgnDst->numRects;
yMax = prgnDst->extents.y2;
pwidthNewThatWeWerePassed = pwidthNew;
for (; ppt < pptLast; ppt++, pwidth++)
{
if(fSorted)
{
if(ppt->y >= yMax)
break;
pbox = pboxTest;
}
else
{
if(ppt->y >= yMax)
continue;
pbox = prgnDst->rects;
}
if(*pwidth == 0)
continue;
while(pbox < pboxLast)
{
if(pbox->y1 > ppt->y)
{
/* scanline is before clip box */
break;
}
if(pbox->y2 <= ppt->y)
{
/* clip box is before scanline */
pboxTest = ++pbox;
continue;
}
if(pbox->x1 >= ppt->x + *pwidth)
{
/* clip box is to right of scanline */
break;
}
if(pbox->x2 <= ppt->x)
{
/* scanline is to right of clip box */
pbox++;
continue;
}
/* at least some of the scanline is in the current clip box */
pptNew->x = max(pbox->x1, ppt->x);
pptNew->y = ppt->y;
*pwidthNew++ = min(ppt->x + *pwidth, pbox->x2) - pptNew->x;
pptNew++;
pbox++;
}
}
return (pwidthNew - pwidthNewThatWeWerePassed);
}