These patches make a test case attached to the bug https://bugs.winehq.org/show_bug.cgi?id=33190 work.
-- v2: win32u: NtGdiExtTextOutW() should translate x,y from logical to device units at the last step. win32u: Fix device<->world width/height converters.
From: Dmitry Timoshkov dmitry@baikal.ru
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;
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/win32u/font.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index ff3a079e495..8f59c2719eb 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -5970,12 +5970,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 */ @@ -6072,8 +6066,6 @@ 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)); switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) ) { case TA_LEFT: @@ -6141,6 +6133,12 @@ BOOL WINAPI NtGdiExtTextOutW( HDC hdc, INT x, INT y, UINT flags, const RECT *lpr } }
+ 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 );
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=144017
Your paranoid android.
=== debian11b (64 bit WoW report) ===
d3dx10_34: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011C3730. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011C3AD0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011C3CA0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011C3CA0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011E3DE0.
d3dx10_35: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011C3440. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011C3440. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D1AF0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011C3440. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011959D0.
d3dx10_36: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011E3AD0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011A4A80. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011E37F0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 0000000001195B10. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011E37F0.
d3dx10_37: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011E3290. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E3290. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011C19A0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BBC10. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011C19A0.
d3dx10_38: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011E3A40. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E3A40. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011E3A40. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BBC10. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011E3A40.
d3dx10_39: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001195800. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011D1B50. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D1B50. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011B5DE0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011D5650.
d3dx10_40: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001230C40. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 0000000001230C40. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 0000000001239E20. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 0000000001195B10. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 0000000001230C40.
d3dx10_41: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011BB560. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E3CB0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011BB730. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011E3CB0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011BB560.
d3dx10_42: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001239D50. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011BE3C0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011A4A10. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 0000000001195BC0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011C3700.
d3dx10_43: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011E3D80. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E3C70. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011B5D90. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011B5F60. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011E3990.
So now `INTERNAL_XDSTOWS()` and `width_to_LP()` are the same. If this is really what we want we should unify them before changing the implementation.
Also, `hypot()` may be useful here.
New version of the patches should follow the suggestions.
Is there anything else that could be improved to make the patches accepted?
Is there any chance for a review?
The patches from this MR are included in wine-staging since 18 Oct 2024, does this qualify as an extented testing timeframe? What else is needed to get these patches reviewed?
Sorry about the delay.
It seems to me we could have some tests for this. e.g. create a font with an identity world transform, measure its metrics and some of its glyph widths, then add a transform and use the identity metrics/widths to compute the expected metrics/widths based on the new transform.
Also, if we're going to do some function renaming, could we go from e.g. INTERNAL_YDSTOWS to the vastly more readable height_to_LP rather than the other way around? Could we please do this renaming in a separate commit, so that the actual changes end up being in a smaller commit?
Thanks for the review. I considered adding some tests, however pretty soon figured out that Wine doesn't have a metrics compatible scaleable font with Windows, our Tahoma has pretty different metrics, and that makes the tests meaningless. So, instead I used a test application attached to the mentioned in the description bug report.
Using height_to_LP instead of INTERNAL_YDSTOWS sounds reasonable.
I considered adding some tests, however pretty soon figured out that Wine doesn't have a metrics compatible scaleable font with Windows, our Tahoma has pretty different metrics, and that makes the tests meaningless.
Did you try calculating the expected metrics from the metrics obtained without a world transform?
On Fri Apr 4 09:12:33 2025 +0000, Huw Davies wrote:
I considered adding some tests, however pretty soon figured out that
Wine doesn't have a metrics compatible scaleable font with Windows, our Tahoma has pretty different metrics, and that makes the tests meaningless. Did you try calculating the expected metrics from the metrics obtained without a world transform?
You mean using something like height_to_LP() in the tests? If yes, what kind of benefit would it provide to simple comparisons of expected values?
On Fri Apr 4 09:12:33 2025 +0000, Dmitry Timoshkov wrote:
You mean using something like height_to_LP() in the tests? If yes, what kind of benefit would it provide to simple comparisons of expected values?
Yes. It would allow for the variation in metrics returned by Windows / Wine in the non-transformed case and basically test that your scaling works as Windows does.
On Fri Apr 4 09:21:23 2025 +0000, Huw Davies wrote:
Yes. It would allow for the variation in metrics returned by Windows / Wine in the non-transformed case and basically test that your scaling works as Windows does.
Font scaling in Wine already works pretty much similar to Windows. The problem is with glyph positioning during rotation, and I have no idea how to test that.
On Fri Apr 4 09:32:07 2025 +0000, Dmitry Timoshkov wrote:
Font scaling in Wine already works pretty much similar to Windows. The problem is with glyph positioning during rotation, and I have no idea how to test that.
Perhaps I'm misunderstanding the problem; I wasn't asking about the glyph positions, just the font metrics and glyph widths.
On Fri Apr 4 13:43:16 2025 +0000, Huw Davies wrote:
Perhaps I'm misunderstanding the problem; I wasn't asking about the glyph positions, just the font metrics and glyph widths.
There are existing tests for outline text metrics and world transforms, and this MR shouldn't influence that. What kind of new tests would like to be added?
There are existing tests for outline text metrics and world transforms, and this MR shouldn't influence that. What kind of new tests would like to be added?
Ones that show that your proposed changes are needed.