[comp.windows.x] V11 miClipSpans quits early when fSorted is FALSE

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);
}