[comp.windows.x] XDrawImageString bug

garya@Solbourne.COM (Gary Aitken) (08/04/89)

XDrawImageString has a bug in it for fonts like .../75dpi/courR14.snf which have
pixels at the top of the font for things like umlauts.  The font height,
as measured by maxbounds ascent+descent, is 16.  A font property, PIXEL_SIZE,
is 14.  XDrawImageString does not draw the top two pixels in some cases.
I'm guessing it's using the property somehow to determine a clip region?

Here's a demo:
Fails on X11R3 and the pre release R4 Xlib

==================================  cut here  ========================================
#include <X11/Xlib.h>
 main(argc,argv)
		int		argc ;
		char		**argv ;
 {
		Display		*dpy ;
		Window		rt,win1,win2 ;
		int		x,y ;
		char		*fnp ;		/* font name */
		XFontStruct	*fp ;		/* ptr to X font structure for new font */
		XGCValues	tempgc ;	/* temporary X graphics context for creating GC's */
		GC		gc1,gc2 ;
	unsigned long		mask ;
	static	char		string[] = "H\305" ;	/* H, A with a circle over it in courR14.snf */
		XEvent		event ;

	dpy = XOpenDisplay("unix:0.0") ;
	XSynchronize(dpy,1) ;
	rt = XDefaultRootWindow(dpy) ;
	fp = XLoadQueryFont(dpy,"-adobe-courier-medium-r-normal--14-140-75-75-m-90-iso8859-1") ;
	tempgc.graphics_exposures = False ;
	tempgc.foreground = XBlackPixel(dpy,0) ;
	tempgc.background = XWhitePixel(dpy,0) ;
	tempgc.font = fp->fid ;
	mask = GCForeground | GCBackground | GCGraphicsExposures | GCFont ;
	gc1 = XCreateGC(dpy,rt,mask,&tempgc) ;
	win1 = XCreateSimpleWindow(dpy,rt,100,100,300,200,4,tempgc.foreground,tempgc.background) ;
	win2 = XCreateSimpleWindow(dpy,rt,200,100,300,200,4,tempgc.foreground,tempgc.foreground) ;
	XSelectInput(dpy,win1,StructureNotifyMask) ;
	XSelectInput(dpy,win2,StructureNotifyMask) ;
	XMapWindow(dpy,win1) ;
	XMapWindow(dpy,win2) ;
	while (!XCheckTypedWindowEvent(dpy,win1,MapNotify,&event))
		 ;
	while (!XCheckTypedWindowEvent(dpy,win2,MapNotify,&event))
		 ;
	tempgc.foreground = XWhitePixel(dpy,0) ;
	tempgc.background = XBlackPixel(dpy,0) ;
	gc2 = XCreateGC(dpy,rt,mask,&tempgc) ;

	XDrawImageString(dpy,win1,gc1,50,50,string,2) ;
	XDrawImageString(dpy,win1,gc2,100,50,string,2) ;
	XDrawImageString(dpy,win2,gc1,50,50,string,2) ;
	XDrawImageString(dpy,win2,gc2,100,50,string,2) ;
	
	while (1) ;
 }
-- 
Gary Aitken

Solbourne Computer Inc.    ARPA: garya@Solbourne.COM
Longmont, CO               UUCP: !{boulder,nbires,sun}!stan!garya

rws@EXPO.LCS.MIT.EDU (08/04/89)

    Fails on X11R3 and the pre release R4 Xlib

Please refrain from reporting suspected problems with pre-release software on
public lists.  I suspect your company asks the same thing of its customers.

rws@EXPO.LCS.MIT.EDU (08/04/89)

    Here's a demo:
    Fails on X11R3 and the pre release R4 Xlib

Your program produces correct output on a Sun R3 server, and on a server
in our current development system.  Either your server ddx is broken, or
you misunderstand what bits should be drawn.  The "background" fill is only
done based on font-ascent and font-descent, not based on maxbounds.  For the
font in question, font-ascent is defined as 11, even though some glyphs
extend higher than that.  If you believe the Courier fonts should be
altered to make them more directly useful for image text, you can plead
your case to Adobe and Digital, from whence the fonts came.

wdc@ATHENA.MIT.EDU (Bill Cattey) (08/05/89)

I think more clarification is needed with XDrawImageString.

I have had the advantage of being able to pick the brains of Ralph Swick
who worked with me for a long time before I got the underlying concept
of XDrawImageString.  I _think_ I have it right now.  Ralph, correct me
if I still mis-understand.  Here goes:

Whereas XDrawString and XDrawText are for applications that allow text
drawing to be totally unconstrained, XDrawImageString is for those
applications where the drawing is "well-behaved".

The definition of well-behaved is that all characters drawn have
vertical bounds within the bounding box of the font, and no characters
have a negative left bearing.  This enables simplifying assumptions to
be made on redisplay:  Since the bounding box constrains the height and
descent of characters, line spacing is done by looking at the bounding
box of the font, and the application never has to worry about redrawing
text above or below the current line.  Characters need not be erased,
and redrawn, they need only be overwritten.  Simple bit blit'ing of
rectangular regions move the lines and other characters out of the way.

As soon as you permit the more general case, of characters that can
bleed into previous characters, and lines above and below the current
line, you must write a redisplay that knows what characters it drew,
knows to erase and redraw them, and to repair any damage on lines above,
below, or to the left of what is drawn.

XDrawImageString is, NOT for the general case.  When you look at what
has to be done for such simple drawing, you understand that the
background must be drawn in the constrained rectangle, and that fonts
that are not "well-behaved" simply can't be used by applications making
the simplifying assumptions.

To summarize:  you can't write a redisplay algorithm for text that could
bleed into nearby bounding boxes without performing erase and redraw
operations.  A redisply that just pours rectangles of characters and
their background onto the screen must be well-behaved.

-wdc