[comp.windows.x] Purdue+ speedups bug

jdi@sparky.UUCP (John Irwin) (01/21/89)

Your message:

    Setup: R3 w/ 4 patches + Purdue + PurduePlus on a sun3/260 OS3.4
	   and sun3/160 OS4.0, compiled with gcc.

    Summary: Bug in clipped text output using PurduePlus speedups

This bug occurs when text (of fixed width <= 8, thus the Purdue+ text speedup
is being used) is output to a window that has either a gcontext clip mask or 
a server clip mask (because of occluding windows).  The manifestation is that
when a string is drawn that spans a vertical clipping line, a vertical strip of
a couple pixels is left out of the characters that span the boundary between
the clipped and non-clipped regions.

I guess it's an indication of how few people are using the Purdue+ speedups
that we were one of the first to notice...

	-- John, jdi%franz.uucp@ucbarpa.berkeley.edu

martin@CITI.UMICH.EDU (01/23/89)

>    Summary: Bug in clipped text output using PurduePlus speedups
>
>This bug occurs when text (of fixed width <= 8, thus the Purdue+ text speedup
>is being used) is output to a window that has either a gcontext clip mask or
>a server clip mask (because of occluding windows).  The manifestation is that
>when a string is drawn that spans a vertical clipping line,a vertical strip of
>a couple pixels is left out of the characters that span the boundary between
>the clipped and non-clipped regions.


I am glad that you have found this bug.  Please mail me and spaf a source file
which sets the proper GC stuff and font junk.  

Now for an explanation.  Since the text is clipped, I am sure that the bug is
not in my purdue+ speedup.  Examine the mfbtegblt.c file:

    switch ((*pGC->pScreen->RectIn)(
                ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip, &bbox))
    {
      case rgnOUT:
	break;
      case rgnPART:
	/* this is the WRONG thing to do, but it works.
	   calling the non-terminal text is easy, but slow, given
	   what we know about the font.

	   the right thing to do is something like:
	    for each clip rectangle
		compute at which row the glyph starts to be in it,
		   and at which row the glyph ceases to be in it
		compute which is the first glyph inside the left
		    edge, and the last one inside the right edge
		draw a fractional first glyph, using only
		    the rows we know are in
		draw all the whole glyphs, using the appropriate rows
		draw any pieces of the last glyph, using the right rows

	   this way, the code would take advantage of knowing that
	   all glyphs are the same height and don't overlap.

	   one day...
	*/
	CLIPTETEXT(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
	break;
      case rgnIN:
	...  (run purdue+ mods)

The call to CLIPTETEXT (one of mfbImageGlyphBltWhite, mfbImageGlyphBltBlack)
is made in the case you speak of.

Now...  Here is an excerpt from ./contrib/server/speedups/donahue/README

>The gcc-compiled version has one small bug during clipping text to the
>right-hand edge of an overlapping window.  The bug is somewhere in
>mfbimggblt.c, but I have not yet found it.

And later Terry Donhue sent me a fix for this bug.  I have just seen the
effects of this bug, and am going to recompile the server with the following
fix.  Iff the fix fixes the bug I saw, Spaf and I may include this fix in the
next (very soon) release of Purdue2.0 .


The fix.

*** ./ddx/mfb.old/mfbimggblt.c	Tue Sep  8 10:04:17 1987
--- ./ddx/mfb/mfbimggblt.c	Tue Aug 30 20:51:40 1988
***************
*** 277,282 ****
--- 277,283 ----
  	int glyphRow;		/* first row of glyph not wholly
  				   clipped out */
  	int glyphCol;		/* leftmost visible column of glyph */
+ 	int getWidth;		/* bits to get from glyph */
  
  	if(!(ppos = (TEXTPOS *)ALLOCATE_LOCAL(nglyph * sizeof(TEXTPOS))))
  	    return;
***************
*** 375,380 ****
--- 376,382 ----
  
  		glyphCol = (leftEdge - ppos[i].xpos) -
  			   (pci->metrics.leftSideBearing);
+ 		getWidth = w + glyphCol;
  		xoff = xchar + (leftEdge - ppos[i].xpos);
  		if (xoff > 31)
  		{
***************
*** 392,398 ****
  		    maskpartialbits(xoff, w, startmask);
  		    while (h--)
  		    {
! 			getshiftedleftbits(pglyph, glyphCol, w, tmpSrc);
  			*pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
  			pglyph += widthGlyph;
  			pdst += widthDst;
--- 394,400 ----
  		    maskpartialbits(xoff, w, startmask);
  		    while (h--)
  		    {
! 			getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
  			*pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
  			pglyph += widthGlyph;
  			pdst += widthDst;
***************
*** 404,410 ****
  		    nFirst = 32 - xoff;
  		    while (h--)
  		    {
! 			getshiftedleftbits(pglyph, glyphCol, w, tmpSrc);
  			*pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
  			*(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask);
  			pglyph += widthGlyph;
--- 406,412 ----
  		    nFirst = 32 - xoff;
  		    while (h--)
  		    {
! 			getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
  			*pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
  			*(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask);
  			pglyph += widthGlyph;