fillPath doesn't fill path

it only seems to draw the lines, just like strokePath, but with less options. how would i go about actually filling the space inside of a path that ends where it starts?

Are you using setFillType before fillPath? I think this might be why it’s not working for you if not.

eg:

    auto triangle = Path();
    triangle.startNewSubPath(19.0 / 2.0, 2.0);
    triangle.lineTo(17.0, 17.0);
    triangle.lineTo(2.0, 17.0);
    triangle.closeSubPath();
    auto transform = triangle.getTransformToScaleToFit(getLocalBounds().toFloat(), true);
    auto fillType = FillType();
    fillType.setColour(Colours::black);
    g.setFillType(fillType);
    g.fillPath(triangle, transform);
2 Likes

Perhaps you’re not using closeSubPath to close the path? Simply adding the same point as start and end point doesn’t suffice.

2 Likes

Wow, i’m just discovering this class

https://docs.juce.com/master/classFillType.html#a10bd0d13433133545b26ea3894b3c641

Doesn’t it make sense to make the alpha be its own member, instead of pulled from some colour member?

1 Like

hey. thanks for your help :slight_smile: i added the things that you suggested now, but i still have a problem. my code looks like this:

my goal is that everything to the right of the yellow line becomes a bit darker, just like the rectangle at the top. some kinda… universal function that fills everything with a colour, no matter which shape it has. as you can see the code didn’t do that. (not even sure what it did in general.) maybe you misunderstood me or i made something wrong here… idk. also i must admit i was kinda expecting it to be more of a one-liner, since filling rectangles is also like that^^. maybe a point for the improvement of juce.

if all this stuff is not so easily possible i’d also be happy about just a function for filling triangles for this particular project. then i could make it look like a whole piece, while actually being fragments

You need to define a gradient whose point members are the left side and right side of the area you want to paint with the gradient.

Not sure if this is the problem, but 2 things might help:

  • Don’t use the Array intermediary, just add points to a Path directly.
  • Don’t add the last point (0.f, 2.f), just close the path.

You don’t need any of the transform stuff since you’re not using it, that was just an example that was specific to my particular code that I just copy/pasted, sorry for the red herring!

Presumably transBlack is defined as a semi-opaque black?

