[ltp] XFree86 fill problems

Carl Nygard linux-thinkpad@linux-thinkpad.org
Sun, 07 Mar 2004 12:20:23 -0500


--=-gx1elIHxES/igC8IIOmK
Content-Type: text/plain
Content-Transfer-Encoding: 7bit


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

--=-gx1elIHxES/igC8IIOmK
Content-Disposition: attachment; filename=test6.c
Content-Type: text/x-c; name=test6.c; charset=
Content-Transfer-Encoding: 7bit

//**********************************************************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;
}

--=-gx1elIHxES/igC8IIOmK--