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