adam@UUNET.UU.NET (Adam de Boor) (05/03/89)
X Window System Bug Report xbugs@expo.lcs.mit.edu VERSION: R3 CLIENT MACHINE and OPERATING SYSTEM: Sun 3/50 running SunOS 3.5 (gcc version 1.34) DISPLAY: Sun BW2 WINDOW MANAGER: awm AREA: server/mfb SYNOPSIS: a CopyArea with function == GXxor doesn't work -- the combination of bits happens with the longword to the right of the dest, rather than with the destination itself. DESCRIPTION: I'm not sure if this is a compiler artifact or a real bug. However, running gremlin (available for X11 from ucbvax.berkeley.edu, if you're interested) reveals that a CopyArea from a pixmap to a window using XOR doesn't work right. The results are sometimes entertaining, however. In addition, given that many compilers today perform switches with calculated branches, and even if a compiler doesn't, a single switch on the function followed by unwound loops with the alu employed directly is bound to be faster than 6 compares per longword as currently used in the macros for mfbBitBlt, I have changed the longRop macro to switch on the alu. In places that don't employ putbitsrop, I've also changed DoRop to BltRop, which is the same except there's no compare against GXcopy at the front, since GXcopy is special-cased. I've no empirical data for these changes, just common sense. Anyway, with these changes, the problem with the XOR copy goes away. REPEAT BY: to be linked with wsimple.o from the xfd directory. Give -X to perform the copy in XOR mode. If you place the small window on top of another window with text in it, and the problem I had wasn't just a compiler artifact, pieces of the text will find their way into the right half of the window when you bring the beastie to the top. /* Copyright 1987, Massachusetts Institute of Technology */ /* * xfd: program to display a font for perusal by the user. * * Written by Mark Lillibridge * */ #include <X11/Xos.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <X11/cursorfont.h> #include <stdio.h> #define BUFFERSIZE 10 #define VERBOSE_LINES 4 /* Number of lines in verbose display */ #define GRAY_PAD 2 /* padding for gray mode */ /* Global variables */ int space_per_line; /* How much space to reserve per line */ int line_offset; /* Where to start writting (base line) */ int number_of_lines=1; /* number of lines in bottom area display */ int verbose = 0; /* verbose mode? */ int box_x = 0; /* The size of one box in grid */ int box_y = 0; int x_offset = 0; /* Point in box to display character from */ int y_offset = 0; int x_boxes = 0; /* Current size of window in # of boxes */ int y_boxes = 0; int bottom = 0; /* Size of grid in pixels */ int right = 0; int first_char = 0; /* Character # of first character displayed on the grid */ int gray = 0; /* use gray background ? */ GC body_gc, real_gc; /* Graphics contexts */ XFontStruct *real_font; /* The font we are to display */ /* Gray pattern for use as background */ #include "X11/bitmaps/light_gray" /* Include routines to handle parsing defaults */ #define TITLE_DEFAULT "xfd" /* Our name... */ #define DEFX_DEFAULT 300 /* Default window pop-up location */ #define DEFY_DEFAULT 300 #define RESIZE_X_INC 1 /* We will specify a resize inc later ... */ #define RESIZE_Y_INC 1 #define MIN_X_SIZE 1 /* Ditto for minimum window size */ #define MIN_Y_SIZE 1 #include "wsimple.h" /* * usage: routine to show usage then exit. */ usage() { fprintf(stderr, "%s: usage: %s %s [-v[erbose]] [-gray] [-start <char number>] -fn fontname\n", program_name, program_name, X_USAGE); exit(1); } /* * The main program: */ main(argc, argv) int argc; char **argv; { register int i; GC gc; XGCValues gc_init; XEvent event; char *fontname = NULL; /* Display default body font */ char buffer[BUFFERSIZE]; /* buffer for XLookupString */ Cursor cursor; Pixmap pix; int xor = 0; INIT_NAME; /* Handle command line arguments, open the display */ Get_X_Options(&argc, argv); for (i = 1; i < argc; i++) { if (!strcmp("-help", argv[i])) usage (); if (!strcmp("-X", argv[i])) { xor=1; continue; } if (!strcmp("-", argv[i])) continue; if (argv[i][0] == '-') usage(); if (fontname) usage(); fontname = argv[i]; } /* Resolve the X options */ Resolve_X_Options(); line_offset = 2 + body_font->ascent; space_per_line = body_font->descent + line_offset + 2; /* Get minimun perfered size */ Calc_Default_Size(); /* Create the window */ Create_Default_Window(); pix = XCreatePixmap(dpy, wind, 64, 32, 1); gc_init.foreground = BlackPixel(dpy, 0); gc_init.background = WhitePixel(dpy, 0); gc = XCreateGC(dpy, pix, GCForeground|GCBackground, &gc_init); XDrawLine(dpy, pix, gc, 0, 0, 64, 32); XFreeGC(dpy, gc); gc_init.function = xor ? GXxor : GXcopy; gc = XCreateGC(dpy, wind, GCFunction, &gc_init); /* Start main loop by selecting events then mapping window */ XSelectInput(dpy, wind, ExposureMask); XMapWindow(dpy, wind); /* Main event loop */ for (;;) { XNextEvent(dpy, &event); if (event.type == Expose && !event.xexpose.count) { XClearArea(dpy, wind, 0, 0, 0, 0, False); XCopyArea(dpy, pix, wind, DefaultGC(dpy, 0), 0, 0, 64, 32, 0, 0); XCopyArea(dpy, pix, wind, gc, 0, 0, 64, 32, 0, 0); } } } char short_format[] = "%d (0x%x)"; char line1_alt[] = "%s bounds:"; char line1_format[] = "character # = %d (0x%x):"; char line2_format[] = "left bearing = %d, right bearing = %d"; char line3_format[] = "ascent = %d, descent = %d"; char line4_format[] = "width = %d"; char buf[80*2]; /* * Calc_Default_Size: This routine calculates the size of a box in the grid * and where to write a character from so that every character will fit * in a box. The size of an ideal window (16 boxes by 16 boxes with room * for the bottom text) is then calculated. */ Calc_Default_Size() { size_hints.min_width = size_hints.max_width = 64; size_hints.min_height = size_hints.max_height = 32; size_hints.flags = USSize|USPosition; size_hints.height = 32; size_hints.width = 64; size_hints.x = size_hints.y = 0; } char s[4] = { 0, 0, 0, 0 }; SAMPLE FIX: *** /tmp/,RCSt1a20453 Tue May 2 15:10:13 1989 --- mfbbitblt.c Tue May 2 14:59:29 1989 *************** *** 243,273 **** } \ } ! #define longRop(alu,from,to,count) \ { \ switch (count & 7) { \ ! case 0: *to = DoRop (alu, *from++, *to); to++; \ ! case 7: *to = DoRop (alu, *from++, *to); to++; \ ! case 6: *to = DoRop (alu, *from++, *to); to++; \ ! case 5: *to = DoRop (alu, *from++, *to); to++; \ ! case 4: *to = DoRop (alu, *from++, *to); to++; \ ! case 3: *to = DoRop (alu, *from++, *to); to++; \ ! case 2: *to = DoRop (alu, *from++, *to); to++; \ ! case 1: *to = DoRop (alu, *from++, *to); to++; \ } \ ! while ((count -= 8) > 0) { \ ! *to = DoRop (alu, *from++, *to); to++; \ ! *to = DoRop (alu, *from++, *to); to++; \ ! *to = DoRop (alu, *from++, *to); to++; \ ! *to = DoRop (alu, *from++, *to); to++; \ ! *to = DoRop (alu, *from++, *to); to++; \ ! *to = DoRop (alu, *from++, *to); to++; \ ! *to = DoRop (alu, *from++, *to); to++; \ ! *to = DoRop (alu, *from++, *to); to++; \ ! } \ } #define getunalignedword(psrc, x, dst) \ { \ int m; \ --- 243,295 ---- } \ } ! #define longDoRop(fn,from,to,count) \ { \ switch (count & 7) { \ ! case 0: *to = fn(*from++, *to); to++;\ ! case 7: *to = fn(*from++, *to); to++;\ ! case 6: *to = fn(*from++, *to); to++;\ ! case 5: *to = fn(*from++, *to); to++;\ ! case 4: *to = fn(*from++, *to); to++;\ ! case 3: *to = fn(*from++, *to); to++;\ ! case 2: *to = fn(*from++, *to); to++;\ ! case 1: *to = fn(*from++, *to); to++;\ } \ ! while ((count -= 8) > 0) {\ ! *to = fn(*from++, *to); to++;\ ! *to = fn(*from++, *to); to++;\ ! *to = fn(*from++, *to); to++;\ ! *to = fn(*from++, *to); to++;\ ! *to = fn(*from++, *to); to++;\ ! *to = fn(*from++, *to); to++;\ ! *to = fn(*from++, *to); to++;\ ! *to = fn(*from++, *to); to++;\ ! }\ } + #define longRop(alu,from,to,count) \ + {\ + switch(alu) {\ + case GXclear: longDoRop(fnCLEAR,from,to,count); break;\ + case GXand: longDoRop(fnAND,from,to,count); break;\ + case GXandReverse: longDoRop(fnANDREVERSE,from,to,count); break;\ + case GXcopy: /* Never happens */ break;\ + case GXandInverted: longDoRop(fnANDINVERTED,from,to,count); break;\ + case GXnoop: from += count; to += count; break;\ + case GXxor: longDoRop(fnXOR,from,to,count); break;\ + case GXor: longDoRop(fnOR,from,to,count); break;\ + case GXnor: longDoRop(fnNOR,from,to,count); break;\ + case GXequiv: longDoRop(fnEQUIV,from,to,count); break;\ + case GXinvert: longDoRop(fnINVERT,from,to,count); break;\ + case GXorReverse: longDoRop(fnORREVERSE,from,to,count); break;\ + case GXcopyInverted: longDoRop(fnCOPYINVERTED,from,to,count); break;\ + case GXorInverted: longDoRop(fnORINVERTED,from,to,count); break;\ + case GXnand: longDoRop(fnNAND,from,to,count); break;\ + case GXset: longDoRop(fnSET,from,to,count); break;\ + }\ + } + #define getunalignedword(psrc, x, dst) \ { \ int m; \ *************** *** 276,281 **** --- 298,323 ---- (SCRRIGHT(*((psrc)+1), m) & starttab[m]); \ } + /* Like DoRop, but no compare for GXcopy, since this is never used for + * GXcopy. + */ + #define BltRop(alu, src, dst) \ + ( (((alu) >= GXnor) ? \ + (((alu) >= GXcopyInverted) ? \ + (((alu) >= GXnand) ? \ + (((alu) == GXnand) ? ~((src) & (dst)) : ~0) : \ + (((alu) == GXcopyInverted) ? ~(src) : (~(src) | (dst)))) : \ + (((alu) >= GXinvert) ? \ + (((alu) == GXinvert) ? ~(dst) : ((src) | ~(dst))) : \ + (((alu) == GXnor) ? ~((src) | (dst)) : (~(src) ^ (dst)))) ) : \ + (((alu) >= GXandInverted) ? \ + (((alu) >= GXxor) ? \ + (((alu) == GXxor) ? ((src) ^ (dst)) : ((src) | (dst))) : \ + (((alu) == GXnoop) ? (dst) : (~(src) & (dst)))) : \ + (((alu) >= GXandReverse) ? \ + (((alu) == GXandReverse) ? ((src) & ~(dst)) : (src)) : \ + (((alu) == GXand) ? ((src) & (dst)) : 0))) ) ) + mfbDoBitblt(pSrcDrawable, pDstDrawable, alu, prgnDst, pptSrc) DrawablePtr pSrcDrawable; DrawablePtr pDstDrawable; *************** *** 509,515 **** else nend = 0; ! xoffSrc = ((pptSrc->x & 0x1f) + nstart) & 0x1f; srcStartOver = ((pptSrc->x & 0x1f) + nstart) > 31; if (xdir == 1) /* move left to right */ --- 551,557 ---- else nend = 0; ! xoffSrc = (pptSrc->x + nstart) & 0x1f; srcStartOver = ((pptSrc->x & 0x1f) + nstart) > 31; if (xdir == 1) /* move left to right */ *************** *** 657,663 **** else nend = 0; ! xoffSrc = ((pptSrc->x & 0x1f) + nstart) & 0x1f; srcStartOver = ((pptSrc->x & 0x1f) + nstart) > 31; if (xdir == 1) /* move left to right */ --- 699,705 ---- else nend = 0; ! xoffSrc = (pptSrc->x + nstart) & 0x1f; srcStartOver = ((pptSrc->x & 0x1f) + nstart) > 31; if (xdir == 1) /* move left to right */ *************** *** 694,701 **** while (--nl) { getunalignedword (psrc, xoffSrc, tmpSrc) ! *pdst++ = DoRop (alu, tmpSrc, *pdst); ! psrc++; } } --- 736,743 ---- while (--nl) { getunalignedword (psrc, xoffSrc, tmpSrc) ! *pdst = BltRop (alu, tmpSrc, *pdst); ! psrc++, pdst++; } }