File 0001-win32u-Fix-device-world-width-height-converters.patch of Package wine

From 6c8f9f119c7d57e564bccafc1e051e050ab327d6 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 7 Feb 2024 19:14:29 +0300
Subject: [PATCH 1/2] win32u: Fix device<->world width/height converters.

See https://gitlab.winehq.org/wine/wine/-/merge_requests/5068

Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
---
 dlls/win32u/font.c | 130 +++++++++++++++++++++------------------------
 1 file changed, 60 insertions(+), 70 deletions(-)

diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c
index 26518d285d9..ff3a079e495 100644
--- a/dlls/win32u/font.c
+++ b/dlls/win32u/font.c
@@ -228,12 +228,10 @@ static inline int facename_compare( const WCHAR *str1, const WCHAR *str2, SIZE_T
  */
 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
 {
-    double floatWidth;
+    float scale_x;
 
-    /* Perform operation with floating point */
-    floatWidth = (double)width * dc->xformVport2World.eM11;
-    /* Round to integers */
-    return GDI_ROUND(floatWidth);
+    scale_x = hypotf(dc->xformWorld2Vport.eM11, dc->xformWorld2Vport.eM12);
+    return GDI_ROUND( (float)width / scale_x );
 }
 
 /* Performs a device to world transformation on the specified size (which
@@ -241,34 +239,26 @@ static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
  */
 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
 {
-    double floatHeight;
+    float scale_y;
 
-    /* Perform operation with floating point */
-    floatHeight = (double)height * dc->xformVport2World.eM22;
-    /* Round to integers */
-    return GDI_ROUND(floatHeight);
+    scale_y = hypotf(dc->xformWorld2Vport.eM21, dc->xformWorld2Vport.eM22);
+    return GDI_ROUND( (float)height / scale_y );
 }
 
-/* scale width and height but don't mirror them */
-
-static inline INT width_to_LP( DC *dc, INT width )
+static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
 {
-    return GDI_ROUND( (double)width * fabs( dc->xformVport2World.eM11 ));
-}
+    float scale_x;
 
-static inline INT height_to_LP( DC *dc, INT height )
-{
-    return GDI_ROUND( (double)height * fabs( dc->xformVport2World.eM22 ));
+    scale_x = hypotf(dc->xformWorld2Vport.eM11, dc->xformWorld2Vport.eM12);
+    return GDI_ROUND( (float)width / scale_x );
 }
 
 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
 {
-    POINT pt[2];
-    pt[0].x = pt[0].y = 0;
-    pt[1].x = 0;
-    pt[1].y = height;
-    lp_to_dp(dc, pt, 2);
-    return pt[1].y - pt[0].y;
+    float scale_y;
+
+    scale_y = hypotf(dc->xformWorld2Vport.eM21, dc->xformWorld2Vport.eM22);
+    return GDI_ROUND( (float)height / scale_y );
 }
 
 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
@@ -4208,8 +4198,8 @@ static void scale_outline_font_metrics( const struct gdi_font *font, OUTLINETEXT
     else
         scale_x = font->scale_y;
 
-    scale_x *= fabs(font->matrix.eM11);
-    scale_y = font->scale_y * fabs(font->matrix.eM22);
+    scale_x *= hypotf(font->matrix.eM11, font->matrix.eM12);
+    scale_y = font->scale_y * hypotf(font->matrix.eM21, font->matrix.eM22);
 
 /* Windows scales these values as signed integers even if they are unsigned */
 #define SCALE_X(x) (x) = GDI_ROUND((int)(x) * (scale_x))
@@ -4423,8 +4413,8 @@ static void scale_font_metrics( struct gdi_font *font, TEXTMETRICW *tm )
     else
         scale_x = font->scale_y;
 
-    scale_x *= fabs(font->matrix.eM11);
-    scale_y = font->scale_y * fabs(font->matrix.eM22);
+    scale_x *= hypotf(font->matrix.eM11, font->matrix.eM12);
+    scale_y = font->scale_y * hypotf(font->matrix.eM21, font->matrix.eM22);
 
 #define SCALE_X(x) (x) = GDI_ROUND((x) * scale_x)
 #define SCALE_Y(y) (y) = GDI_ROUND((y) * scale_y)
@@ -5398,14 +5388,14 @@ BOOL WINAPI NtGdiGetTextMetricsW( HDC hdc, TEXTMETRICW *metrics, ULONG flags )
 
         metrics->tmDigitizedAspectX = NtGdiGetDeviceCaps(hdc, LOGPIXELSX);
         metrics->tmDigitizedAspectY = NtGdiGetDeviceCaps(hdc, LOGPIXELSY);
-        metrics->tmHeight           = height_to_LP( dc, metrics->tmHeight );
-        metrics->tmAscent           = height_to_LP( dc, metrics->tmAscent );
-        metrics->tmDescent          = height_to_LP( dc, metrics->tmDescent );
-        metrics->tmInternalLeading  = height_to_LP( dc, metrics->tmInternalLeading );
-        metrics->tmExternalLeading  = height_to_LP( dc, metrics->tmExternalLeading );
-        metrics->tmAveCharWidth     = width_to_LP( dc, metrics->tmAveCharWidth );
-        metrics->tmMaxCharWidth     = width_to_LP( dc, metrics->tmMaxCharWidth );
-        metrics->tmOverhang         = width_to_LP( dc, metrics->tmOverhang );
+        metrics->tmHeight           = INTERNAL_YDSTOWS( dc, metrics->tmHeight );
+        metrics->tmAscent           = INTERNAL_YDSTOWS( dc, metrics->tmAscent );
+        metrics->tmDescent          = INTERNAL_YDSTOWS( dc, metrics->tmDescent );
+        metrics->tmInternalLeading  = INTERNAL_YDSTOWS( dc, metrics->tmInternalLeading );
+        metrics->tmExternalLeading  = INTERNAL_YDSTOWS( dc, metrics->tmExternalLeading );
+        metrics->tmAveCharWidth     = INTERNAL_XDSTOWS( dc, metrics->tmAveCharWidth );
+        metrics->tmMaxCharWidth     = INTERNAL_XDSTOWS( dc, metrics->tmMaxCharWidth );
+        metrics->tmOverhang         = INTERNAL_XDSTOWS( dc, metrics->tmOverhang );
         ret = TRUE;
 
         TRACE("text metrics:\n"
@@ -5461,38 +5451,38 @@ UINT WINAPI NtGdiGetOutlineTextMetricsInternalW( HDC hdc, UINT cbData,
     {
         output->otmTextMetrics.tmDigitizedAspectX = NtGdiGetDeviceCaps(hdc, LOGPIXELSX);
         output->otmTextMetrics.tmDigitizedAspectY = NtGdiGetDeviceCaps(hdc, LOGPIXELSY);
-        output->otmTextMetrics.tmHeight           = height_to_LP( dc, output->otmTextMetrics.tmHeight );
-        output->otmTextMetrics.tmAscent           = height_to_LP( dc, output->otmTextMetrics.tmAscent );
-        output->otmTextMetrics.tmDescent          = height_to_LP( dc, output->otmTextMetrics.tmDescent );
-        output->otmTextMetrics.tmInternalLeading  = height_to_LP( dc, output->otmTextMetrics.tmInternalLeading );
-        output->otmTextMetrics.tmExternalLeading  = height_to_LP( dc, output->otmTextMetrics.tmExternalLeading );
-        output->otmTextMetrics.tmAveCharWidth     = width_to_LP( dc, output->otmTextMetrics.tmAveCharWidth );
-        output->otmTextMetrics.tmMaxCharWidth     = width_to_LP( dc, output->otmTextMetrics.tmMaxCharWidth );
-        output->otmTextMetrics.tmOverhang         = width_to_LP( dc, output->otmTextMetrics.tmOverhang );
-        output->otmAscent                = height_to_LP( dc, output->otmAscent);
-        output->otmDescent               = height_to_LP( dc, output->otmDescent);
+        output->otmTextMetrics.tmHeight           = INTERNAL_YDSTOWS( dc, output->otmTextMetrics.tmHeight );
+        output->otmTextMetrics.tmAscent           = INTERNAL_YDSTOWS( dc, output->otmTextMetrics.tmAscent );
+        output->otmTextMetrics.tmDescent          = INTERNAL_YDSTOWS( dc, output->otmTextMetrics.tmDescent );
+        output->otmTextMetrics.tmInternalLeading  = INTERNAL_YDSTOWS( dc, output->otmTextMetrics.tmInternalLeading );
+        output->otmTextMetrics.tmExternalLeading  = INTERNAL_YDSTOWS( dc, output->otmTextMetrics.tmExternalLeading );
+        output->otmTextMetrics.tmAveCharWidth     = INTERNAL_XDSTOWS( dc, output->otmTextMetrics.tmAveCharWidth );
+        output->otmTextMetrics.tmMaxCharWidth     = INTERNAL_XDSTOWS( dc, output->otmTextMetrics.tmMaxCharWidth );
+        output->otmTextMetrics.tmOverhang         = INTERNAL_XDSTOWS( dc, output->otmTextMetrics.tmOverhang );
+        output->otmAscent                = INTERNAL_YDSTOWS( dc, output->otmAscent);
+        output->otmDescent               = INTERNAL_YDSTOWS( dc, output->otmDescent);
         output->otmLineGap               = INTERNAL_YDSTOWS(dc, output->otmLineGap);
         output->otmsCapEmHeight          = INTERNAL_YDSTOWS(dc, output->otmsCapEmHeight);
         output->otmsXHeight              = INTERNAL_YDSTOWS(dc, output->otmsXHeight);
-        output->otmrcFontBox.top         = height_to_LP( dc, output->otmrcFontBox.top);
-        output->otmrcFontBox.bottom      = height_to_LP( dc, output->otmrcFontBox.bottom);
-        output->otmrcFontBox.left        = width_to_LP( dc, output->otmrcFontBox.left);
-        output->otmrcFontBox.right       = width_to_LP( dc, output->otmrcFontBox.right);
-        output->otmMacAscent             = height_to_LP( dc, output->otmMacAscent);
-        output->otmMacDescent            = height_to_LP( dc, output->otmMacDescent);
+        output->otmrcFontBox.top         = INTERNAL_YDSTOWS( dc, output->otmrcFontBox.top);
+        output->otmrcFontBox.bottom      = INTERNAL_YDSTOWS( dc, output->otmrcFontBox.bottom);
+        output->otmrcFontBox.left        = INTERNAL_XDSTOWS( dc, output->otmrcFontBox.left);
+        output->otmrcFontBox.right       = INTERNAL_XDSTOWS( dc, output->otmrcFontBox.right);
+        output->otmMacAscent             = INTERNAL_YDSTOWS( dc, output->otmMacAscent);
+        output->otmMacDescent            = INTERNAL_YDSTOWS( dc, output->otmMacDescent);
         output->otmMacLineGap            = INTERNAL_YDSTOWS(dc, output->otmMacLineGap);
-        output->otmptSubscriptSize.x     = width_to_LP( dc, output->otmptSubscriptSize.x);
-        output->otmptSubscriptSize.y     = height_to_LP( dc, output->otmptSubscriptSize.y);
-        output->otmptSubscriptOffset.x   = width_to_LP( dc, output->otmptSubscriptOffset.x);
-        output->otmptSubscriptOffset.y   = height_to_LP( dc, output->otmptSubscriptOffset.y);
-        output->otmptSuperscriptSize.x   = width_to_LP( dc, output->otmptSuperscriptSize.x);
-        output->otmptSuperscriptSize.y   = height_to_LP( dc, output->otmptSuperscriptSize.y);
-        output->otmptSuperscriptOffset.x = width_to_LP( dc, output->otmptSuperscriptOffset.x);
-        output->otmptSuperscriptOffset.y = height_to_LP( dc, output->otmptSuperscriptOffset.y);
+        output->otmptSubscriptSize.x     = INTERNAL_XDSTOWS( dc, output->otmptSubscriptSize.x);
+        output->otmptSubscriptSize.y     = INTERNAL_YDSTOWS( dc, output->otmptSubscriptSize.y);
+        output->otmptSubscriptOffset.x   = INTERNAL_XDSTOWS( dc, output->otmptSubscriptOffset.x);
+        output->otmptSubscriptOffset.y   = INTERNAL_YDSTOWS( dc, output->otmptSubscriptOffset.y);
+        output->otmptSuperscriptSize.x   = INTERNAL_XDSTOWS( dc, output->otmptSuperscriptSize.x);
+        output->otmptSuperscriptSize.y   = INTERNAL_YDSTOWS( dc, output->otmptSuperscriptSize.y);
+        output->otmptSuperscriptOffset.x = INTERNAL_XDSTOWS( dc, output->otmptSuperscriptOffset.x);
+        output->otmptSuperscriptOffset.y = INTERNAL_YDSTOWS( dc, output->otmptSuperscriptOffset.y);
         output->otmsStrikeoutSize        = INTERNAL_YDSTOWS(dc, output->otmsStrikeoutSize);
-        output->otmsStrikeoutPosition    = height_to_LP( dc, output->otmsStrikeoutPosition);
-        output->otmsUnderscoreSize       = height_to_LP( dc, output->otmsUnderscoreSize);
-        output->otmsUnderscorePosition   = height_to_LP( dc, output->otmsUnderscorePosition);
+        output->otmsStrikeoutPosition    = INTERNAL_YDSTOWS( dc, output->otmsStrikeoutPosition);
+        output->otmsUnderscoreSize       = INTERNAL_YDSTOWS( dc, output->otmsUnderscoreSize);
+        output->otmsUnderscorePosition   = INTERNAL_YDSTOWS( dc, output->otmsUnderscorePosition);
 
         if(output != lpOTM)
         {
@@ -5552,7 +5542,7 @@ BOOL WINAPI NtGdiGetCharWidthW( HDC hdc, UINT first, UINT last, WCHAR *chars,
             INT *buffer = buf;
             /* convert device units to logical */
             for (i = 0; i < count; i++)
-                buffer[i] = width_to_LP( dc, buffer[i] );
+                buffer[i] = INTERNAL_XDSTOWS( dc, buffer[i] );
         }
         else
         {
@@ -5851,7 +5841,7 @@ BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect
  */
 static inline int get_line_width( DC *dc, int metric_size )
 {
-    int width = abs( INTERNAL_YWSTODS( dc, metric_size ));
+    int width = abs( INTERNAL_XWSTODS( dc, metric_size ));
     if (width == 0) width = 1;
     if (metric_size < 0) width = -width;
     return width;
@@ -6285,9 +6275,9 @@ BOOL WINAPI NtGdiGetCharABCWidthsW( HDC hdc, UINT first, UINT last, WCHAR *chars
             /* convert device units to logical */
             for (i = 0; i < count; i++)
             {
-                abc[i].abcA = width_to_LP( dc, abc[i].abcA );
-                abc[i].abcB = width_to_LP( dc, abc[i].abcB );
-                abc[i].abcC = width_to_LP( dc, abc[i].abcC );
+                abc[i].abcA = INTERNAL_XDSTOWS( dc, abc[i].abcA );
+                abc[i].abcB = INTERNAL_XDSTOWS( dc, abc[i].abcB );
+                abc[i].abcC = INTERNAL_XDSTOWS( dc, abc[i].abcC );
             }
         }
         else
@@ -7076,8 +7066,8 @@ BOOL WINAPI NtGdiGetCharWidthInfo( HDC hdc, struct char_width_info *info )
 
     if (ret)
     {
-        info->lsb = width_to_LP( dc, info->lsb );
-        info->rsb = width_to_LP( dc, info->rsb );
+        info->lsb = INTERNAL_XDSTOWS( dc, info->lsb );
+        info->rsb = INTERNAL_XDSTOWS( dc, info->rsb );
     }
     release_dc_ptr(dc);
     return ret;
-- 
2.45.2

openSUSE Build Service is sponsored by