Is there something like masks from photoshop?

imagine you have 2 closed paths that never intersect. that would mean that they sorround a complexly shaped area within the window. now imagine you wanna draw an image onto the whole window’s size, but only make it visible in that area, similiar to how masks work in photoshop when you select an area. i have some problems with this. first of all there seems to be no way to get an object that represents the shape between 2 paths. 2ndly i don’t see other object-types that can be used to draw complex shapes so nicely except for paths. but even if there’s function somewhere that really draws a thing between 2 paths it would probably only be simple colours and gradients instead of parts of an image because images don’t have masks (yet) do they? i think if something like masks doesn’t exist yet it would be a powerful new feature for making guis. it would probably even make stuff like slider development simpler. if there is a way to do this already pls tell me about it :>

edit: oh and i’d add a Point-Array to path objects. it’s kinda weird that i can’t iterate through a path after having it made

You can get the low level graphics contents from the Graphics object in your paint() function. Then you can “mask” using one of a number of methods in LowLevelGraphicsContext:

virtual bool clipToRectangle (const Rectangle<int>&) = 0;
virtual bool clipToRectangleList (const RectangleList<int>&) = 0;
virtual void excludeClipRectangle (const Rectangle<int>&) = 0;
virtual void clipToPath (const Path&, const AffineTransform&) = 0;
virtual void clipToImageAlpha (const Image&, const AffineTransform&) = 0;

For example using a Path object via clipToPath()

1 Like

And you can iterate through a Path object using Path::Iterator.

1 Like

yeah matkat told me about that too but i didn’t understand what an iterator is and just moved on with something else for now. i just wonder why it can’t be an array like almost all other information that is stored in list-type of ways in c++.

i see. then i will check these methods out. the clipToPath-object could really be helpful here, even though just from looking at it i don’t instantly see how i could get the area in the middle of 2 paths with that, since it only takes one path. admittedly i never tried to just use 2 subpaths in one path yet, so if there is any solution to the problem i suspect it to be there and i’ll try that soon

Probably because modern c++ leans towards containers, not arrays, and iterators are used to iterate over the contents. :slight_smile:

i don’t even know what a container is. another thing on my long long list of c++things to check out.

standard library (aka std:: ) vector, list, queue, map, etc… :slight_smile: they encapsulate details, allow usage of std algorithms, etc…

Seems there is a misconception about what a path is. It is NOT a list of points (polygon), but a list of segments.
Each segment can be

  • start position
  • lineTo point (straight line from last position)
  • quadraticTo segment (curved line from last position, needs a point and a control point to determine the curve how to approach the point)
  • cubicTo segment (curved line, has a control point how the previous point is left and how the next point is approached)
  • closeSubPath (straight line to start position)

All the othr primitives are actually shortcuts to add those segments to make the primitive appear

That is the reason, why you cannot iterate the points, but rather the segments using the Path::Iterator. If you look at it’s docs, you will see what can actually be in the path.

To use the clipRegion, if you need the intersection, simply add both paths after each other using clipToPath(). To create a union, I would suggest to draw twice using one of the masks each time.

BTW, to get rid of a clip region, save the previous state using

{
    const Graphics::ScopedSaveState state (g);
    g.clipToPath (p1);
    g.clipToPath (p2);
    g.drawImage (/* ... */)
}
// when state went out of scope, the previous state is restored -> clip area is reset
1 Like

I’m sorry to wake up this old discussion, but I was playing with clipping today using the LowLevelGraphicsContext and this code does not seem to work to restore the previous state. What does work, as an example, is:

LowLevelGraphicsContext& llgc = g.getInternalContext();
       
llgc.saveState();
Rectangle<int> test = getLocalBounds().reduced(40, 40);
llgc.clipToRectangle(test);

// do some drawing here, anything outside the test rect is clipped

llgc.restoreState();

// do some more drawing here, outside the test rect, it is no longer clipped
1 Like

Interesting, as far as for the ScopedSaveState, that is exactly what happens under the hood:

The {} in my example above are not optional, they delimit the scope to trigger destruction of the ScopedSaveState and therefore restoring the previous state.

Yes, I understand that, and I put it within {} before attempting to draw outside of the clip again. Let me see if I did something wrong…

In my object’s paint() method, I’m trying to:

  • draw some stuff
  • set up a clipping rect and draw several paths with different colors such that anything outside the clip region is clipped.
  • go back to the original clipping shape, and draw some more stuff outside of my clipping rect.

EDIT: deleted long explanation and wrong assumptions…

I found the answer here:

All I needed to do is:

// draw some stuff first
g.fillAll(someColour.withAlpha(alpha));
  
// set up a clipping rect
Rectangle<int> clip = getLocalBounds().reduced(20, 20);

// save state
g.saveState();

// reduce the clipping region:
g.reduceClipRegion(clip);

// draw all the path stuff here

// restore the state
g.restoreState();

// draw more stuff here outside of the clipping rect