shithub: freetype+ttf2subf

Download patch

ref: b45043c44030337c1f7006f8c3d19fdfffe541f6
parent: e77ee789faaf5697143027452df6669afede0a57
author: Werner Lemberg <[email protected]>
date: Fri Aug 11 05:34:20 EDT 2017

[sfnt, truetype] Improve handling of missing sbits.

Requested by Behdad.

Modern bitmap-only SFNTs like `NotoColorEmoji.ttf' don't contain
entries in the bitmap strike(s) for empty glyphs.  Instead, they
rely that a space glyph gets created from the font's metrics data.
This commit makes FreeType behave accordingly.

* include/freetype/fterrdef.h (FT_Err_Missing_Bitmap): New error
code.

* src/sfnt/ttsbit.c (tt_sbit_decoder_load_image): Change error codes
to make a distinction between a missing bitmap in a composite and a
simple missing bitmap.

* src/truetype/ttgload.c (TT_Load_Glyph): For a missing bitmap (in a
bitmap-only font), synthesize an empty bitmap glyph if metrics are
available.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2017-08-11  Werner Lemberg  <[email protected]>
+
+	[sfnt, truetype] Improve handling of missing sbits.
+
+	Requested by Behdad.
+
+	Modern bitmap-only SFNTs like `NotoColorEmoji.ttf' don't contain
+	entries in the bitmap strike(s) for empty glyphs.  Instead, they
+	rely that a space glyph gets created from the font's metrics data.
+	This commit makes FreeType behave accordingly.
+
+	* include/freetype/fterrdef.h (FT_Err_Missing_Bitmap): New error
+	code.
+
+	* src/sfnt/ttsbit.c (tt_sbit_decoder_load_image): Change error codes
+	to make a distinction between a missing bitmap in a composite and a
+	simple missing bitmap.
+
+	* src/truetype/ttgload.c (TT_Load_Glyph): For a missing bitmap (in a
+	bitmap-only font), synthesize an empty bitmap glyph if metrics are
+	available.
+
 2017-08-10  Werner Lemberg  <[email protected]>
 
 	[base] Minor API improvement for default variation axis setting.
--- a/include/freetype/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -233,6 +233,8 @@
                 "invalid PostScript (post) table" )
   FT_ERRORDEF_( DEF_In_Glyf_Bytecode,                        0x9C,
                 "found FDEF or IDEF opcode in glyf bytecode" )
+  FT_ERRORDEF_( Missing_Bitmap,                              0x9D,
+                "missing bitmap in strike" )
 
   /* CFF, CID, and Type 1 errors */
 
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -1448,10 +1448,17 @@
     return FT_THROW( Invalid_Table );
 
   NoBitmap:
+    if ( recurse_count )
+    {
+      FT_TRACE4(( "tt_sbit_decoder_load_image:"
+                  " missing subglyph sbit with glyph index %d\n",
+                  glyph_index ));
+      return FT_THROW( Invalid_Composite );
+    }
+
     FT_TRACE4(( "tt_sbit_decoder_load_image:"
                 " no sbit found for glyph index %d\n", glyph_index ));
-
-    return FT_THROW( Invalid_Argument );
+    return FT_THROW( Missing_Bitmap );
   }
 
 
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -87,7 +87,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* Return the vertical metrics in font units for a given glyph.          */
-  /* See macro `TT_LOADER_SET_PP' below for explanations.                  */
+  /* See function `tt_loader_set_pp' below for explanations.               */
   /*                                                                       */
   FT_LOCAL_DEF( void )
   TT_Get_VMetrics( TT_Face     face,
@@ -2625,7 +2625,58 @@
          IS_DEFAULT_INSTANCE                     )
     {
       error = load_sbit_image( size, glyph, glyph_index, load_flags );
-      if ( error )
+      if ( FT_ERR_EQ( error, Missing_Bitmap ) )
+      {
+        /* the bitmap strike is incomplete and misses the requested glyph; */
+        /* if we have a bitmap-only font, return an empty glyph            */
+        if ( !FT_IS_SCALABLE( glyph->face ) )
+        {
+          TT_Face    face = (TT_Face)glyph->face;
+          FT_Short   left_bearing = 0, top_bearing = 0;
+          FT_UShort  advance_width = 0, advance_height = 0;
+
+
+          /* to return an empty glyph, however, we need metrics data   */
+          /* from the `hmtx' (or `vmtx') table; the assumption is that */
+          /* empty glyphs are missing intentionally, representing      */
+          /* whitespace - not having at least horizontal metrics is    */
+          /* thus considered an error                                  */
+          if ( !face->horz_metrics_size )
+            return error;
+
+          /* we now construct an empty bitmap glyph */
+          TT_Get_HMetrics( face, glyph_index,
+                           &left_bearing,
+                           &advance_width );
+          TT_Get_VMetrics( face, glyph_index,
+                           0,
+                           &top_bearing,
+                           &advance_height );
+
+          glyph->outline.n_points   = 0;
+          glyph->outline.n_contours = 0;
+
+          glyph->metrics.width  = 0;
+          glyph->metrics.height = 0;
+
+          glyph->metrics.horiBearingX = left_bearing;
+          glyph->metrics.horiBearingY = 0;
+          glyph->metrics.horiAdvance  = advance_width;
+
+          glyph->metrics.vertBearingX = 0;
+          glyph->metrics.vertBearingY = top_bearing;
+          glyph->metrics.vertAdvance  = advance_height;
+
+          glyph->format            = FT_GLYPH_FORMAT_BITMAP;
+          glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
+
+          glyph->bitmap_left = 0;
+          glyph->bitmap_top  = 0;
+
+          return FT_Err_Ok;
+        }
+      }
+      else if ( error )
       {
         /* return error if font is not scalable */
         if ( !FT_IS_SCALABLE( glyph->face ) )