[PATCH] d2d1: Strip translation from transform when scaling arc radii.
d2d_arc_transform() applies the same affine matrix to the arc's end point and to its two radius vectors (width, 0) and (0, height). That is correct for the end point (a position) but wrong for the radii (direction vectors): when the matrix includes a non-zero translation (_31, _32), the transformed radius vector becomes (width * _11 + _31, width * _12 + _32) and the resulting d2d_point_length() returns sqrt((width*_11 + _31)^2 + (width*_12 + _32)^2) instead of the intended sqrt((width*_11)^2 + (width*_12)^2) = width * sqrt(_11^2 + _12^2) i.e. the magnitude of the linear part only. Visible whenever a path that contains an arc is wrapped in a transformed geometry whose transform has both a non-trivial linear part and a translation — common for plugin host UIs with offset rendering. Fix: build a local copy of the matrix with _31 = _32 = 0 and use it for the radius transforms. Keep the original transform for the end point. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59718 Signed-off-by: Giang Nguyen <nen24t@gmail.com> --- dlls/d2d1/geometry.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index 68de4c2193c..eda79d35e2b 100644 --- a/dlls/d2d1/geometry.c +++ b/dlls/d2d1/geometry.c @@ -4479,12 +4479,19 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Open(ID2D1PathGeometry1 *ifac static inline void d2d_arc_transform(D2D1_ARC_SEGMENT *arc, const D2D1_MATRIX_3X2_F *transform) { + D2D1_MATRIX_3X2_F linear = *transform; D2D_POINT_2F point; + /* Radii are direction vectors, so they should be transformed with the + * linear part of the matrix only. Including the translation would add + * (_31, _32) to (width, 0) and (0, height) and yield incorrect lengths. */ + linear._31 = 0.0f; + linear._32 = 0.0f; + d2d_point_transform(&arc->point, transform, arc->point.x, arc->point.y); - d2d_point_transform(&point, transform, arc->size.width, 0.0f); + d2d_point_transform(&point, &linear, arc->size.width, 0.0f); arc->size.width = d2d_point_length(&point); - d2d_point_transform(&point, transform, 0.0f, arc->size.height); + d2d_point_transform(&point, &linear, 0.0f, arc->size.height); arc->size.height = d2d_point_length(&point); } -- 2.43.0
participants (1)
-
Giang Nguyen