Commit 212aee0d6ec8bcae84c3278e6f786d01044dea7d

Wu, Chia-I (吳佳一) 2006-01-15T06:24:53

* include/freetype/internal/ftobjs.h (ft_fake_vertical_metrics), src/base/ftobjs.c (ft_fake_vertical_metrics): New function to fake the vertical metrics. * src/cff/cffgload.c, src/cid/cidgload.c, src/pcf/pcfdrivr.c, src/type1/t1gload.c, src/winfonts/winfnt.c: Fake the vertical metrics. The fake metrics is monotone. * src/truetype/ttgload.c (compute_glyph_metrics): Some fixes and formattings in vertical metrics faking. There are still rooms for improvements (and so do the CFF module).

diff --git a/ChangeLog b/ChangeLog
index e8a7c67..29f26c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2006-01-15  Chia-I Wu  <b90201047@ntu.edu.tw>
 
+	* include/freetype/internal/ftobjs.h (ft_fake_vertical_metrics),
+	src/base/ftobjs.c (ft_fake_vertical_metrics): New function to fake the
+	vertical metrics.
+
+	* src/cff/cffgload.c, src/cid/cidgload.c, src/pcf/pcfdrivr.c,
+	src/type1/t1gload.c, src/winfonts/winfnt.c: Fake the vertical metrics.
+	The fake metrics is monotone.
+
+	* src/truetype/ttgload.c (compute_glyph_metrics): Some fixes and
+	formattings in vertical metrics faking.  There are still rooms for
+	improvements (and so do the CFF module).
+
+2006-01-15  Chia-I Wu  <b90201047@ntu.edu.tw>
+
 	* src/bdf/bdfdrivr.c (BDF_Glyph_Load), src/pcf/pcfdrivr.c
 	(PCF_Glyph_Load), src/winfonts/winfnt.c (FNT_Load_Glyph): Don't set
 	the linear advance fields as they are only for the outline glyphs.
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 0a6c316..a6c6aae 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -461,6 +461,15 @@ FT_BEGIN_HEADER
                  FT_ULong*        index );
 
 
+  /*
+   * Use the horizontal metrics to fake the vertical metrics.
+   * If `advance' is zero, it is also faked.
+   */
+  FT_BASE( void )
+  ft_fake_vertical_metrics( FT_Glyph_Metrics*  metrics,
+                            FT_Pos             advance );
+
+
  /*
   * Free the bitmap of a given glyphslot when needed
   * (i.e., only when it was allocated with ft_glyphslot_alloc_bitmap).
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index cbb466c..34b1f95 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2039,6 +2039,21 @@
   }
 
 
+  /* documentation is in ftobjs.h */
+
+  FT_BASE_DEF( void )
+  ft_fake_vertical_metrics( FT_Glyph_Metrics*  metrics,
+                            FT_Pos             advance )
+  {
+    if ( !advance )
+      advance = metrics->height * 12 / 10;
+
+    metrics->vertBearingX = -( metrics->width / 2 );
+    metrics->vertBearingY = ( advance - metrics->height ) / 2;
+    metrics->vertAdvance  = advance;
+  }
+
+
   static void
   ft_recompute_scaled_metrics( FT_Face           face,
                                FT_Size_Metrics*  metrics )
diff --git a/src/bdf/bdfdrivr.c b/src/bdf/bdfdrivr.c
index 64b6e1f..a70f8a2 100644
--- a/src/bdf/bdfdrivr.c
+++ b/src/bdf/bdfdrivr.c
@@ -702,13 +702,19 @@ THE SOFTWARE.
     slot->bitmap_left = glyph.bbx.x_offset;
     slot->bitmap_top  = glyph.bbx.ascent;
 
-    /* FZ XXX: TODO: vertical metrics */
     slot->metrics.horiAdvance  = glyph.dwidth << 6;
     slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
     slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
     slot->metrics.width        = bitmap->width << 6;
     slot->metrics.height       = bitmap->rows << 6;
 
+    /* 
+     * XXX DWIDTH1 and VVECTOR should be parsed and
+     * used here, provided such fonts do exist.
+     */
+    ft_fake_vertical_metrics( &slot->metrics,
+                              face->bdffont->bbx.height << 6 );
+
   Exit:
     return error;
   }
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 2f9c612..417eb4d 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -2602,6 +2602,7 @@
         FT_BBox            cbox;
         FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
         FT_Vector          advance;
+        FT_Bool            has_vertical_info;
 
 
         /* copy the _unscaled_ advance width */
@@ -2609,17 +2610,12 @@
         glyph->root.linearHoriAdvance           = decoder.glyph_width;
         glyph->root.internal->glyph_transformed = 0;
 
-        /* make up vertical ones */
-        metrics->vertAdvance  = 0;
-        metrics->vertBearingX = 0;
-        metrics->vertBearingY = 0;
-
-        glyph->root.linearVertAdvance = 0;
+        has_vertical_info = ( face->vertical_info                   &&
+                              face->vertical.number_Of_VMetrics > 0 &&
+                              face->vertical.long_metrics != 0      );
 
         /* get the vertical metrics from the vtmx table if we have one */