It would be easy to give you proper code example that fits your use case if you had pasted the code here rather than a screen shot, use triple back ticks ( ` x 3 ) to surround your code (or use the </> button on the code after highlighting it here in the editor) in future, makes life easier. :wink:

this is going to be slightly offtopic but i’d like to explain this. i made a grid-class that draws a grid on the component and then lets me make layout decisions based on that grid. however i noticed that it’s kinda unintuitive sometimes, that a line-object’s last 2 values are not the relative amount of pixels away from that start, just like when you make a rectangle, but the absolute values of that position. so i wrote a function that draws a path if you just give it an array of “movements”. it works fine as you can see. it draws the yellow path.

thank you for clarifying that! i am still confused about transform and try to avoid it as much as possible when i’m not in the mood for riddles.

ok, that was something i actually asked myself. when i only used closePath it didn’t drew that last line so i thought it wouldn’t work like that.

thanks! that might be it. trying to figure out how to use gradient-objects now.

edit: currently trying to understand filltype and gradient-objects. if i understand it correctly a colourGradient is basically just an object with 2 colours and some functions to draw lines that go from one colour to another. maybe there is a misunderstanding here. i don’t want to make a gradient. i want to take this opaqueblack-colour called transBlack and apply it to the whole area to the right of the yellow line. just like you’d fill a rectangle, but with more complex shapes than that.

if i understood fillType already it changes the way paths are being rendered by Graphics& g. however i don’t see any function in it that claims to enable me to fill a shape with a colour. i mean these functions also use the word “fill” but they are made for drawing lines, not filling space, aren’t they?

Then you need 2 paths.
one path includes the line and the left edge of your GUI
The other path includes the line, and the right edge of the GUI.

Make them closed paths so you can g.fillPath() them.

Path line;  //the line itself, not closed.

Path left, right;
left.addPath(line);
left.lineTo(bounds.getBottomLeft().toFloat());
left.closeSubPath();

right.addPath(line);
right.lineTo(bounds.getBottomRight().toFloat());
right.lineTo(bounds.getTopRight().toFloat());
right.closeSubPath();

g.setColour(Colours::yellow);
g.strokePath(line, PathStrokeType(2));
g.setColour(leftFill);
g.fillPath(left);
g.setColour(rightFill);
g.fillPath(right);

that kinda just draws the same line again. unexpected though. i thought it would add lines that go to these corners.

You are going to need to figure out what you want your path shape to be for the area you’re trying to fill. That’s not something we can debug for you.

i’m not even sure if it’s really a “bug”. it’s either a completely missing function or no one understands me.


i just want to find a function that looks at a closed path and draw a colour everywhere inside of it, like this green space that i just drew in gimp for demonstrational purposes. the reason why i think that no one quite gets me here is that i don’t believe there is no function for such stuff. i mean i can’t be the first person here who wants to fill a different shape than a rectangle or ellipse, can i?

You sure getLinePath really does what you want? Filling closed paths works without problems. Maybe your path is really just a line path (seems it’s not a JUCE method right?).
You might want to test it with one of the examples the others posted above.

Sure. I draw a tab and edge on the side of a component. There must be something incorrect in what you are doing.

resized()
{
    browserTabPath.clear ();
    browserTabPath.startNewSubPath (0.0f, startY);
    browserTabPath.lineTo (tabHeight, startY);
    browserTabPath.lineTo (tabHeight, startY + tabWidth);
    browserTabPath.lineTo (0.0f, startY + tabWidth);
    browserTabPath.closeSubPath ();
}
	
paint()
{
	g.setColour (AppBlue);
	g.fillPath (browserTabPath);
}

image

Sounds like you don’t understand how to create a path properly.

void paint(Graphics& g)
{
    auto bounds = getLocalBounds().toFloat();
    Path p;
    p.startNewSubPath(bounds.getTopLeft());
    p.lineTo(bounds.getTopRight());
    p.lineTo(bounds.getBottomRight());
    p.closeSubPath();

    g.setColour(Colours::green);
    g.fillPath(p);
}

Now just make your path be the complex path you need.
The yellow border is a path filled with black
the histogram plots are Paths filled with a gradient.

yeah i’m pretty sure it does. i wrote it myself and it’s a very easy method. it just creates a path that consists of an unspecific amount of lines. this is the code, if you wanna check:

Path getLinePath(Array<Array<float>> way) {
        Path path;

        float xA, yA, xB, yB;

        xA = way[0][0];
        yA = way[0][1];
        xB = way[1][0];
        yB = way[1][1];

        path.addLineSegment(getLine(xA, yA, xB, yB), 1.f);

        for (unsigned int point = 2; point < way.size(); point++) {
            xA += xB;
            yA += yB;
            xB = way[point][0];
            yB = way[point][1];

            path.addLineSegment(getLine(xA, yA, xB, yB), 1.f);
        }

        return path;
    }

i did, but i already failed at closing a subpath. the method closeSubPath() just doesn’t do anything. it is supposed to add the last line to the path, that goes back to the start, but it just doesn’t do that. not even in a fresh project.

that’s not impossible. however, i find it more likely that closeSubPath() is just not working properly for some reason. or else i’d see it adding a line when i fill or stroke the path, wouldn’t i?

We have all shown you examples of us successfully creating and filling paths, using closeSubPath() as part of the process. I find it more likely that you are doing something wrong.

lol no. it definitely works correctly.

stop using your function for a bit, and create your path normally the way we have all shown you. See if that gets you where you want to get to.

ok i finally got it working. i gotta admit you were right that i didn’t understand paths correctly. but in my defense the path-class can be extremely misleading! i mean… it gives you the option to add line-objects but if you do that you can’t use closeSubPath() anymore, because the path doesn’t know anymore that its lines belong together. why are these methods even in the path-object at all if they only reduce its functionality drastically? however. thank y’all for helping me out again <3

here’s code that works in case anyone else googles paths while having my exact problem and finds this post:

Path path;
    path.startNewSubPath(20, 20);
    path.lineTo(20, 200);
    path.lineTo(200, 200);
    path.closeSubPath();

    g.setColour(Colours::grey);
    g.fillPath(path);

    g.setColour(Colours::yellow);
    g.strokePath(path, PathStrokeType(2.f));

The path cannot know, if you want to display separate line segments or a polygon. And it is not the path’s job to check, if vertices of your line segments accidentally coincide.

The path is to bundle an arbitrary amount of drawing primitives together, heavily used in SVG rendering, font rendering and many more places. And it makes it easy to keep them tied together and apply transformations on the whole.

1 Like