Commit 58b477d1 authored by Zhiyi Zhang's avatar Zhiyi Zhang Committed by Alexandre Julliard

win32u: Choose a smaller ppem to avoid exceeding the requested font height.

When height > 0, CreateFontA/W() should not return a font face exceeding the requested height. For instance, Tahoma has 2049 units of ascent, 423 units of descent and its units per EM square is 2048. When requesting a font 20 pixels in height, ppem = units_per_EM * requested_height / (ascent + descent) = 2048 * 20 / (2049 + 423) = 16.57 ~= 17. When getting the resulting height back from the ppem, resulting_height = (ascent + descent) * ppem / units_per_EM = (2049.0 + 423) * 17 / 2048 = 20.52 ~=21. So it ends up getting a larger font than requested and violates the spec. Fix Nancy Drew: Legend of the Crystal Skull crash at start. Signed-off-by: 's avatarZhiyi Zhang <zzhang@codeweavers.com>
parent 821b36e0
...@@ -4124,7 +4124,6 @@ static void test_GetTextMetrics(void) ...@@ -4124,7 +4124,6 @@ static void test_GetTextMetrics(void)
old_hf = SelectObject(hdc, hf); old_hf = SelectObject(hdc, hf);
ret = GetTextMetricsA(hdc, &tm); ret = GetTextMetricsA(hdc, &tm);
ok(ret, "GetTextMetricsA failed, error %lu\n", GetLastError()); ok(ret, "GetTextMetricsA failed, error %lu\n", GetLastError());
todo_wine
ok(tm.tmHeight <= 20, "Got unexpected tmHeight %ld\n", tm.tmHeight); ok(tm.tmHeight <= 20, "Got unexpected tmHeight %ld\n", tm.tmHeight);
SelectObject(hdc, old_hf); SelectObject(hdc, old_hf);
DeleteObject(hf); DeleteObject(hf);
......
...@@ -1927,10 +1927,18 @@ static LONG calc_ppem_for_height(FT_Face ft_face, LONG height) ...@@ -1927,10 +1927,18 @@ static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
if(height > 0) { if(height > 0) {
USHORT windescent = get_fixed_windescent(pOS2->usWinDescent); USHORT windescent = get_fixed_windescent(pOS2->usWinDescent);
LONG units;
if(pOS2->usWinAscent + windescent == 0) if(pOS2->usWinAscent + windescent == 0)
ppem = pFT_MulDiv(ft_face->units_per_EM, height, pHori->Ascender - pHori->Descender); units = pHori->Ascender - pHori->Descender;
else else
ppem = pFT_MulDiv(ft_face->units_per_EM, height, pOS2->usWinAscent + windescent); units = pOS2->usWinAscent + windescent;
ppem = pFT_MulDiv(ft_face->units_per_EM, height, units);
/* If rounding ends up getting a font exceeding height, choose a smaller ppem */
if(ppem > 1 && pFT_MulDiv(units, ppem, ft_face->units_per_EM) > height)
--ppem;
if(ppem > MAX_PPEM) { if(ppem > MAX_PPEM) {
WARN("Ignoring too large height %d, ppem %d\n", height, ppem); WARN("Ignoring too large height %d, ppem %d\n", height, ppem);
ppem = 1; ppem = 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment