Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45123
In `gdiplus/graphicspath.c` calculating the Pythagorean addition is needed, which is defined as:
a ⊕ b = sqrt(a^2+b^2)
This is hypotenuse, or the length of the longest side of a right-angled triangle, that we know the other 2 sides, a and b. https://en.wikipedia.org/wiki/Pythagorean_addition
By using `sqrt(a * a + b * b)`, for large (or small) `a` or `b`, there is a possibility of overflow (underflow), although the result itself is not that big (small) to cause overflow (underflow).
To overcome this problem, there are implementations of hypotenuse that do not use power of 2, and use other methods to calculate the result. To calculate `a ⊕ b`, you can easily use `hypotf(a,b)`.
https://en.cppreference.com/w/cpp/numeric/math/hypot
-- v5: gdiplus/font: Avoid computation overflow and underflow by using hypotf gdiplus/graphicspath: Avoid computation overflow and underflow by using hypotf.
From: Bartosz Kosiorek gang65@poczta.onet.pl
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45123
By using sqrt(a * a + b * b), for large (or small) a or b, there is a possibility of overflow (underflow), although the result itself is not that big to cause overflow.
To overcome this problem, there are implementations of hypotenuse that do not use power of 2, and use other methods to calculate the result. To calculate a ⊕ b, you can easily use hypotf(a,b).
https://en.cppreference.com/w/cpp/numeric/math/hypot --- dlls/gdiplus/graphicspath.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 63f120a6aba..bcaa1230d22 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -201,7 +201,7 @@ static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, R * x0(y2 - y1) + y0(x1 - x2) + (x2*y1 - x1*y2) */ area_triangle = (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); - distance_start_end = sqrtf(powf(pt.Y - pt_st.Y, 2.0) + powf(pt_st.X - pt.X, 2.0)); + distance_start_end = hypotf((pt.Y - pt_st.Y), (pt_st.X - pt.X)); if(fabs(area_triangle) <= (0.5 * flatness * distance_start_end)){ continue; } @@ -1867,7 +1867,7 @@ static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint, { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; - REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx); + REAL segment_length = hypotf(segment_dy, segment_dx); REAL distance = pen_width / 2.0; REAL bevel_dx, bevel_dy;
@@ -1903,8 +1903,8 @@ static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF * if ((p2->X - p1->X) * (p3->Y - p1->Y) > (p2->Y - p1->Y) * (p3->X - p1->X)) { float distance = pen_width / 2.0; - float length_0 = sqrtf((p2->X-p1->X)*(p2->X-p1->X)+(p2->Y-p1->Y)*(p2->Y-p1->Y)); - float length_1 = sqrtf((p3->X-p2->X)*(p3->X-p2->X)+(p3->Y-p2->Y)*(p3->Y-p2->Y)); + float length_0 = hypotf((p2->X - p1->X), (p2->Y - p1->Y)); + float length_1 = hypotf((p3->X - p2->X), (p3->Y - p2->Y)); float dx0 = distance * (p2->X - p1->X) / length_0; float dy0 = distance * (p2->Y - p1->Y) / length_0; float dx1 = distance * (p3->X - p2->X) / length_1; @@ -1954,7 +1954,7 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; - REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx); + REAL segment_length = hypotf(segment_dy, segment_dx); REAL distance = pen_width / 2.0; REAL bevel_dx, bevel_dy; REAL extend_dx, extend_dy; @@ -1989,7 +1989,7 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; - REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx); + REAL segment_length = hypotf(segment_dy, segment_dx); REAL distance = pen_width / 2.0; REAL dx, dy, dx2, dy2; const REAL control_point_distance = 0.5522847498307935; /* 4/3 * (sqrt(2) - 1) */ @@ -2034,7 +2034,7 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; - REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx); + REAL segment_length = hypotf(segment_dy, segment_dx); REAL distance = pen_width / 2.0; REAL dx, dy;
@@ -2074,7 +2074,7 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; - REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx); + REAL segment_length = hypotf(segment_dy, segment_dx); REAL distance = pen_width / sqrtf(2.0); REAL par_dx, par_dy; REAL perp_dx, perp_dy; @@ -2099,7 +2099,7 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; - REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx); + REAL segment_length = hypotf(segment_dy, segment_dx); REAL dx, dy, dx2, dy2; const REAL control_point_distance = 0.55228475; /* 4/3 * (sqrt(2) - 1) */
@@ -2151,7 +2151,7 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; - REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx); + REAL segment_length = hypotf(segment_dy, segment_dx); REAL par_dx, par_dy; REAL perp_dx, perp_dy;
@@ -2175,7 +2175,7 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, { REAL segment_dy = nextpoint->Y - endpoint->Y; REAL segment_dx = nextpoint->X - endpoint->X; - REAL segment_length = sqrtf(segment_dy * segment_dy + segment_dx * segment_dx); + REAL segment_length = hypotf(segment_dy, segment_dx); REAL par_dx = pen_width * segment_dx / segment_length; REAL par_dy = pen_width * segment_dy / segment_length; REAL perp_dx = -par_dy; @@ -2407,7 +2407,7 @@ static void widen_dashed_figure(GpPath *path, int start, int end, int closed,
segment_dy = path->pathdata.Points[j].Y - path->pathdata.Points[i].Y; segment_dx = path->pathdata.Points[j].X - path->pathdata.Points[i].X; - segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx); + segment_length = hypotf(segment_dy, segment_dx); segment_pos = 0.0;
while (1)
From: Bartosz Kosiorek gang65@poczta.onet.pl
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45122 --- dlls/gdiplus/graphics.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-)
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index cc8411d54f7..39c073eeb00 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -274,7 +274,7 @@ static INT prepare_dc(GpGraphics *graphics, GpPen *pen) scale_x = graphics->worldtrans.matrix[0] + graphics->worldtrans.matrix[2]; scale_y = graphics->worldtrans.matrix[1] + graphics->worldtrans.matrix[3];
- width = sqrt(scale_x * scale_x + scale_y * scale_y) / sqrt(2.0); + width = hypotf(scale_x, scale_y) / sqrt(2.0);
width *= units_to_pixels(pen->width, pen->unit == UnitWorld ? graphics->unit : pen->unit, graphics->xres, graphics->printer_display); @@ -285,8 +285,7 @@ static INT prepare_dc(GpGraphics *graphics, GpPen *pen) pt[1].X = 1.0; pt[1].Y = 1.0; gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceDevice, pt, 2); - width *= sqrt((pt[1].X - pt[0].X) * (pt[1].X - pt[0].X) + - (pt[1].Y - pt[0].Y) * (pt[1].Y - pt[0].Y)) / sqrt(2.0); + width *= hypotf((pt[1].X - pt[0].X), (pt[1].Y - pt[0].Y)) / sqrt(2.0); }
if(pen->dash == DashStyleCustom){ @@ -1844,7 +1843,7 @@ static void shorten_line_percent(REAL x1, REAL y1, REAL *x2, REAL *y2, REAL per if((y1 == *y2) && (x1 == *x2)) return;
- dist = sqrt((*x2 - x1) * (*x2 - x1) + (*y2 - y1) * (*y2 - y1)) * -percent; + dist = hypotf((*x2 - x1), (*y2 - y1)) * -percent; theta = gdiplus_atan2((*y2 - y1), (*x2 - x1)); dx = cos(theta) * dist; dy = sin(theta) * dist; @@ -1865,7 +1864,7 @@ static void shorten_line_amt(REAL x1, REAL y1, REAL *x2, REAL *y2, REAL amt) if(dx == 0 && dy == 0) return;
- percent = amt / sqrt(dx * dx + dy * dy); + percent = amt / hypotf(dx, dy); if(percent >= 1.0){ *x2 = x1; *y2 = y1; @@ -1913,7 +1912,7 @@ static void shorten_bezier_amt(GpPointF * pt, REAL amt, BOOL rev) dx = pt[fourth].X - origx; dy = pt[fourth].Y - origy;
- diff = sqrt(dx * dx + dy * dy); + diff = hypotf(dx, dy); percent += 0.0005 * amt; } } @@ -5372,11 +5371,9 @@ void transform_properties(GpGraphics *graphics, GDIPCONST GpMatrix *matrix, BOOL gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, pt, 3);
if (rel_width) - *rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+ - (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X)); + *rel_width = hypotf((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X)); if (rel_height) - *rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+ - (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X)); + *rel_height = hypotf((pt[2].Y - pt[0].Y), (pt[2].X-pt[0].X)); if (angle) *angle = -gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X)); } @@ -7110,10 +7107,8 @@ GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT GdipTransformMatrixPoints(&xform, pt, 3); } gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, pt, 3); - rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+ - (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X)); - rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+ - (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X)); + rel_width = hypotf((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X)); + rel_height = hypotf((pt[2].Y - pt[0].Y), (pt[2].X - pt[0].X));
if (flags & DriverStringOptionsCmapLookup) {
This merge request was approved by Esme Povirk.