diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 4d513415bc4..480b8e568b5 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -319,7 +319,8 @@ struct tagGdiFont { DWORD gmsize; struct list hfontlist; FONT_DESC font_desc; - LONG aveWidth; + LONG aveWidth, ppem; + float scale_x, scale_y; SHORT yMax; SHORT yMin; OUTLINETEXTMETRICW *potm; @@ -329,7 +330,6 @@ struct tagGdiFont { FONTSIGNATURE fs; GdiFont *base_font; struct list child_fonts; - LONG ppem; }; typedef struct { @@ -2439,7 +2439,6 @@ static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height) if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0) WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", 0, font->ppem, err); } else { - font->ppem = height; if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0) WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", width, height, err); } @@ -3126,6 +3125,12 @@ found: TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName), debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index); + ret->ppem = height; + ret->aveWidth = abs(lf.lfWidth); + + ret->scale_x = 0.0; + ret->scale_y = 0.0; + if(!face->scalable) { width = face->size.x_ppem >> 6; height = face->size.y_ppem >> 6; @@ -3159,7 +3164,6 @@ found: TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont); - ret->aveWidth = FT_IS_SCALABLE(ret->ft_face) ? abs(lf.lfWidth) : 0; list_add_head(&gdi_font_list, &ret->entry); return ret; } @@ -3594,7 +3598,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, INT left, right, top = 0, bottom = 0, adv, lsb, bbx; FT_Angle angle = 0; FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; - float widthRatio = 1.0; + float widthRatio = 1.0, heightRatio = 1.0; FT_Matrix transMat = identityMat; BOOL needsTransform = FALSE; @@ -3624,7 +3628,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, if (!font->gm[glyph_index / GM_BLOCK_SIZE]) font->gm[glyph_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE); - if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP) || font->aveWidth || lpmat) + if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP) || lpmat) load_flags |= FT_LOAD_NO_BITMAP; err = pFT_Load_Glyph(ft_face, glyph_index, load_flags); @@ -3635,8 +3639,10 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, } /* Scaling factor */ - if (font->aveWidth && font->potm) { - widthRatio = (float)font->aveWidth * font->font_desc.matrix.eM11 / (float) font->potm->otmTextMetrics.tmAveCharWidth; + if (font->scale_x != 0.0) + { + widthRatio = font->scale_x; + heightRatio = font->scale_y; } left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64; @@ -3652,7 +3658,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, scaleMat.xx = FT_FixedFromFloat(widthRatio); scaleMat.xy = 0; scaleMat.yx = 0; - scaleMat.yy = (1 << 16); + scaleMat.yy = FT_FixedFromFloat(heightRatio); pFT_Matrix_Multiply(&scaleMat, &transMat); needsTransform = TRUE; @@ -4130,6 +4136,39 @@ static BOOL get_bitmap_text_metrics(GdiFont *font) return TRUE; } + +static void scale_font_metrics(GdiFont *font, LPTEXTMETRICW ptm) +{ + if (font->scale_x == 0.0) + { + if (FT_IS_SCALABLE(font->ft_face) || !font->ppem) + font->scale_y = 1.0; + else + { + font->scale_y = (float)font->ppem * font->font_desc.matrix.eM22; + font->scale_y /= (float)font->potm->otmTextMetrics.tmHeight; + } + + if (font->aveWidth) + { + font->scale_x = (float)font->aveWidth * font->font_desc.matrix.eM11; + font->scale_x /= (float)font->potm->otmTextMetrics.tmAveCharWidth; + } + else + font->scale_x = font->scale_y; + + TRACE("font scale x: %f y: %f\n", font->scale_x, font->scale_y); + } + ptm->tmHeight = (float)ptm->tmHeight * font->scale_y; + ptm->tmAscent = (float)ptm->tmAscent * font->scale_y; + ptm->tmDescent = (float)ptm->tmDescent * font->scale_y; + ptm->tmInternalLeading = (float)ptm->tmInternalLeading * font->scale_y; + ptm->tmExternalLeading = (float)ptm->tmExternalLeading * font->scale_y; + + ptm->tmAveCharWidth = (float)ptm->tmAveCharWidth * font->scale_x; + ptm->tmMaxCharWidth = (float)ptm->tmMaxCharWidth * font->scale_x; +} + /************************************************************* * WineEngGetTextMetrics * @@ -4143,10 +4182,8 @@ BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm) } if(!font->potm) return FALSE; memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm)); + scale_font_metrics(font, ptm); - if (font->aveWidth) { - ptm->tmAveCharWidth = font->aveWidth * font->font_desc.matrix.eM11; - } return TRUE; } @@ -4176,7 +4213,10 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, if(font->potm) { if(cbSize >= font->potm->otmSize) + { memcpy(potm, font->potm, font->potm->otmSize); + scale_font_metrics(font, &potm->otmTextMetrics); + } return font->potm->otmSize; } @@ -4404,7 +4444,10 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, ret = needed; if(potm && needed <= cbSize) + { memcpy(potm, font->potm, font->potm->otmSize); + scale_font_metrics(font, &potm->otmTextMetrics); + } end: HeapFree(GetProcessHeap(), 0, style_nameW); diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index b6e8327db00..7d73c19f35c 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -244,20 +244,14 @@ static void test_bitmap_font(void) bitmap_lf.lfHeight = height_orig * 2; bitmap_lf.lfWidth *= 3; hfont = create_font("3x2", &bitmap_lf); -todo_wine -{ test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2); -} DeleteObject(hfont); /* test integer scaling 3x3 */ bitmap_lf.lfHeight = height_orig * 3; bitmap_lf.lfWidth = 0; hfont = create_font("3x3", &bitmap_lf); -todo_wine -{ test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3); -} DeleteObject(hfont); ReleaseDC(0, hdc);