diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index de50bf0de42..fd03580a754 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -2685,7 +2685,9 @@ static UINT get_font_type( const NEWTEXTMETRICEXW *ntm ) static BOOL get_face_enum_data( struct gdi_font_face *face, ENUMLOGFONTEXW *elf, NEWTEXTMETRICEXW *ntm ) { struct gdi_font *font; - LOGFONTW lf = { .lfHeight = 100 }; + LOGFONTW lf = { .lfHeight = -4096 /* preferable EM Square size */ }; + + if (!face->scalable) lf.lfHeight = 0; if (!(font = create_gdi_font( face, NULL, &lf ))) return FALSE; @@ -2695,12 +2697,42 @@ static BOOL get_face_enum_data( struct gdi_font_face *face, ENUMLOGFONTEXW *elf, return FALSE; } + if (font->scalable && -lf.lfHeight % font->otm.otmEMSquare != 0) + { + /* reload with the original EM Square size */ + lf.lfHeight = -font->otm.otmEMSquare; + free_gdi_font( font ); + + if (!(font = create_gdi_font( face, NULL, &lf ))) return FALSE; + if (!font_funcs->load_font( font )) + { + free_gdi_font( font ); + return FALSE; + } + } + if (font_funcs->set_outline_text_metrics( font )) { - memcpy( &ntm->ntmTm, &font->otm.otmTextMetrics, sizeof(TEXTMETRICW) ); + static const DWORD ntm_ppem = 32; + +#define TM font->otm.otmTextMetrics +#define SCALE_NTM(value) (MulDiv( ntm->ntmTm.tmHeight, (value), TM.tmHeight )) + ntm->ntmTm.tmHeight = MulDiv( ntm_ppem, font->ntmCellHeight, font->otm.otmEMSquare ); + ntm->ntmTm.tmAscent = SCALE_NTM( TM.tmAscent ); + ntm->ntmTm.tmDescent = ntm->ntmTm.tmHeight - ntm->ntmTm.tmAscent; + ntm->ntmTm.tmInternalLeading = SCALE_NTM( TM.tmInternalLeading ); + ntm->ntmTm.tmExternalLeading = SCALE_NTM( TM.tmExternalLeading ); + ntm->ntmTm.tmAveCharWidth = SCALE_NTM( TM.tmAveCharWidth ); + ntm->ntmTm.tmMaxCharWidth = SCALE_NTM( TM.tmMaxCharWidth ); + + memcpy((char *)&ntm->ntmTm + offsetof( TEXTMETRICW, tmWeight ), + (const char *)&TM + offsetof( TEXTMETRICW, tmWeight ), + sizeof(TEXTMETRICW) - offsetof( TEXTMETRICW, tmWeight )); ntm->ntmTm.ntmSizeEM = font->otm.otmEMSquare; ntm->ntmTm.ntmCellHeight = font->ntmCellHeight; ntm->ntmTm.ntmAvgWidth = font->ntmAvgWidth; +#undef SCALE_NTM +#undef TM } else if (font_funcs->set_bitmap_text_metrics( font )) { diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index d5ae526d536..ed0acf8243a 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -3923,6 +3923,25 @@ static void test_text_metrics(const LOGFONTA *lf, const NEWTEXTMETRICA *ntm) ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n", font_name, ntm->ntmCellHeight, cell_height, ascent, descent); + /* NEWTEXTMETRIC's scaling method is different from TEXTMETRIC's */ +#define SCALE_NTM(value) (MulDiv(ntm->tmHeight, (value), cell_height)) + size = MulDiv(32, ntm->ntmCellHeight, ntm->ntmSizeEM); + ok(ntm->tmHeight == size, "%s: ntm->tmHeight %d != %d (%u/%u)\n", + font_name, ntm->tmHeight, size, ntm->ntmCellHeight, ntm->ntmSizeEM); + size = SCALE_NTM(ntm->ntmAvgWidth); + ok(ntm->tmAveCharWidth == size, "%s: ntm->tmAveCharWidth %d != %d (%u/%u,%d)\n", + font_name, ntm->tmAveCharWidth, size, ntm->ntmAvgWidth, cell_height, ntm->tmHeight); + size = SCALE_NTM(ascent); + ok(ntm->tmAscent == size, "%s: ntm->tmAscent %d != %d (%u/%u,%d)\n", + font_name, ntm->tmAscent, size, ascent, cell_height, ntm->tmHeight); + size = ntm->tmHeight - ntm->tmAscent; + ok(ntm->tmDescent == size, "%s: ntm->tmDescent %d != %d (%u/%u,%d)\n", + font_name, ntm->tmDescent, size, descent, cell_height, ntm->tmHeight); + size = SCALE_NTM(cell_height - ntm->ntmSizeEM); + ok(ntm->tmInternalLeading == size, "%s: ntm->tmInternalLeading %d != %d (%u/%u,%d)\n", + font_name, ntm->tmInternalLeading, size, cell_height - ntm->ntmSizeEM, cell_height, ntm->tmHeight); +#undef SCALE_NTM + version = GET_BE_WORD(tt_os2.version); os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);