Search code examples
c#drawingmauibezier

FillPath ignores bezier curve in a seemingly closed path in MAUI app


I am trying to draw a bar, whose top segment wraps around a centered button. I have succesfully constructed a PathF object, which consists of lines and bezier curves, and when I use the DrawPath method, it does draw the bar as I intend.

Now when I try to fill it (which is the end goal), the path gets ignored, as it is not closed. See the following screenshots:

DrawPath:

DrawPath

FillPath:

FillPath

I have tried to tweak my code in a different way for the last hour but could not get it to work, surely I must be misunderstanding something about the way to fill/close a path ?

Here is the Draw method of the IDrawable object for the bar:

        public void Draw(ICanvas canvas, RectF dirtyRect)
        {
            float buttonSize = 80;
            float width = dirtyRect.Width;
            float height = dirtyRect.Height;
            canvas.StrokeColor = Colors.Red;
            canvas.FillColor = Colors.Blue;
            canvas.StrokeSize = 1;

            float y1 = height / 2; // bar top 
            float tX = width / 2; // x translation applied to all bezier curve points
            float tY = height / 2; // y translation applied to all bezier curve points
            float r = buttonSize * 1.5f / 2; // radius
            float c = 0.5522847498307933984022516322796f;

            float segmentWidth = (width - (r * 2)) / 2;

            PathF path = new PathF(0, y1);

            path.LineTo(segmentWidth, y1);            //  _____
            path.MoveTo(width - segmentWidth, y1);    //          x
            path.LineTo(width, y1);                   //           _____
            path.LineTo(width, height);               //               |
            path.LineTo(0, height);                   //  --------------
            path.LineTo(0, y1);                       // |


            path.MoveTo(r + tX, 0 + tY);
            path.CurveTo(r + tX, c * r + tY,
                c * r + tX, r + tY,
                0 + tX, r + tY);

            path.MoveTo(0 + tX, r + tY);
            path.CurveTo(-c * r + tX, r + tY,
                -r + tX, c * r + tY,
                -r + tX, 0 + tY);

            canvas.FillPath(path);
        }

<Grid ColumnDefinitions="*, Auto, *" RowDefinitions="*, 15*, 200">
    <Button Grid.Row="0" Text="Draw" Clicked="Button_Clicked"/>
    <Grid Grid.Row="2" Grid.ColumnSpan="3" Padding="10, 10">
        <GraphicsView x:Name="bottomBar" Grid.ColumnSpan="3"/>
    </Grid>
</Grid>

Thanks a lot for any input on this


Solution

  • As Mike commented, the Path is not closed because of the MoveTo instructions in the middle, the following code does the trick:

                float buttonSize = 80;
                float width = dirtyRect.Width;
                float height = dirtyRect.Height;
                canvas.StrokeColor = Colors.Green;
                canvas.FillColor = Colors.Blue;
                canvas.StrokeSize = 1;
    
                float tX = width / 2; // x translation applied to all bezier curve points
                float r = buttonSize * 1.5f / 2; // radius
                float c = 0.5522847498307933984022516322796f;
    
                PathF path = new PathF(r + tX, 0);
    
                path.CurveTo(r + tX, c * r,
                    c * r + tX, r,
                    0 + tX, r);
    
                path.CurveTo(-c * r + tX, r,
                    -r + tX, c * r,
                    -r + tX, 0);
    
                path.LineTo(0, 0);
                path.LineTo(0, height);
                path.LineTo(width, height);
                path.LineTo(width, 0);
                path.LineTo(width - ((width - (r * 2)) / 2), 0);
                canvas.FillPath(path);