[PATCH 2/2] gdiplus: Revise closeness check for bezier curve flattening.

Esme Povirk (she/they) esme at codeweavers.com
Fri Feb 4 11:38:22 CST 2022


It's possible, but I'd say there are also correct ways to use these comparisons.

On Fri, Feb 4, 2022 at 10:03 AM Fabian Maurer <dark.shadow4 at web.de> wrote:
>
> More of a general question towards the wine devs:
> According to gcc we have a lot of such float comparisons in the code. Isn't
> that a potential general problem?
>
> Regards,
> Fabian Maurer
>
> On Freitag, 4. Februar 2022 16:58:48 CET Robert Feuerbach wrote:
> > The float equality and flatness calculation in flatten_bezier
> > can fail due to the limited precision of the float math.
> > The equality test was replaced with a simple check against
> > the given flatness tolerance.
> >
> > Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52492
> > Signed-off-by: Robert Feuerbach <rjfeuerbach at gmail.com>
> > ---
> >  dlls/gdiplus/graphicspath.c | 11 ++++++-----
> >  1 file changed, 6 insertions(+), 5 deletions(-)
> >
> > diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c
> > index ce2666eedab..c1bdf226e52 100644
> > --- a/dlls/gdiplus/graphicspath.c
> > +++ b/dlls/gdiplus/graphicspath.c
> > @@ -109,7 +109,7 @@ static INT path_list_count(path_list_node_t *node)
> >   *  - (x2, y2): first control point;
> >   *  - (x3, y3): second control point;
> >   *  - end     : pointer to end point node
> > - *  - flatness: admissible error of linear approximation.
> > + *  - flatness: admissible error of linear approximation in coordinate
> > units. *
> >   * Return value:
> >   *  TRUE : success
> > @@ -142,12 +142,13 @@ static BOOL flatten_bezier(path_list_node_t *start,
> > REAL x2, REAL y2, REAL x3, R mp[2].X = (mp[1].X + mp[3].X) / 2.0;
> >      mp[2].Y = (mp[1].Y + mp[3].Y) / 2.0;
> >
> > -    if ((x2 == mp[0].X && y2 == mp[0].Y && x3 == mp[1].X && y3 == mp[1].Y)
> > || -        (x2 == mp[3].X && y2 == mp[3].Y && x3 == mp[4].X && y3 ==
> > mp[4].Y)) -        return TRUE;
> > -
> >      pt = end->pt;
> >      pt_st = start->pt;
> > +    /* test for closely spaced points to avoid limited-precision errors in
> > flatness check */ +    if((fabs(pt.X - mp[2].X) + fabs(pt.Y - mp[2].Y) +
> > +        fabs(pt_st.X - mp[2].X) + fabs(pt_st.Y - mp[2].Y) ) <= flatness)
> > +        return TRUE;
> > +
> >      /* check flatness as a half of distance between middle point and a
> > linearized path */ if(fabs(((pt.Y - pt_st.Y)*mp[2].X + (pt_st.X -
> > pt.X)*mp[2].Y + (pt_st.Y*pt.X - pt_st.X*pt.Y))) <=
>
>
>
>
>



More information about the wine-devel mailing list