gdi32: Add support for scaling font metrics.

This commit is contained in:
Dmitry Timoshkov 2008-01-08 23:02:09 +08:00 committed by Alexandre Julliard
parent 29a0b3622c
commit 535053b927
2 changed files with 55 additions and 18 deletions

View File

@ -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);

View File

@ -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);