> Could you, please, post a simple code example that displays
> the problem ? This would be very helpful.
> Also, specify whether you are on snow leopard or not, because
> there are small peculiarities of snow leopard on this topic.

Sure, code is at the bottom.  This is all on 10.5.8.

Now, when compiled on 1.1.9, this shows a rect with a one pixel red
line, a rect with a two pixel red line, and the third rect is not
drawn at all.  It prints:
clip rect: 10 10 x 1 20
clip rect: 10 50 x 2 20

So that all makes sense.  When compiled on fltk-1.3.x-r7008, the first
rect has no red line (so a clip of width 1 is mistaken as a complete
clip), the second has two pixels (so that's correct), and the third
rect isn't clipped, and shows up (so a clip of width 0 does nothing).
And it prints:
clip rect: 0 0 x 0 0
clip rect: 10 50 x 1 19

So it looks like for some reason OS X clip functions are clipping one
pixel *wider* than the given rect, so fltk subtracts 1 to compensate.
Except OS X doesn't add 1 to 0, so when you pass 1, fltk makes it zero
and OS X goes ahead and clips it all... even though CGRectIsEmpty is
false for this zero width rect.  Then if you pass 0, it becomes -1,
which is finally considered "empty", and so MacRectRegionIntersect
ignores it entirely.

And... fltk doesn't add 1 back on when it returns it from fl_clip_box,
so using this to add a new clip successively shaves off pixels.

As far as the solution, I haven't looked into that much yet, I don't
really know anything about OS X graphics programming.  Obviously the
best thing would be to figure out what's up with this +1 behaviour and
turn it off.  The docs for CGContextClipToRects [1] says only that
"The locations and dimensions of the rectangles are specified in the
user space coordinate system."  I don't know what user space
coordinate systems are on OS X, but maybe there's something wrong
there.  Otherwise, we can add specific hacks for ==0, ==1, and >1, but
I wouldn't have a lot of trust that it will continue to work without
understanding the underlying cause.

BTW, fl_rect.cxx:fl_push_clip is a real mess of #ifdefs.  In fact the
whole file is like that.  Isn't the idea to separate platform specific
files?  If I made a patch that separated it out, at the cost of some
code duplication, would it be accepted?  And this stuff about
__APPLE_QUARTZ__ and __APPLE_COCOA__ overlapping is confusing,
shouldn't they be exclusive?

Also, on a similar subject, wouldn't it be better to conditionally
compile Fl_cocoa.mm and fl_color_mac.cxx etc. from the build system
rather than using #include?  It's confusing.

Also also while I'm in a cleanup mood... how about someday removing
reference output params like fl_clip_box?  Ref args should be const,
output args should be pointers.  Adding a new function and deprecating
the old one is ok too, as long as we eventually get rid of deprecated
stuff (fl_clip() is still around...).

[1] 
http://developer.apple.com/mac/library/DOCUMENTATION/GraphicsImaging/Reference/CGContext/Reference/reference.html#//apple_ref/c/func/CGContextClipToRects


#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>

struct Rect {
    Rect(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {}
    int x, y, w, h;
};

static void
print_clip()
{
    Rect r(0, 0, 0, 0);
    fl_clip_box(0, 0, 9999, 9999, r.x, r.y, r.w, r.h);
    printf("clip rect: %d %d x %d %d\n", r.x, r.y, r.w, r.h);
}

class Box : public Fl_Box {
public:
    Box(int x, int y, int w, int h) : Fl_Box(x, y, w, h) {
        box(FL_THIN_DOWN_BOX);
        color(FL_WHITE);
    }
    void draw() {
        Fl_Box::draw();
        fl_push_clip(0, 0, w(), h());

        fl_color(FL_BLACK);
        fl_rectf(10, 10, 50, 20);

        fl_push_clip(10, 10, 1, 20);
        print_clip();
        fl_color(FL_RED);
        fl_rectf(0, 0, 30, 100);
        fl_pop_clip();

        fl_color(FL_BLACK);
        fl_rectf(10, 50, 50, 20);
        fl_push_clip(10, 50, 2, 20);
        print_clip();
        fl_color(FL_RED);
        fl_rectf(0, 50, 30, 100);
        fl_pop_clip();

        fl_push_clip(10, 100, 0, 20);
        fl_rectf(10, 100, 50, 20);
        fl_pop_clip();

        fl_pop_clip();
    }
};

int
main(int argc, char **argv)
{
    Fl_Double_Window win(100, 100, 200, 200);
    Box box(0, 0, 200, 200);
    win.show(argc, argv);
    Fl::run();
    return 0;
}

_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev

Reply via email to