These patches make a test case attached to the bug https://bugs.winehq.org/show_bug.cgi?id=33190 work.
-- v8: win32u: NtGdiExtTextOutW() should translate x,y from logical to device units at the last step. win32u: Fix device<->world width/height converters. win32u: Use slightly more readable names for DP/LP converters. win32u: Use correct helper for converting width to device units. gdi32/tests: Add some tests for rotated font metrics.
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/gdi32/tests/font.c | 100 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+)
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 933e061ce31..4238bcf95f0 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -22,6 +22,7 @@ #include <stdarg.h> #include <stdio.h> #include <assert.h> +#include <math.h>
#include "windef.h" #include "winbase.h" @@ -7892,6 +7893,104 @@ static void test_font_weight(void) ok(bret, "got error %ld\n", GetLastError()); }
+static void test_rotated_metrics(void) +{ + static const WCHAR str[] = L"Hello World!"; + static const struct + { + float angle_d; + POINT pt; + LONG tmHeight, tmAscent, tmDescent; + SIZE ext; + } test[] = + { + { 0.0f, {100,100}, 21,17,4, {88,21} }, + { 45.0f, {141,0}, 23,18,6, {89,23} }, + { 90.0f, {100,-100}, 21,17,4, {89,21} }, + { 180.0f, {-100,-100}, 21,17,4, {89,21} } + }; + float angle_r; + HDC hdc; + LOGFONTW lf; + HFONT hfont; + XFORM xform; + TEXTMETRICW tm; + POINT pt; + SIZE sz; + int i, off; + + hdc = CreateCompatibleDC(0); + + memset(&lf, 0, sizeof(lf)); + wcscpy(lf.lfFaceName, L"Tahoma"); + lf.lfHeight = 20; + hfont = CreateFontIndirectW(&lf); + + SetGraphicsMode(hdc, GM_ADVANCED); + SetMapMode(hdc, MM_TEXT); + + hfont = SelectObject(hdc, hfont); + + pt.x = 100; + pt.y = 100; + DPtoLP(hdc, &pt, 1); + ok(pt.x == 100, "got %ld\n", pt.x); + ok(pt.y == 100, "got %ld\n", pt.y); + + GetTextMetricsW(hdc, &tm); + ok(match_off_by_n(tm.tmHeight, 20, 1), "got %ld\n", tm.tmHeight); + ok(match_off_by_n(tm.tmAscent, 17, 1), "got %ld\n", tm.tmAscent); + ok(match_off_by_n(tm.tmDescent, 3, 0), "got %ld\n", tm.tmDescent); + + GetTextExtentPoint32W(hdc, str, wcslen(str), &sz); + ok(match_off_by_n(sz.cx, 88, 5), "got %ld\n", sz.cx); + ok(match_off_by_n(sz.cy, 20, 1), "got %ld\n", sz.cy); + + for (i = 0; i < ARRAY_SIZE(test); i++) + { + winetest_push_context("%d", i); + + angle_r = test[i].angle_d * 3.141592f / 180.0f; + + xform.eM11 = cosf(angle_r); + xform.eM12 = sinf(angle_r); + xform.eM21 = -xform.eM12; + xform.eM22 = xform.eM11; + xform.eDx = 0.0f; + xform.eDy = 0.0f; + SetWorldTransform(hdc, &xform); + + pt.x = 100; + pt.y = 100; + DPtoLP(hdc, &pt, 1); + ok(match_off_by_n(pt.x, test[i].pt.x, 1), "got pt.x %ld\n", pt.x); + ok(match_off_by_n(pt.y, test[i].pt.y, 1), "got pt.y %ld\n", pt.y); + + GetTextMetricsW(hdc, &tm); + /* Windows produces noticeable diff for angles 45.0 and 135.0 */ + off = test[i].angle_d == 45.0f ? 4 : 2; + todo_wine_if(i == 1 || i == 2) + ok(match_off_by_n(tm.tmHeight, test[i].tmHeight, off), "got %ld\n", tm.tmHeight); + todo_wine_if(i == 1 || i == 2) + ok(match_off_by_n(tm.tmAscent, test[i].tmAscent, 2), "got %ld\n", tm.tmAscent); + todo_wine_if(i == 1 || i == 2) + ok(match_off_by_n(tm.tmDescent, test[i].tmDescent, 2), "got %ld\n", tm.tmDescent); + + GetTextExtentPoint32W(hdc, str, wcslen(str), &sz); + todo_wine_if(i == 1 || i == 2) + ok(match_off_by_n(sz.cx, test[i].ext.cx, 5), "got %ld\n", sz.cx); + todo_wine_if(i == 1 || i == 2) + ok(match_off_by_n(sz.cy, test[i].ext.cy, off), "got %ld\n", sz.cy); + + winetest_pop_context(); + } + + hfont = SelectObject(hdc, hfont); + DeleteObject(hfont); + + DeleteDC(hdc); +} + START_TEST(font) { static const char *test_names[] = @@ -7913,6 +8012,7 @@ START_TEST(font) return; }
+ test_rotated_metrics(); test_stock_fonts(); test_logfont(); test_bitmap_font();
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/win32u/font.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index cddf7add9e7..c3195de98bd 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -262,6 +262,16 @@ static inline INT height_to_LP( DC *dc, INT height ) return GDI_ROUND( (double)height * fabs( dc->xformVport2World.eM22 )); }
+static inline INT INTERNAL_XWSTODS(DC *dc, INT width) +{ + POINT pt[2]; + pt[0].x = pt[0].y = 0; + pt[1].x = width; + pt[1].y = 0; + lp_to_dp(dc, pt, 2); + return pt[1].x - pt[0].x; +} + static inline INT INTERNAL_YWSTODS(DC *dc, INT height) { POINT pt[2]; @@ -5758,7 +5768,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;
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/win32u/font.c | 56 +++++++++++++--------------------------------- 1 file changed, 15 insertions(+), 41 deletions(-)
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index c3195de98bd..991ee4d04bf 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -224,32 +224,6 @@ static inline int facename_compare( const WCHAR *str1, const WCHAR *str2, SIZE_T
/* Device -> World size conversion */
-/* Performs a device to world transformation on the specified width (which - * is in integer format). - */ -static inline INT INTERNAL_XDSTOWS(DC *dc, INT width) -{ - double floatWidth; - - /* Perform operation with floating point */ - floatWidth = (double)width * dc->xformVport2World.eM11; - /* Round to integers */ - return GDI_ROUND(floatWidth); -} - -/* Performs a device to world transformation on the specified size (which - * is in integer format). - */ -static inline INT INTERNAL_YDSTOWS(DC *dc, INT height) -{ - double floatHeight; - - /* Perform operation with floating point */ - floatHeight = (double)height * dc->xformVport2World.eM22; - /* Round to integers */ - return GDI_ROUND(floatHeight); -} - /* scale width and height but don't mirror them */
static inline INT width_to_LP( DC *dc, INT width ) @@ -262,7 +236,7 @@ static inline INT height_to_LP( DC *dc, INT height ) return GDI_ROUND( (double)height * fabs( dc->xformVport2World.eM22 )); }
-static inline INT INTERNAL_XWSTODS(DC *dc, INT width) +static inline INT width_to_DP(DC *dc, INT width) { POINT pt[2]; pt[0].x = pt[0].y = 0; @@ -272,7 +246,7 @@ static inline INT INTERNAL_XWSTODS(DC *dc, INT width) return pt[1].x - pt[0].x; }
-static inline INT INTERNAL_YWSTODS(DC *dc, INT height) +static inline INT height_to_DP(DC *dc, INT height) { POINT pt[2]; pt[0].x = pt[0].y = 0; @@ -5275,7 +5249,7 @@ BOOL WINAPI NtGdiGetTextExtentExW( HDC hdc, const WCHAR *str, INT count, INT max { for (i = 0; i < count; i++) { - unsigned int dx = abs( INTERNAL_XDSTOWS( dc, pos[i] )) + + unsigned int dx = abs( width_to_LP( dc, pos[i] )) + (i + 1) * dc->attr->char_extra; if (nfit && dx > (unsigned int)max_ext) break; if (dxs) dxs[i] = dx; @@ -5283,8 +5257,8 @@ BOOL WINAPI NtGdiGetTextExtentExW( HDC hdc, const WCHAR *str, INT count, INT max if (nfit) *nfit = i; }
- size->cx = abs( INTERNAL_XDSTOWS( dc, size->cx )) + count * dc->attr->char_extra; - size->cy = abs( INTERNAL_YDSTOWS( dc, size->cy )); + size->cx = abs( width_to_LP( dc, size->cx )) + count * dc->attr->char_extra; + size->cy = abs( height_to_LP( dc, size->cy )); }
if (pos != buffer && pos != dxs) free( pos ); @@ -5388,16 +5362,16 @@ UINT WINAPI NtGdiGetOutlineTextMetricsInternalW( HDC hdc, UINT cbData, 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->otmLineGap = INTERNAL_YDSTOWS(dc, output->otmLineGap); - output->otmsCapEmHeight = INTERNAL_YDSTOWS(dc, output->otmsCapEmHeight); - output->otmsXHeight = INTERNAL_YDSTOWS(dc, output->otmsXHeight); + output->otmLineGap = height_to_LP(dc, output->otmLineGap); + output->otmsCapEmHeight = height_to_LP(dc, output->otmsCapEmHeight); + output->otmsXHeight = height_to_LP(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->otmMacLineGap = INTERNAL_YDSTOWS(dc, output->otmMacLineGap); + output->otmMacLineGap = height_to_LP(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); @@ -5406,7 +5380,7 @@ UINT WINAPI NtGdiGetOutlineTextMetricsInternalW( HDC hdc, UINT cbData, 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->otmsStrikeoutSize = INTERNAL_YDSTOWS(dc, output->otmsStrikeoutSize); + output->otmsStrikeoutSize = height_to_LP(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); @@ -5768,7 +5742,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_XWSTODS( dc, metric_size )); + int width = abs( width_to_DP( dc, metric_size )); if (width == 0) width = 1; if (metric_size < 0) width = -width; return width; @@ -5999,8 +5973,8 @@ BOOL WINAPI NtGdiExtTextOutW( HDC hdc, INT x, INT y, UINT flags, const RECT *lpr width = desired[1]; }
- tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent)); - tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent)); + tm.tmAscent = abs(height_to_DP(dc, tm.tmAscent)); + tm.tmDescent = abs(height_to_DP(dc, tm.tmDescent)); switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) ) { case TA_LEFT: @@ -6097,10 +6071,10 @@ done: { otm = malloc( size ); NtGdiGetOutlineTextMetricsInternalW( hdc, size, otm, 0 ); - underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition )); + underlinePos = abs( height_to_DP( dc, otm->otmsUnderscorePosition )); if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos; underlineWidth = get_line_width( dc, otm->otmsUnderscoreSize ); - strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition )); + strikeoutPos = abs( height_to_DP( dc, otm->otmsStrikeoutPosition )); if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos; strikeoutWidth = get_line_width( dc, otm->otmsStrikeoutSize ); free( otm );
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/gdi32/tests/font.c | 5 ----- dlls/win32u/font.c | 38 ++++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 23 deletions(-)
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 4238bcf95f0..e3918e2b52f 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -7969,17 +7969,12 @@ static void test_rotated_metrics(void) GetTextMetricsW(hdc, &tm); /* Windows produces noticeable diff for angles 45.0 and 135.0 */ off = test[i].angle_d == 45.0f ? 4 : 2; - todo_wine_if(i == 1 || i == 2) ok(match_off_by_n(tm.tmHeight, test[i].tmHeight, off), "got %ld\n", tm.tmHeight); - todo_wine_if(i == 1 || i == 2) ok(match_off_by_n(tm.tmAscent, test[i].tmAscent, 2), "got %ld\n", tm.tmAscent); - todo_wine_if(i == 1 || i == 2) ok(match_off_by_n(tm.tmDescent, test[i].tmDescent, 2), "got %ld\n", tm.tmDescent);
GetTextExtentPoint32W(hdc, str, wcslen(str), &sz); - todo_wine_if(i == 1 || i == 2) ok(match_off_by_n(sz.cx, test[i].ext.cx, 5), "got %ld\n", sz.cx); - todo_wine_if(i == 1 || i == 2) ok(match_off_by_n(sz.cy, test[i].ext.cy, off), "got %ld\n", sz.cy);
winetest_pop_context(); diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 991ee4d04bf..11ff289bee0 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -228,32 +228,34 @@ static inline int facename_compare( const WCHAR *str1, const WCHAR *str2, SIZE_T
static inline INT width_to_LP( DC *dc, INT width ) { - return GDI_ROUND( (double)width * fabs( dc->xformVport2World.eM11 )); + float scale_x; + + scale_x = hypotf( dc->xformWorld2Vport.eM11, dc->xformWorld2Vport.eM12 ); + return GDI_ROUND( (float)width / scale_x ); }
static inline INT height_to_LP( DC *dc, INT height ) { - return GDI_ROUND( (double)height * fabs( dc->xformVport2World.eM22 )); + float scale_y; + + scale_y = hypotf( dc->xformWorld2Vport.eM21, dc->xformWorld2Vport.eM22 ); + return GDI_ROUND( (float)height / scale_y ); }
static inline INT width_to_DP(DC *dc, INT width) { - POINT pt[2]; - pt[0].x = pt[0].y = 0; - pt[1].x = width; - pt[1].y = 0; - lp_to_dp(dc, pt, 2); - return pt[1].x - pt[0].x; + float scale_x; + + scale_x = hypotf( dc->xformWorld2Vport.eM11, dc->xformWorld2Vport.eM12 ); + return GDI_ROUND( (float)width * scale_x ); }
static inline INT height_to_DP(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 ); @@ -4104,8 +4106,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)) @@ -4319,8 +4321,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)
From: Dmitry Timoshkov dmitry@baikal.ru
Bug: https://bugs.winehq.org/show_bug.cgi?id=33190
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/win32u/font.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 11ff289bee0..e1dba2e3dc0 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -5873,12 +5873,6 @@ BOOL WINAPI NtGdiExtTextOutW( HDC hdc, INT x, INT y, UINT flags, const RECT *lpr goto done; }
- pt.x = x; - pt.y = y; - lp_to_dp(dc, &pt, 1); - x = pt.x; - y = pt.y; - char_extra = dc->attr->char_extra; if (char_extra && lpDx && NtGdiGetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER) char_extra = 0; /* Printer drivers don't add char_extra if lpDx is supplied */ @@ -5975,8 +5969,6 @@ BOOL WINAPI NtGdiExtTextOutW( HDC hdc, INT x, INT y, UINT flags, const RECT *lpr width = desired[1]; }
- tm.tmAscent = abs(height_to_DP(dc, tm.tmAscent)); - tm.tmDescent = abs(height_to_DP(dc, tm.tmDescent)); switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) ) { case TA_LEFT: @@ -6038,12 +6030,19 @@ BOOL WINAPI NtGdiExtTextOutW( HDC hdc, INT x, INT y, UINT flags, const RECT *lpr text_box.bottom = y + tm.tmDescent;
if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc ); + lp_to_dp(dc, (POINT *)&text_box, 2); if (!IsRectEmpty( &text_box )) physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL ); } } }
+ pt.x = x; + pt.y = y; + lp_to_dp(dc, &pt, 1); + x = pt.x; + y = pt.y; + ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc, str, count, (INT*)deltas );
On Fri Jun 27 15:36:27 2025 +0000, Dmitry Timoshkov wrote:
And we should take into account that font metrics for Wine and Windows versions of Tahoma couldn't match precisely, so a match within 1-2 pixels is not really possible.
Does new version of the patches look better? Pretty large margin (5) for string cx extent is necessary to mitigate difference of Tahoma font metrics between Wine and Windows, and should be expected for longer strings.
It's probably worth to add a couple of notes: 1. If I use tahoma.ttf from Windows I get almost identical results between Windows and Wine. 'Almost' is because Windows produces more visible errors (+2/-2) for a rotated font while under Wine I get practically the same results for all angles. 2. A test case attached to the bug https://bugs.winehq.org/show_bug.cgi?id=33190 works and displays rotated text identical to what I see under Windows.
Huw, could you please have a look at this MR once again?
We have some custom fonts already in gdi32 tests. Could we perhaps use one of those instead of Tahoma?
On Tue Sep 16 18:49:46 2025 +0000, Elizabeth Figura wrote:
We have some custom fonts already in gdi32 tests. Could we perhaps use one of those instead of Tahoma?
I guess you mean to make tests less depend on Windows vs Wine font metrics difference? Sure, we could. That won't help much I'm afraid, in my testing I dropped exactly same Windows fonts to Wine prefix and even that produced pretty large differences in 135 degrees, so that I removed 135 degrees from test data. That made the tests in current version of the patch have very little difference between Wine and Windows, and that shouldn't be a problem anymore.
On Tue Sep 16 18:49:46 2025 +0000, Dmitry Timoshkov wrote:
I guess you mean to make tests less depend on Windows vs Wine font metrics difference? Sure, we could. That won't help much I'm afraid, in my testing I dropped exactly same Windows fonts to Wine prefix and even that produced pretty large differences in 135 degrees, so that I removed 135 degrees from test data. That made the tests in current version of the patch have very little difference between Wine and Windows, and that shouldn't be a problem anymore.
If there's a difference, doesn't that mean there's something wrong with this implementation?
On Tue Sep 16 19:09:38 2025 +0000, Elizabeth Figura wrote:
If there's a difference, doesn't that mean there's something wrong with this implementation?
As I explained in earlier comments the difference is caused by pretty bad accuracy for rotated metrics under Windows, probably because it doesn't use floating point math for calculations.
On Tue Sep 16 19:15:48 2025 +0000, Dmitry Timoshkov wrote:
As I explained in earlier comments the difference is caused by pretty bad accuracy for rotated metrics under Windows, probably because it doesn't use floating point math for calculations.
Okay, I guess I was thrown off by your earlier saying it was "almost identical", but in that later comment "pretty large differences".
probably because it doesn't use floating point math for calculations.
Maybe we shouldn't either, then?
On Tue Sep 16 19:39:42 2025 +0000, Elizabeth Figura wrote:
Okay, I guess I was thrown off by your earlier saying it was "almost identical", but in that later comment "pretty large differences".
probably because it doesn't use floating point math for calculations.
Maybe we shouldn't either, then?
We do use floating point to scale font metrics everywhere in gdi32/win32u, why should we stop doing that and make scaling results worse just because rotated font metrics scaling is bad in Windows? The test application attached to https://bugs.winehq.org/show_bug.cgi?id=33190 demonstrates that rotated fonts match pretty closely in Windows and Wine, probably that could be a better measure of the patch quality? Besides, I have a real world application that uses rotated fonts and rotated text in it looks pretty good, and matches what I observe under Windows.
On Tue Sep 16 19:53:02 2025 +0000, Dmitry Timoshkov wrote:
We do use floating point to scale font metrics everywhere in gdi32/win32u, why should we stop doing that and make scaling results worse just because rotated font metrics scaling is bad in Windows? The test application attached to https://bugs.winehq.org/show_bug.cgi?id=33190 demonstrates that rotated fonts match pretty closely in Windows and Wine, probably that could be a better measure of the patch quality? Besides, I have a real world application that uses rotated fonts and rotated text in it looks pretty good, and matches what I observe under Windows.
I don't know, sometimes matching Windows is seen as a good thing. I'm just trying to propose anything that might help this make progress.
On Tue Sep 16 20:58:50 2025 +0000, Elizabeth Figura wrote:
I don't know, sometimes matching Windows is seen as a good thing. I'm just trying to propose anything that might help this make progress.
I understand and appreciate it very much, thank you for your help. As I see current situation is that existing code uses floating point math but doesn't support font metrics and coordinate rotation, new code keeps using floating point math and adds support for correct calculations of rotated font metrics and coordinates however this doesn't fully match Windows results because under Windows the results are much more coarse. Doesn't that look like an improvement?