Implement average font width support
Warren_Baird at cimmetry.com
Warren_Baird at cimmetry.com
Thu Feb 6 08:49:19 CST 2003
ChangeLog:
Added support for average width specification when creating a font
using CreateFontIndirect. That is, scale the font horizontaly
according to the average width value specified by the user in
the input LOGFONT.
Force the font average width to be at least one. It happened to
be zero sometimes for a significantly small x-scale factor
between logical and device coordinates, which was causing
a division by zero when calculating the width scaling factor
in GetGlyphOutline.
Description:
It implies keeping the average width specified in the LOGFONT
inside the GdiFont internal structure.
In GetGlyphOutline, scale the output bounding box and the output
outline horizontaly with a proper width ratio calculated using
the desired width average in logical coordinates, the actual width
average for that font in device coordinates and the x-scale factor
between logical and device coordinates.
Also, in GetTextMetrics, return the user-speficied average width
(if so) instead of the actual average width. It behaves that way
on Windows.
Warren Baird : Warren_Baird at cimmetry.com
Dave Belanger
diff -ur clean/wine/dlls/gdi/freetype.c wine/dlls/gdi/freetype.c
--- clean/wine/dlls/gdi/freetype.c 24 Jan 2003 15:12:16 -0000 1.1.1.3
+++ wine/dlls/gdi/freetype.c 28 Jan 2003 19:04:55 -0000
@@ -143,6 +143,7 @@
GM *gm;
DWORD gmsize;
HFONT hfont;
+ LONG aveWidth;
SHORT yMax;
SHORT yMin;
OUTLINETEXTMETRICW *potm;
@@ -1105,6 +1106,7 @@
TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont);
ret->hfont = hfont;
+ ret->aveWidth = lf.lfWidth;
ret->next = GdiFontList;
GdiFontList = ret;
@@ -1379,6 +1381,7 @@
INT left, right, top = 0, bottom = 0;
FT_Angle angle = 0;
FT_Int load_flags = FT_LOAD_DEFAULT;
+ float widthRatio = 1.0;
TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
buflen, buf, lpmat);
@@ -1400,8 +1403,9 @@
}
}
- if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP))
- load_flags |= FT_LOAD_NO_BITMAP;
+ if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP) ||
font->aveWidth)
+ load_flags |= FT_LOAD_NO_BITMAP;
+
err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
@@ -1409,12 +1413,16 @@
FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
return GDI_ERROR;
}
+
+ // Scaling the bounding box.
+ if (font->aveWidth && font->potm) {
+ widthRatio = (float)font->aveWidth * font->xform.eM11 / (float)
font->potm->otmTextMetrics.tmAveCharWidth;
+ }
- left = ft_face->glyph->metrics.horiBearingX & -64;
- right = ((ft_face->glyph->metrics.horiBearingX +
- ft_face->glyph->metrics.width) + 63) & -64;
+ left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
+ right = (INT)((ft_face->glyph->metrics.horiBearingX +
ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
- font->gm[glyph_index].adv = (ft_face->glyph->metrics.horiAdvance + 63) >>
6;
+ font->gm[glyph_index].adv = (INT)((ft_face->glyph->metrics.horiAdvance *
widthRatio) + 63) >> 6;
font->gm[glyph_index].lsb = left >> 6;
font->gm[glyph_index].bbx = (right - left) >> 6;
@@ -1432,8 +1440,8 @@
TRACE("angle %ld\n", angle >> 16);
for(xc = 0; xc < 2; xc++) {
for(yc = 0; yc < 2; yc++) {
- vec.x = ft_face->glyph->metrics.horiBearingX +
- xc * ft_face->glyph->metrics.width;
+ vec.x = (ft_face->glyph->metrics.horiBearingX +
+ xc * ft_face->glyph->metrics.width) * widthRatio;
vec.y = ft_face->glyph->metrics.horiBearingY -
yc * ft_face->glyph->metrics.height;
TRACE("Vec %ld,%ld\n", vec.x, vec.y);
@@ -1455,7 +1463,7 @@
top = (top + 63) & -64;
TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
- vec.x = ft_face->glyph->metrics.horiAdvance;
+ vec.x = ft_face->glyph->metrics.horiAdvance * widthRatio;
vec.y = 0;
pFT_Vector_Rotate(&vec, angle);
lpgm->gmCellIncX = (vec.x+63) >> 6;
@@ -1477,6 +1485,19 @@
return GDI_ERROR;
}
+ // Scaling the outline.
+ if(ft_face->glyph->format == ft_glyph_format_outline && font->aveWidth) {
+ FT_Matrix scaleMatrix;
+ unsigned int roundedOffWidthRatio = (unsigned int)widthRatio;
+ FT_Fixed fixedWidthRatio = (roundedOffWidthRatio << 16) |
+ (unsigned int)((widthRatio - roundedOffWidthRatio) * 0xFFFF);
+ scaleMatrix.xx = fixedWidthRatio;
+ scaleMatrix.xy = 0;
+ scaleMatrix.yx = 0;
+ scaleMatrix.yy = (1 << 16);
+ pFT_Outline_Transform(&ft_face->glyph->outline, &scaleMatrix);
+ }
+
switch(format) {
case GGO_BITMAP:
width = lpgm->gmBlackBoxX;
@@ -1776,6 +1797,10 @@
}
if(!font->potm) return FALSE;
memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
+
+ if (font->aveWidth) {
+ ptm->tmAveCharWidth = font->aveWidth * font->xform.eM11;
+ }
return TRUE;
}
@@ -1890,6 +1915,9 @@
(pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
+ if (TM.tmAveCharWidth == 0) {
+ TM.tmAveCharWidth = 1;
+ }
TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin,
x_scale) + 32) >> 6;
TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
TM.tmOverhang = 0;
More information about the wine-patches
mailing list