Is there a way to undo a reduction of the clipping region?


#1

I often find myself needing to reduce the clipping bounds for various reasons. And sometimes I need to draw multiple things within one component but each having different clipping bounds. The trouble is, once I reduce the clipping bounds to allow me to draw feature A, I don’t know how to undo those clipping bounds so that I can create entirely different clipping bounds for feature B.


#2

Wrap your calls in a block containing a Graphics::ScopedSaveState and when it goes out of scope it will reset the clipping region.


#3

Awesome! Thanks man!


#4

there’s a video from ADC around 2015 where Jules says that ScopedSaveState is a pretty heavy object, and you shouldn’t use it frequently if you can avoid it tho. Any comments on that @dave96?


#5

If graphics performance matters then you have to think carefully about everything you do, and sure, pushing and popping the graphics state can involve more work than you expect, depending on the complexity of the clip region. But I think you’d typically only decide to use ScopedSaveState if you really need to achieve this effect.


#6

Well to be honest, I could alternatively use a bunch of Images, each with their own clip region and then draw each image onto the component. I have just never really devoted enough time to understanding how to optimise graphics, so I assumed that changing clip regions would be faster than the approach I just described. (Technically it involves drawing each image twice… so common sense seemed to suggest that it would involve more processing power)


#7

If the ScopedSaveState is such a heavy object, would there be a way to expose a “partial save state” that does not store and reset the entire state of the Graphics object, but only, say, the clipping region? Or is the clipping region so interweaved with the rest of the object, that it’s impractical to separate it?


#8

No, it’s all very intertwined!

Don’t get too concerned about how long it takes though, I think people are making it sound a lot worse than it is. Unless you’re really hammering it, it’s not something you generally need to worry about.


#9

Graphics::saveState/restoreState (which is all Graphics::ScopedSavedState calls) is called for every Component::paint call so it’s effectively being used a hell of a lot already.

You can opt-in to disable it by calling Component::setPaintingIsUnclipped (true) but that’s not the default and requires a bit more care in your paint method.

My general rule of thumb is to not worry about this for normal Components but if I have something that’s small or being repainted a lot, turn setPaintingIsUnclipped on.

As always though, you need to profile this stuff. Graphics::saveState/restoreState effectively bumps a few reference counts and copies a few trivial objects. That’s really not “heavyweight” compared to the amount of work done in flattening, rasterizing and drawing even a simple path…