[comp.windows.x] bug: XSetForeground vs mfb servers

mouse@lightning.mcrcim.mcgill.EDU (der Mouse) (03/06/91)

			  X Window System Bug Report
			    xbugs@expo.lcs.mit.edu
			 [copy sent to xpert as well]

VERSION:
    R4

CLIENT MACHINE and OPERATING SYSTEM:
    N/A

DISPLAY TYPE:
    Any using mfb

WINDOW MANAGER:
    N/A

AREA:
    server

SYNOPSIS:
    mfb CopyPlane doesn't truncate the foreground and background values
    in the GC to "the appropriate number of bits" as required by the
    protocol document.

DESCRIPTION:
    mfbCopyPlane tests the fgPixel and bgPixel values in the GC for
    equality with 1, 0, and one another.  Apparently (this is purely
    inference from the observed behavior), these values have not yet
    been "truncated to the appropriate number of bits".  For example,
    setting a foreground color of ~0L is not the same as setting a
    foreground color of 1L.

REPEAT BY:

    Run this program on (against :-) an mfb-based server.  Notice that
    when it does the AND operation, the outer edges remain striped and
    the inner bar becomes solid (white or black depending on your
    server).  Change the ~0L to 1L and notice that this time, the inner
    bar is the piece that stays striped.  (The latter is the correct
    behavior, but the presence of any difference is enough to indicate
    a bug.)

	#define X 100
	#define Y 100
	#define W 100
	#define H 100
	
	#include <stdio.h>
	#include <X11/X.h>
	#include <X11/Xlib.h>
	#include <X11/Xutil.h>
	#include <X11/Xatom.h>
	
	int argc;
	char **argv;
	
	Display *disp;
	Screen *scr;
	int width;
	int height;
	int depth;
	Window rootwin;
	
	Window win;
	GC wingc;
	Pixmap pic;
	Pixmap mask;
	GC maskgc;
	
	unsigned long int black;
	unsigned long int white;
	
	main(ac,av)
	int ac;
	char **av;
	{
	 int i;
	 unsigned long int attrmask;
	 unsigned long int gcvalmask;
	 XGCValues gcval;
	 XSetWindowAttributes attr;
	 XTextProperty wn_prop;
	 XTextProperty in_prop;
	 XSizeHints normal_hints;
	 XWMHints wm_hints;
	 XClassHint class_hints;
	 XEvent e;
	
	 /* boilerplate begins here */
	
	 disp = XOpenDisplay((char *)0);
	 scr = XDefaultScreenOfDisplay(disp);
	 depth = XDefaultDepthOfScreen(scr);
	 rootwin = XRootWindowOfScreen(scr);
	 white = XWhitePixelOfScreen(scr);
	 black = XBlackPixelOfScreen(scr);
	 attrmask = 0;
	 attr.background_pixel = black;
	 attrmask |= CWBackPixel;
	 attr.border_pixel = white;
	 attrmask |= CWBorderPixel;
	 attr.backing_store = NotUseful;
	 attrmask |= CWBackingStore;
	 attr.event_mask = ExposureMask | ButtonPressMask | ButtonMotionMask;
	 attrmask |= CWEventMask;
	 win = XCreateWindow(disp,rootwin,X,Y,W,H,1,depth,InputOutput,CopyFromParent,attrmask,&attr);
	 wn_prop.value = (unsigned char *) "bug-test";
	 wn_prop.encoding = XA_STRING;
	 wn_prop.format = 8;
	 wn_prop.nitems = strlen((char *)wn_prop.value);
	 in_prop.value = (unsigned char *) "bug-test";
	 in_prop.encoding = XA_STRING;
	 in_prop.format = 8;
	 in_prop.nitems = strlen((char *)in_prop.value);
	 normal_hints.flags = PPosition | PSize;
	 normal_hints.x = X;
	 normal_hints.y = Y;
	 normal_hints.width = W;
	 normal_hints.height = H;
	 wm_hints.flags = InputHint;
	 wm_hints.input = False;
	 class_hints.res_name = "bugtest";
	 class_hints.res_class = "BugTest";
	 XSetWMProperties(disp,win,&wn_prop,&in_prop,argv,argc,&normal_hints,&wm_hints,&class_hints);
	 XMapRaised(disp,win);
	
	 /* boilerplate ends. */
	
	 /* create a pixmap and a bitmap of appropriate size, and a GC for each */
	 wingc = XCreateGC(disp,win,0L,&gcval);
	 pic = XCreatePixmap(disp,rootwin,W,H,depth);
	 mask = XCreatePixmap(disp,rootwin,W,H,1);
	 maskgc = XCreateGC(disp,mask,0L,&gcval);
	 /* draw a pattern of diagonal lines in the pixmap */
	 XSetForeground(disp,wingc,black);
	 XSetFunction(disp,wingc,GXcopy);
	 XFillRectangle(disp,pic,wingc,0,0,W,H);
	 XSetForeground(disp,wingc,white);
	 for (i=0;i<W+H;i+=4) XDrawLine(disp,pic,wingc,i,0,0,i);
	 /* put a vertical bar of 1s in a field of 0s in the bitmap */
	 XSetForeground(disp,maskgc,0L);
	 XFillRectangle(disp,mask,maskgc,0,0,W,H);
	 XSetForeground(disp,maskgc,1L);
	 XFillRectangle(disp,mask,maskgc,W/3,0,W/3,H);
	 /* wait for an Expose from the window map above */
	 while (1)
	  { XNextEvent(disp,&e);
	    if (e.type == Expose) break;
	  }
	 /* wait for user confirmation before proceeding */
	 getchar();
	 /* display the pixmap in the window */
	 XCopyArea(disp,pic,win,wingc,0,0,W,H,0,0);
	 /* wait for confirmation */
	 XSync(disp,True);
	 getchar();
	 /* AND the pixmap with the bitmap.  on an mfb server, this actually
	    ands with the complement of the bitmap; changing ~0L to 1L works. */
	 XSetForeground(disp,wingc,~0L);
	 XSetBackground(disp,wingc,0L);
	 XSetFunction(disp,wingc,GXand);
	 XCopyPlane(disp,mask,pic,wingc,0,0,W,H,0,0,1L);
	 /* display the masked picture */
	 XCopyArea(disp,pic,win,wingc,0,0,W,H,0,0);
	 /* let the user look at it */
	 XSync(disp,True);
	 getchar();
	 exit(0);
	}

SAMPLE FIX:

    The following patch to mit/ddx/mfb/mfbbitblt.c works for me.

	*** mit/ddx/mfb/mfbbitblt.c=	Wed Mar  7 10:01:25 1990
	--- mit/ddx/mfb/mfbbitblt.c	Wed Mar  6 04:47:17 1991
	***************
	*** 1083,1094 ****
	      if (plane != 1)
	  	return NULL;
	  
	!     if ((pGC->fgPixel == 1) && (pGC->bgPixel == 0))
	      {
	  	prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
	  			 pGC, srcx, srcy, width, height, dstx, dsty);
	      }
	!     else if (pGC->fgPixel == pGC->bgPixel)
	      {
	  	alu = pGC->alu;
	  	pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
	--- 1083,1094 ----
	      if (plane != 1)
	  	return NULL;
	  
	!     if ((pGC->fgPixel & 1) && !(pGC->bgPixel & 1))
	      {
	  	prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
	  			 pGC, srcx, srcy, width, height, dstx, dsty);
	      }
	!     else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))
	      {
	  	alu = pGC->alu;
	  	pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
	
					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu