drawRect and component transforms in windows - bug?


#1
const int elementSpacing = 3; 
const int elementSize = 2; 

        for (int i = 0; i < elements; ++i)
        {
            Rectangle<int>r (mx, i * elementSpacing, mw, elementSize);
            g.setColour (color[i]);
            g.fillRect (r);
        }

This code produces the following incorrect output (the meter) when scaling is applied to a parent component:

WIth a 1.0, 1.0 scaling ratio it looks correct.

If I change the Rectangle<int> to a Rectangle<float> the correct output appears at all scalings, e.g. 

This affects my build on Windows 7, but not my MacOS build.  I've not tested with other versions of windows, nor dug into the root cause.  But I don't think it's correct behaviour?

 

 

 


#2

Does it work if you draw a rectangle with floats instead of ints?


#3

Yep.  All fine with a float...that's what i was trying to say! :)  The bottom image is it drawing, scaled, with floats.


#4

Sorry Jim, failed to read your post properly!

There is actually a bit of a difference between the way it handles int and float rectangles. If everything was drawn with float precision then adjacent large blocks of colour (e.g. the background colour of adjacent components) get little anti-aliasing artifacts between them when the GUI is scaled to tricky scale factors. To avoid that, I opted to use snapping when scaling the integer ones, which solved a lot of painting problems. I think this is only the case in the software renderer, though - somehow OSX seems to have a more cunning algorithm that solves the original problem, though I can't figure out what it is.


#5

Awkward ;)  I'll stick to using the floats for this kind of thing then!  

 


#6

Yeah, it's a fundamental problem that if you draw two exactly-adjacent rectangles of the same colour, e.g. (0, 0, 100.5, 100) and (100.5, 0, 100, 100) then with normal anti-aliasing you'll have a visible artifact at the join.

So where people have done totally reasonable paint methods that fill their entire contents with adjacent-but-not-overlapping rectangles, then this goes wrong on scaled displays. Hence my hack. As far as I can tell CoreGraphics does something along the same lines, or maybe messes with the gamma or something.. but not sure exactly what their trick is.