[PATCH] gdi32: Clamp unsigned integers to 32-bit range when scaling fonts
Alex Henrie
alexhenrie24 at gmail.com
Mon Dec 11 23:10:48 CST 2017
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
Fixes test crash (floating point exception due to double value outside
of integer range) with TAMu_Kadampari.ttf from Arch Linux's
ttf-indic-otf package. sTypoLineGap is -194 in this font, and Windows 10
sets otmLineGap to 4294967295.
Also fixes the crash with GohaTibebZemen.otf from Arch's xorg-fonts-misc
package. sCapHeight and sxHeight are -32768 in this font, and Windows 10
refuses to install it. However, Windows XP installs the font without
complaint and sets otmsCapEmHeight and otmsXHeight to 4294966903. I
think the 0.00000009% difference from UINT_MAX is just rounding error.
---
dlls/gdi32/freetype.c | 11 ++++++-----
dlls/gdi32/gdi_private.h | 7 +++++++
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 7c5a7ef979..961f9e5f03 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -7578,19 +7578,20 @@ static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *
#define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
#define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
+#define SCALE_YU(y) (y) = GDI_ROUND_UINT((double)(y) * (scale_y))
SCALE_Y(potm->otmAscent);
SCALE_Y(potm->otmDescent);
- SCALE_Y(potm->otmLineGap);
- SCALE_Y(potm->otmsCapEmHeight);
- SCALE_Y(potm->otmsXHeight);
+ SCALE_YU(potm->otmLineGap);
+ SCALE_YU(potm->otmsCapEmHeight);
+ SCALE_YU(potm->otmsXHeight);
SCALE_Y(potm->otmrcFontBox.top);
SCALE_Y(potm->otmrcFontBox.bottom);
SCALE_X(potm->otmrcFontBox.left);
SCALE_X(potm->otmrcFontBox.right);
SCALE_Y(potm->otmMacAscent);
SCALE_Y(potm->otmMacDescent);
- SCALE_Y(potm->otmMacLineGap);
+ SCALE_YU(potm->otmMacLineGap);
SCALE_X(potm->otmptSubscriptSize.x);
SCALE_Y(potm->otmptSubscriptSize.y);
SCALE_X(potm->otmptSubscriptOffset.x);
@@ -7599,7 +7600,7 @@ static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *
SCALE_Y(potm->otmptSuperscriptSize.y);
SCALE_X(potm->otmptSuperscriptOffset.x);
SCALE_Y(potm->otmptSuperscriptOffset.y);
- SCALE_Y(potm->otmsStrikeoutSize);
+ SCALE_YU(potm->otmsStrikeoutSize);
SCALE_Y(potm->otmsStrikeoutPosition);
SCALE_Y(potm->otmsUnderscoreSize);
SCALE_Y(potm->otmsUnderscorePosition);
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 4236aa3690..c591057e3a 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -141,6 +141,13 @@ static inline INT GDI_ROUND(double val)
return (int)floor(val + 0.5);
}
+static inline UINT GDI_ROUND_UINT(double val)
+{
+ double ret = floor(val + 0.5);
+ if (ret > UINT_MAX) return UINT_MAX;
+ return (UINT)ret;
+}
+
#define GET_DC_PHYSDEV(dc,func) \
get_physdev_entry_point( (dc)->physDev, FIELD_OFFSET(struct gdi_dc_funcs,func))
--
2.15.1
More information about the wine-devel
mailing list