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?