I've got a Thinkpad T40 running Fedora Core 1 (XFree86-4.3.0-42) and the VESA framebuffer (not sure that matters). When I run the attached simple program, I get problems with the fills when using Stipples. The whole object in question isn't filled properly if it hangs off the left edge of the window.
Running this on my RH9 box (XFree86-4.3.0-2) works fine. When run on RH9 but displaying on my laptop, it's broke. I don't know if this is an XF86 bug, a packaging bug, or what else? See attached code. I've got pictures, but they're about 700K combined, I didn't want to spam the list(s) unless someone wants to see my output. The odd thing I noticed just now is that if I move the window, the fill pattern gets better, as if the root window dimensions are somehow involved in whether the fill is processed properly. If I move the window far enough toward the center of the screen so that the objects would fit on the root window (ignoring the app window boundaries), then things work fine. It also displays fine if I use solid fills. Even odder is that it works if there is another window on top. I discovered this with the Gimp acquire tear-off menu, but it works as well with gnome-terminal. Can someone enlighten me? This seems to be a serious issue. Regards, Carl
//**********************************************************BEGINDOC // // Copyright (c) 1998, 1999 Spatial Software Solutions, Inc. // // Library: OutputDevice // // Class: X11OutputDevice // Test program for X11OutputDevice // // $RCSfile: test5.cxx,v $ $Revision: 1.1.2.1 $ $Date: 2004/03/05 21:41:13 $ // //************************************************************ENDDOC //////////////////////////////////////////////////////////////////// // Flags //////////////////////////////////////////////////////////////////// // Includes #include <Xm/Form.h> #include <Xm/Frame.h> #include <Xm/DrawingA.h> #include <Xm/PushB.h> #include <Xm/Label.h> #include <Xm/PushBG.h> #include <math.h> #include <unistd.h> #include <sys/times.h> #include <stdlib.h> //////////////////////////////////////////////////////////////////// // Imports //////////////////////////////////////////////////////////////////// // Exports //////////////////////////////////////////////////////////////////// // Constants //////////////////////////////////////////////////////////////////// // Local Classes //////////////////////////////////////////////////////////////////// // Local Variables Widget Ggraf; Display* dpy = NULL; Window win; GC gc; //////////////////////////////////////////////////////////////////// // Forward Declarators //////////////////////////////////////////////////////////////////// // Static Class Members //////////////////////////////////////////////////////////////////// // Code GC CreateGC(Display* dsp, Window win) { int screen = DefaultScreen(dsp); XGCValues values; values.function = GXcopy; values.plane_mask = AllPlanes; values.line_width = 0; values.line_style = LineSolid; values.cap_style = CapButt; values.fill_style = FillSolid; values.join_style = JoinBevel; values.subwindow_mode = ClipByChildren; values.graphics_exposures = False; values.clip_x_origin = 0; values.clip_y_origin = 0; values.clip_mask = None; values.foreground = WhitePixel(dsp, screen); values.background = BlackPixel(dsp, screen); values.join_style = JoinRound; GC gc = XCreateGC(dsp, win, GCFunction|GCPlaneMask|GCLineWidth| GCLineStyle|GCCapStyle| GCFillStyle|GCJoinStyle|GCForeground| GCBackground|GCSubwindowMode| GCGraphicsExposures|GCClipXOrigin| GCClipYOrigin|GCClipMask, &values); if (gc == None) { printf("Unable to get GC\n"); exit(-1); } return gc; } void SetFillStipple(Display* dsp, Window win, GC gc) { unsigned char opaque_bits[] = { 0x55, 0x50, 0xa0, 0xaa, 0x50, 0x55, 0xaa, 0xa0, 0x55, 0x50, 0xaa, 0xa0, 0x55, 0x50, 0xa0, 0xaa, 0x50, 0x55, 0xaa, 0xa0, 0x55, 0x50, 0xaa, 0xa0, 0x55, 0x50, 0xa0, 0xaa, 0x50, 0x55, 0xaa, 0xaa}; Pixmap fillPix = XCreatePixmapFromBitmapData(dsp, win, (char *)opaque_bits, 16, 16, 1, 0, 1); printf("Setting fill pixmap\n"); XSetFillStyle(dsp, gc, FillStippled); XSetStipple(dsp, gc, fillPix); XFreePixmap(dsp, fillPix); } void Clear(Display* dsp, Window win, GC gc) { #if CLEAR printf("Clearing Window\n"); XClearWindow(dsp, win); #else XSetFillStyle(dsp, gc, FillSolid); XSetForeground(dsp, gc, 0xffffff); XFillRectangle(dsp, win, gc, 0, 0, 800, 800); #endif } void DrawRectangle(Display* dsp, Window win, GC gc) { printf("Set foreground\n"); XSetForeground(dsp, gc, 0x00ff00); XSetBackground(dsp, gc, 0xff0000); printf("Allocating fill pixmap2\n"); SetFillStipple(dsp, win, gc); // XSetFillRule(dsp,gc, WindingRule); // Makes no difference printf("Drawing rectangle\n"); XFillRectangle(dsp, win, gc, -100, 200, 200, 100); printf("Flushing\n"); XFlush(dsp); printf("Done drawing\n"); } void DrawPoly(Display* dsp, Window win, GC gc, float xfactor, float yfactor, int xoff, int yoff) { const int PTS = 72; XPoint pts[PTS]; int i = 0; double angle; for(angle = 0.0; angle < 360.0 && i < 72; angle += 5, ++i){ pts[i].x = (short)(cos(M_PI * angle/180.0) * xfactor); pts[i].y = (short)(sin(M_PI * angle/180.0) * yfactor); } XPoint* it; for(it = pts; it != pts+PTS; ++it){ it->y += yoff; it->x += xoff; } printf("Allocating fill pixmap2\n"); SetFillStipple(dsp, win, gc); XSetFillRule(dsp,gc, EvenOddRule/*WindingRule*/); /*Makes no difference*/ XSetForeground(dsp, gc, 0x00f800); XSetBackground(dsp, gc, 0x000000); XFillPolygon(dpy, win, gc, pts, PTS, Complex, CoordModeOrigin); printf("Flushing\n"); XFlush(dsp); } void GbuttonPressed(Widget w, XtPointer client_data, XtPointer call_data) { Clear(dpy, win, gc); DrawRectangle(dpy, win, gc); } void Gbutton3Pressed(Widget w, XtPointer client_data, XtPointer call_data) { Clear(dpy, win, gc); DrawPoly(dpy, win, gc, 100, 100, 800, 800); DrawPoly(dpy, win, gc, 200, 50, 800, 800); DrawPoly(dpy, win, gc, 50, 200, 800, 800); } void Gbutton4Pressed(Widget w, XtPointer client_data, XtPointer call_data) { Clear(dpy, win, gc); DrawPoly(dpy, win, gc, 100, 100, 200, 200); DrawPoly(dpy, win, gc, 100, 50, 400, 400); DrawPoly(dpy, win, gc, 100, 200, 600, 600); } void Gbutton2Pressed(Widget w, XtPointer client_data, XtPointer call_data) { Clear(dpy, win, gc); DrawPoly(dpy, win, gc, 100, 100, 0, 200); DrawPoly(dpy, win, gc, 100, 50, 0, 400); DrawPoly(dpy, win, gc, 100, 50, 20, 500); DrawPoly(dpy, win, gc, 100, 50, 40, 600); DrawPoly(dpy, win, gc, 100, 50, 60, 700); // DrawPoly(dpy, win, gc, 100, 200, 0, 600); } int main(int argc, char **argv) { XtAppContext app_context; Widget GtopLevel = XtVaAppInitialize(&app_context, "X11ODTest", NULL,0, &argc,argv, NULL, NULL); Widget Gwindow = XtVaCreateManagedWidget( "Gwindow", xmFormWidgetClass, GtopLevel, NULL); Widget Gbutton = XtVaCreateManagedWidget( "Gbutton", xmPushButtonGadgetClass, Gwindow, XmNtopAttachment,XmATTACH_FORM, XmNleftAttachment,XmATTACH_FORM, NULL); Widget GButton2 = XtVaCreateManagedWidget( "GButton2", xmPushButtonGadgetClass, Gwindow, XmNtopAttachment,XmATTACH_FORM, XmNleftAttachment,XmATTACH_WIDGET, XmNleftWidget, Gbutton, NULL); Widget GButton3 = XtVaCreateManagedWidget( "GButton3", xmPushButtonGadgetClass, Gwindow, XmNtopAttachment,XmATTACH_FORM, XmNleftAttachment,XmATTACH_WIDGET, XmNleftWidget, GButton2, NULL); Widget GButton4 = XtVaCreateManagedWidget( "GButton4", xmPushButtonGadgetClass, Gwindow, XmNtopAttachment,XmATTACH_FORM, XmNleftAttachment,XmATTACH_WIDGET, XmNleftWidget, GButton3, NULL); Ggraf = XtVaCreateManagedWidget( "Ggraf", xmDrawingAreaWidgetClass, Gwindow, XmNtopAttachment,XmATTACH_WIDGET, XmNtopWidget, Gbutton, XmNleftAttachment,XmATTACH_FORM, XmNrightAttachment,XmATTACH_FORM, XmNbottomAttachment,XmATTACH_FORM, XmNwidth,800, XmNheight,800, NULL); XtRealizeWidget(GtopLevel); dpy = XtDisplay(Ggraf); win = XtWindow(Ggraf); gc = CreateGC(dpy, win); XtAddCallback(Gbutton,XmNactivateCallback,GbuttonPressed, (XtPointer) NULL); XtAddCallback(GButton2,XmNactivateCallback,Gbutton2Pressed, (XtPointer) NULL); XtAddCallback(GButton3,XmNactivateCallback,Gbutton3Pressed, (XtPointer) NULL); XtAddCallback(GButton4,XmNactivateCallback,Gbutton4Pressed, (XtPointer) NULL); XtAppMainLoop(app_context); return 1; }