It’s set to false. We don’t use setPaintingisUnclipped anywhere in our code. This component is part of a scaled hierarchy. So the main component gets scaled to the window size. The whole UI gets bigger/smaller. This child component is setOpaque(true), and a fillAll should fill every pixel. But it doesn’t.
If it were unclipped, the grey fill would have filled the whole screen. Which is what I meant by fillAll() technically painting outside the bounds - it’s only safe to call fillAll() when the component’s painting is clipped otherwise you will end up painting outside the bounds.
I guess the problem is that fillAll is based on fillRect(Rectangle), which has a bug since ages, it paints based on pixel boundaries, even when used in scaled context. The behaviour is different on windows vs Mac.
Maybe it would be time to solve the problem and align the behaviour of the GraphicContexts to each other.
PS: workaround, use g.fillRect (getLocalBounds().toFloat());
It’s not a bug, or anything specific to juce, it’s just an artefact of how anti-aliasing is done.
If your rectangle isn’t perfectly pixel-aligned (and you can’t really expect things to be pixel aligned very often in these days of odd scale factors and high-res displays), then its edges will be drawn as a semi-transparent line based on its coverage.
So if those pixels have e.g. 50% coverage, if you draw them first in red and then in grey, they’ll still have a red tinge showing through.
That’s just the nature of coverage-based AA systems. It also means that if you draw two rectangles whose edges line up perfectly on a non-pixel boundary, you’ll probably get a faint line between them.
The only way to get a perfect result would be to use a totally different approach. One would be to render the entire window with no anti-aliasing into a scaled-up canvas, then down-sample it to the display at the end. Or instead of filling shapes immediately, you’d queue them and simplify/merge them before actually doing any drawing.
So “fillAll” is NOT meant to fill the entire component? Should the documentation be updated?
We can’t rely on “fillAll” to do the right thing? We have to use work arounds?
@jules with all due respect, I think you’re wrong here. This is not about some random fillRect function call. This is “fillAll” we’re talking about. It has to do the right thing and fill all pixels of that component. The fact that a workaround without artifacts exists proves you wrong. The work around does not fill outside the clip rect. It’s “fillAll” that stays too far inside.
JUCE itself is using it to fill components, the app background window, menus, etc. it has to be reliable and work without artifacts, no matter the scale.
Rather than fillAll being the problem could it not be the clipping that is the issue. i.e. the component is not being clipped to the clipBounds? or at least the rounding being used in fillAll and the clipping given the same bounds produces different results.
I need to do more research, but I think the issue is that fillAll() anti aliases when it gets to the edges, but the rest of the painting system when it sees an opaque component thinks it doesn’t need to paint anything underneath. But this isn’t true when scaling is involved, so I’m seeing uninitialized memory get painted. I’ll need to update my test program to more like my actual app.
Yes, but the component doesn’t have integer bounds anymore, because it’s scaled. And when the boundary is between two pixels, there is a 50% alpha blend on the outside.
When you analyse the red line you see, its not the pure red, its a mix between the red and grey and and little black (background), and that is the intended behaviour of this rendering engine.
At least on Mac, on windows it might be pure red (with a little black), because of the other fillRect-bug (fillAll is based on fillRect), because on windows it uses physical pixels which is inconsistent, and the grey doesn’t alpha overlap.
Please stop repeating yourselves. We all fully understand what the problem is. Our issue is that the “fillAll” (all means everything) is NOT doing its job. I don’t care what the internal implementation does. I don’t care that it (right now) uses the integer clip-bounds instead of transforming them correctly.
It’s a bug. It should do it correctly. I can’t believe we are arguing about a reproducible bug. The name of the function is “fillAll”. Here is its description from the docs:
Fills the context's entire clip region with the current colour or brush.
I think we can all agree that is NOT what is happening. It’s buggy. Unreliable. Not doing what it says on the tin. It is, in fact, NOT filling the entire clip region. Evidently, if we force a larger rect, it actually fills the entire clip region and thus has no artifacts.
Look when I’m on the modulation page near the User LFO 1 depth. Then I switch to the arp. You can still see the depth slider poking through above the time bar, which is an opaque component. If this was just an antialiasing issue the background of the time bar would be blended with the background of the arp page. But instead, it’s getting antialiased with garbage data. If I’m on a different page before I switch to the arp, then the garbage data is in a different location. If I don’t make the components opaque, then the garbage data is gone. There is definitely an issue with fillAll() + setOpaque(true) + scaling.
Actually I really trying to analyse whats going on. I really putting effort into it. I compiled the example on mac and windows. I have different results on windows and mac. I really think my observation is part of the problem.