-        if ( face->vertical_info                   &&
-             face->vertical.number_Of_VMetrics > 0 &&
-             face->vertical.long_metrics != 0      )
+        if ( has_vertical_info )
         {
           FT_Short   vertBearingY = 0;
           FT_UShort  vertAdvance  = 0;
@@ -2630,6 +2626,18 @@
           metrics->vertBearingY = vertBearingY;
           metrics->vertAdvance  = vertAdvance;
         }
+        else
+        {
+          /* make up vertical ones */
+          if ( face->os2.version != 0xFFFFU )
+            metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
+                                             face->os2.sTypoDescender );
+          else
+            metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
+                                             face->horizontal.Descender );
+        }
+
+        glyph->root.linearVertAdvance = metrics->vertAdvance;
 
         glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
 
@@ -2687,6 +2695,12 @@
 
         metrics->horiBearingX = cbox.xMin;
         metrics->horiBearingY = cbox.yMax;
+
+        if ( has_vertical_info )
+          metrics->vertBearingX = -metrics->width / 2;
+        else
+          ft_fake_vertical_metrics( metrics,
+                                    metrics->vertAdvance );
       }
     }
 
diff --git a/src/cid/cidgload.c b/src/cid/cidgload.c
index 12d749d..eaf6a1a 100644
--- a/src/cid/cidgload.c
+++ b/src/cid/cidgload.c
@@ -343,8 +343,9 @@
         cidglyph->internal->glyph_transformed = 0;
 
         /* make up vertical ones */
-        metrics->vertAdvance  = 0;
-        cidglyph->linearVertAdvance = 0;
+        metrics->vertAdvance = ( face->cid.font_bbox.yMax -
+                                 face->cid.font_bbox.yMin ) >> 16;
+        cidglyph->linearVertAdvance = metrics->vertAdvance;
 
         cidglyph->format            = FT_GLYPH_FORMAT_OUTLINE;
 
@@ -400,8 +401,8 @@
         metrics->horiBearingY = cbox.yMax;
 
         /* make up vertical ones */
-        metrics->vertBearingX = 0;
-        metrics->vertBearingY = 0;
+        ft_fake_vertical_metrics( metrics,
+                                  metrics->vertAdvance );
       }
     }
 
diff --git a/src/pcf/pcfdrivr.c b/src/pcf/pcfdrivr.c
index 0bb1f77..f28854b 100644
--- a/src/pcf/pcfdrivr.c
+++ b/src/pcf/pcfdrivr.c
@@ -531,6 +531,10 @@ THE SOFTWARE.
                                    metric->leftSideBearing ) << 6;
     slot->metrics.height       = bitmap->rows << 6;
 
+    ft_fake_vertical_metrics( &slot->metrics,
+                              ( face->accel.fontAscent +
+                                face->accel.fontDescent ) << 6 );
+
     FT_TRACE4(( " --- ok\n" ));
 
   Exit:
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 6701471..6b28c7d 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -1673,10 +1673,6 @@
     /* up some metrics by `hand'...                                      */
 
     {
-      FT_Short   top_bearing;    /* vertical top side bearing (EM units) */
-      FT_UShort  advance_height; /* vertical advance height   (EM units) */
-
-      FT_Pos     left;     /* scaled vertical left side bearing */
       FT_Pos     top;      /* scaled vertical top side bearing  */
       FT_Pos     advance;  /* scaled vertical advance height    */
 
@@ -1685,18 +1681,18 @@
       if ( face->vertical_info &&
            face->vertical.number_Of_VMetrics > 0 )
       {
-        top_bearing = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
-                                           y_scale );
+        top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
+                                   y_scale );
 
         if ( loader->pp3.y <= loader->pp4.y )
-          advance_height = 0;
+          advance = 0;
         else
-          advance_height = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
-                                                 y_scale );
+          advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
+                                          y_scale );
       }
       else
       {
-        FT_Short  max_height, height;
+        FT_Pos  height;
 
 
         /* XXX Compute top side bearing and advance height in  */
@@ -1707,79 +1703,63 @@
         /*       table in the font.  Otherwise, we use the     */
         /*       values defined in the horizontal header.      */
 
-        height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin, y_scale );
+        height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
+                                      y_scale );
         if ( face->os2.version != 0xFFFFU )
-        {
-          /* sTypoDescender is negative */
-          max_height = (FT_Short)(face->os2.sTypoAscender -
-                                  face->os2.sTypoDescender);
-
-          top_bearing    = (FT_Short)( ( max_height - height ) / 2 );
-          advance_height = (FT_UShort)( max_height + face->os2.sTypoLineGap );
-        }
+          advance = (FT_Pos)( face->os2.sTypoAscender -
+                              face->os2.sTypoDescender );
         else
