From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/win32u/dibdrv/graphics.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/dlls/win32u/dibdrv/graphics.c b/dlls/win32u/dibdrv/graphics.c index cc62d6a681b..e7648cb2596 100644 --- a/dlls/win32u/dibdrv/graphics.c +++ b/dlls/win32u/dibdrv/graphics.c @@ -1556,6 +1556,19 @@ BOOL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, return FALSE; }
+ if (right < left) + { + int tmp = left; + left = right; + right = tmp; + } + if (bottom < top) + { + int tmp = top; + top = bottom; + bottom = tmp; + } + SetRect( &rect, left, top, left + ellipse_width, top + ellipse_height ); /* Points are relative to the arc center. * We just need to specify any point on the vector. */
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/win32u/dibdrv/graphics.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/dlls/win32u/dibdrv/graphics.c b/dlls/win32u/dibdrv/graphics.c index e7648cb2596..64d58ac6ed7 100644 --- a/dlls/win32u/dibdrv/graphics.c +++ b/dlls/win32u/dibdrv/graphics.c @@ -316,6 +316,12 @@ static int get_arc_points( DC *dc, int arc_dir, const RECT *rect, POINT start, P
count = generate_ellipse_top_half( dc, width, height, points );
+ /* The ellipse is always generated counterclockwise from the origin. + * This means our points will essentially be backwards if the world + * transform includes a flip. Swap the arc direction to correct for this. */ + if (dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < dc->xformWorld2Vport.eM12 * dc->xformWorld2Vport.eM21) + arc_dir = (arc_dir == AD_CLOCKWISE ? AD_COUNTERCLOCKWISE : AD_CLOCKWISE); + /* Transform the start and end, but do not translate them, so that they * remain relative to the ellipse center. */ lp_to_dp_no_translate( dc, &start );
From: Elizabeth Figura zfigura@codeweavers.com
This unnecessarily loses precision, and if the point is very close to the origin (as for the internal arcs generated by RoundRect(), but also for those specified manually) this may generate an incorrect arc.
This addresses the last artifacts from bug 35331. --- dlls/win32u/dibdrv/graphics.c | 41 +++++++++++++++-------------------- 1 file changed, 17 insertions(+), 24 deletions(-)
diff --git a/dlls/win32u/dibdrv/graphics.c b/dlls/win32u/dibdrv/graphics.c index 64d58ac6ed7..7af658230a5 100644 --- a/dlls/win32u/dibdrv/graphics.c +++ b/dlls/win32u/dibdrv/graphics.c @@ -267,7 +267,7 @@ static unsigned int generate_ellipse_top_half( const DC *dc, double width, doubl return pos; }
-static int find_intersection( const POINT *points, int x, int y, int count ) +static int find_intersection( const POINT *points, double x, double y, int count ) { int i;
@@ -299,15 +299,16 @@ static int find_intersection( const POINT *points, int x, int y, int count ) } }
-static void lp_to_dp_no_translate( DC *dc, POINT *point ) +static void lp_to_dp_no_translate( DC *dc, double *x, double *y ) { - double x = point->x; - double y = point->y; - point->x = GDI_ROUND( x * dc->xformWorld2Vport.eM11 + y * dc->xformWorld2Vport.eM21 ); - point->y = GDI_ROUND( x * dc->xformWorld2Vport.eM12 + y * dc->xformWorld2Vport.eM22 ); + double in_x = *x, in_y = *y; + + *x = in_x * dc->xformWorld2Vport.eM11 + in_y * dc->xformWorld2Vport.eM21; + *y = in_x * dc->xformWorld2Vport.eM12 + in_y * dc->xformWorld2Vport.eM22; }
-static int get_arc_points( DC *dc, int arc_dir, const RECT *rect, POINT start, POINT end, POINT *points ) +static int get_arc_points( DC *dc, int arc_dir, const RECT *rect, double start_x, double start_y, + double end_x, double end_y, POINT *points ) { int i, pos, count, start_pos, end_pos; int width = rect->right - rect->left; @@ -324,11 +325,11 @@ static int get_arc_points( DC *dc, int arc_dir, const RECT *rect, POINT start, P
/* Transform the start and end, but do not translate them, so that they * remain relative to the ellipse center. */ - lp_to_dp_no_translate( dc, &start ); - lp_to_dp_no_translate( dc, &end ); + lp_to_dp_no_translate( dc, &start_x, &start_y ); + lp_to_dp_no_translate( dc, &end_x, &end_y );
- start_pos = find_intersection( points, start.x, start.y, count ); - end_pos = find_intersection( points, end.x, end.y, count ); + start_pos = find_intersection( points, start_x, start_y, count ); + end_pos = find_intersection( points, end_x, end_y, count ); if (arc_dir == AD_CLOCKWISE) { int tmp = start_pos; @@ -429,9 +430,9 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom, { points[0] = dc->attr->cur_pos; lp_to_dp( dc, points, 1 ); - count = 1 + get_arc_points( dc, dc->attr->arc_direction, &rect, pt[0], pt[1], points + 1 ); + count = 1 + get_arc_points( dc, dc->attr->arc_direction, &rect, pt[0].x, pt[0].y, pt[1].x, pt[1].y, points + 1 ); } - else count = get_arc_points( dc, dc->attr->arc_direction, &rect, pt[0], pt[1], points ); + else count = get_arc_points( dc, dc->attr->arc_direction, &rect, pt[0].x, pt[0].y, pt[1].x, pt[1].y, points );
if (count > max_points) ERR( "point count %u exceeds max points %u\n", count, max_points ); @@ -1538,7 +1539,7 @@ BOOL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, dibdrv_physdev *pdev = get_dibdrv_pdev( dev ); DC *dc = get_physdev_dc( dev ); RECT rect; - POINT start, end, rect_center, *points, *top_points; + POINT rect_center, *points, *top_points; int count, max_points; BOOL ret = TRUE; HRGN outline = 0, interior = 0; @@ -1578,18 +1579,10 @@ BOOL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, SetRect( &rect, left, top, left + ellipse_width, top + ellipse_height ); /* Points are relative to the arc center. * We just need to specify any point on the vector. */ - start.x = -1; - start.y = 0; - end.x = 0; - end.y = -1; - count = get_arc_points( dc, AD_CLOCKWISE, &rect, start, end, top_points ); + count = get_arc_points( dc, AD_CLOCKWISE, &rect, -1.0, 0.0, 0.0, -1.0, top_points );
SetRect( &rect, right - ellipse_width, top, right, top + ellipse_height ); - start.x = 0; - start.y = -1; - end.x = 1; - end.y = 0; - count += get_arc_points( dc, AD_CLOCKWISE, &rect, start, end, top_points + count ); + count += get_arc_points( dc, AD_CLOCKWISE, &rect, 0.0, -1.0, 1.0, 0.0, top_points + count );
if (count * 2 > max_points) ERR( "point count %u * 2 exceeds max points %u\n", count, max_points );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149240
Your paranoid android.
=== debian11b (64 bit WoW report) ===
d2d1: d2d1.c:10856: Test failed: Didn't expect timeout.
Huw Davies (@huw) commented about dlls/win32u/dibdrv/graphics.c:
return FALSE; }
- if (right < left)
- {
int tmp = left;
left = right;
right = tmp;
- }
- if (bottom < top)
- {
int tmp = top;
top = bottom;
bottom = tmp;
- }
It would be nice if we could use `order_rect()` for this.