-        {
-          max_height = (FT_Short)(face->horizontal.Ascender +
-                                  face->horizontal.Descender);
+          advance = (FT_Pos)( face->horizontal.Ascender -
+                              face->horizontal.Descender );
 
-          top_bearing    = (FT_Short)( ( max_height - height ) / 2 );
-          advance_height = (FT_UShort)( max_height +
-                                        face->horizontal.Line_Gap );
-        }
+        top = ( advance - height ) / 2;
       }
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
-
-      /* If this is an incrementally loaded font see if there are */
-      /* overriding metrics for this glyph.                       */
-      if ( face->root.internal->incremental_interface &&
-           face->root.internal->incremental_interface->funcs->get_glyph_metrics )
       {
-        FT_Incremental_MetricsRec  metrics;
-        FT_Error                   error = TT_Err_Ok;
+        FT_Incremental_InterfaceRec*  incr;
+        FT_Incremental_MetricsRec     metrics;
+        FT_Error                      error;
 
 
-        metrics.bearing_x = 0;
-        metrics.bearing_y = top_bearing;
-        metrics.advance   = advance_height;
-        error =
-          face->root.internal->incremental_interface->funcs->get_glyph_metrics(
-            face->root.internal->incremental_interface->object,
-            glyph_index, TRUE, &metrics );
+        incr = face->root.internal->incremental_interface;
 
-        if ( error )
-          return error;
+        /* If this is an incrementally loaded font see if there are */
+        /* overriding metrics for this glyph.                       */
+        if ( incr && incr->funcs->get_glyph_metrics )
+        {
+          metrics.bearing_x = 0;
+          metrics.bearing_y = top;
+          metrics.advance   = advance;
+          error = incr->funcs->get_glyph_metrics( incr->object,
+                                                  glyph_index,
+                                                  TRUE,
+                                                  &metrics );
+          if ( error )
+            return error;
 
-        top_bearing    = (FT_Short)metrics.bearing_y;
-        advance_height = (FT_UShort)metrics.advance;
+          top     = metrics.bearing_y;
+          advance = metrics.advance;
+        }
       }
 
       /* GWW: Do vertical metrics get loaded incrementally too? */
 
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
+      glyph->linearVertAdvance = advance;
+
       /* scale the metrics */
       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
       {
-        top     = FT_MulFix( top_bearing, y_scale );
-        advance = FT_MulFix( advance_height, y_scale );
-      }
-      else
-      {
-        top     = top_bearing;
-        advance = advance_height;
+        top     = FT_MulFix( top, y_scale );
+        advance = FT_MulFix( advance, y_scale );
       }
 
-      /* set the advance height in design units.  It is scaled later by */
-      /* the base layer.                                                */
-      glyph->linearVertAdvance = advance_height;
-
       /* XXX: for now, we have no better algorithm for the lsb, but it */
       /*      should work fine.                                        */
       /*                                                               */
-      left = ( bbox.xMin - bbox.xMax ) / 2;
-
-      glyph->metrics.vertBearingX = left;
+      glyph->metrics.vertBearingX = ( bbox.xMin - bbox.xMax ) / 2;
       glyph->metrics.vertBearingY = top;
       glyph->metrics.vertAdvance  = advance;
     }
diff --git a/src/type1/t1gload.c b/src/type1/t1gload.c
index 88c57da..050c4f0 100644
--- a/src/type1/t1gload.c
+++ b/src/type1/t1gload.c
@@ -298,8 +298,10 @@
         glyph->root.linearHoriAdvance           = decoder.builder.advance.x;
         glyph->root.internal->glyph_transformed = 0;
 
-        metrics->vertAdvance          = 0;
-        glyph->root.linearVertAdvance = 0;
+        /* make up vertical ones */
+        metrics->vertAdvance = ( face->type1.font_bbox.yMax -
+                                 face->type1.font_bbox.yMin ) >> 16;
+        glyph->root.linearVertAdvance = metrics->vertAdvance;
 
         glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
 
@@ -357,8 +359,8 @@
         metrics->horiBearingY = cbox.yMax;
 
         /* make up vertical ones */
-        metrics->vertBearingX = 0;
-        metrics->vertBearingY = 0;
+        ft_fake_vertical_metrics( metrics,
+                                  metrics->vertAdvance );
       }
 
       /* Set control data to the glyph charstrings.  Note that this is */
diff --git a/src/winfonts/winfnt.c b/src/winfonts/winfnt.c
index c20d3bf..376fde3 100644
--- a/src/winfonts/winfnt.c
+++ b/src/winfonts/winfnt.c
@@ -724,6 +724,9 @@
     slot->metrics.horiBearingX = 0;
     slot->metrics.horiBearingY = slot->bitmap_top << 6;
 
+    ft_fake_vertical_metrics( &slot->metrics,
+                              bitmap->rows << 6 );
+
   Exit:
     return error;
   }