Hi Werner et al.,

As discussed, this patch implements synthetic Unicode charmap for sfnt
if one is missing. I mostly copied it from cff and it requires the
psnames module, which is not properly conditioned in the patch yet. I
am not sure if it makes sense without psnames too. Comments?

Alexei
diff --git a/ChangeLog b/ChangeLog
index bc65cbb..acec0e6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2017-06-20  Alexei Podtelezhnikov  <[email protected]>
+
+       [sfnt] Synthesize a Unicode charmap if one is missing.
+
+       * src/sfnt/ttpost.c (tt_get_glyph_name, tt_cmap_unicode_init,
+       tt_cmap_unicode_done, tt_cmap_unicode_char_index,
+       tt_cmap_unicode_char_next, tt_cmap_unicode_class_rec): Implement
+       synthetic Unicode charmap class.
+       * src/sfnt/ttpost.h (tt_cmap_unicode_class_rec): Declare it.
+
+       * src/sfnt/sfobjs.c (sfnt_load_face)
+       [TT_CONFIG_OPTION_POSTSCRIPT_NAMES]: If Unicode charmap is missing,
+       synthesize one.
+
+       * src/sfnt/ttcmap.c (tt_get_cmap_info): Make sure the callback is
+       available.
+
+       * include/freetype/config/ftoption.h: Document it.
+       * devel/ftoption.h: Ditto.
+
+
 2017-06-20  Tony Theodore  <[email protected]>
 
        Fix pkg-config in freetype-config for cross-compiling (#51274).
diff --git a/devel/ftoption.h b/devel/ftoption.h
index db661e7..f11ad00 100644
--- a/devel/ftoption.h
+++ b/devel/ftoption.h
@@ -563,7 +563,7 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to    */
   /* load and enumerate the glyph Postscript names in a TrueType or        */
-  /* OpenType file.                                                        */
+  /* OpenType file and synthesize a Unicode charmap if one is missing.     */
   /*                                                                       */
   /* Note that when you do not compile the `PSNames' module by undefining  */
   /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will   */
diff --git a/include/freetype/config/ftoption.h 
b/include/freetype/config/ftoption.h
index 1bf6e8f..d9c8793 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -563,7 +563,7 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to    */
   /* load and enumerate the glyph Postscript names in a TrueType or        */
-  /* OpenType file.                                                        */
+  /* OpenType file and synthesize a Unicode charmap if one is missing.     */
   /*                                                                       */
   /* Note that when you do not compile the `PSNames' module by undefining  */
   /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will   */
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 3f54d5d..c4257ee 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -40,6 +40,10 @@
 #include "ttbdf.h"
 #endif
 
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include "ttpost.h"
+#endif
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -1464,7 +1468,8 @@
       /* Polish the charmaps.                                              */
       /*                                                                   */
       /*   Try to set the charmap encoding according to the platform &     */
-      /*   encoding ID of each charmap.                                    */
+      /*   encoding ID of each charmap.  Emulate Unicode charmap if one    */
+      /*   is missing.                                                     */
       /*                                                                   */
 
       tt_face_build_cmaps( face );  /* ignore errors */
@@ -1472,7 +1477,10 @@
 
       /* set the encoding fields */
       {
-        FT_Int  m;
+        FT_Int   m;
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+        FT_Bool  has_unicode = FALSE;
+#endif
 
 
         for ( m = 0; m < root->num_charmaps; m++ )
@@ -1482,6 +1490,33 @@
 
           charmap->encoding = sfnt_find_encoding( charmap->platform_id,
                                                   charmap->encoding_id );
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+          if ( charmap->encoding == FT_ENCODING_UNICODE )
+            has_unicode = TRUE;
+        }
+
+        /* synthesize Unicode charmap if one is missing */
+        if ( !has_unicode )
+        {
+          FT_CharMapRec cmaprec;
+
+
+          cmaprec.face        = root;
+          cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
+          cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
+          cmaprec.encoding    = FT_ENCODING_UNICODE;
+
+
+          error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec,
+                               NULL, &cmaprec, NULL );
+          if ( error                                      &&
+               FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
+            FT_TRACE2(( "sfnt_load_face: failed to emulate Unicode\n" ));
+
+#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
         }
       }
 
diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
index 5afa6ae..4178b5b 100644
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -3801,8 +3801,10 @@
     FT_CMap        cmap  = (FT_CMap)charmap;
     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
 
-
-    return clazz->get_cmap_info( charmap, cmap_info );
+    if ( clazz->get_cmap_info )
+      return clazz->get_cmap_info( charmap, cmap_info );
+    else
+      return FT_THROW( Invalid_CharMap_Format );
   }
 
 
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index a47ece0..139c639 100644
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -564,6 +564,105 @@
     return FT_Err_Ok;
   }
 
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                SYNTHETIC UNICODE ENCODING CMAP                *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  FT_CALLBACK_DEF( const char * )
+  tt_get_glyph_name( TT_Face  face,
+                     FT_UInt  idx )
+  {
+    FT_String*  PSname;
+
+
+    tt_face_get_ps_name( face, idx, &PSname );
+
+    return PSname;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  tt_cmap_unicode_init( PS_Unicodes  unicodes,
+                        FT_Pointer   pointer )
+  {
+    TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
+    FT_Memory           memory  = FT_FACE_MEMORY( face );
+    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
+
+    FT_UNUSED( pointer );
+
+
+    return psnames->unicodes_init( memory,
+                                   unicodes,
+                                   face->root.num_glyphs,
+                                   (PS_GetGlyphNameFunc)&tt_get_glyph_name,
+                                   (PS_FreeGlyphNameFunc)NULL,
+                                   (FT_Pointer)face );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  tt_cmap_unicode_done( PS_Unicodes  unicodes )
+  {
+    FT_Face    face   = FT_CMAP_FACE( unicodes );
+    FT_Memory  memory = FT_FACE_MEMORY( face );
+
+
+    FT_FREE( unicodes->maps );
+    unicodes->num_maps = 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_UInt )
+  tt_cmap_unicode_char_index( PS_Unicodes  unicodes,
+                              FT_UInt32    char_code )
+  {
+    TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
+    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+    return psnames->unicodes_char_index( unicodes, char_code );
+  }
+
+
+  FT_CALLBACK_DEF( FT_UInt32 )
+  tt_cmap_unicode_char_next( PS_Unicodes  unicodes,
+                             FT_UInt32   *pchar_code )
+  {
+    TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
+    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+    return psnames->unicodes_char_next( unicodes, pchar_code );
+  }
+
+
+  FT_DEFINE_TT_CMAP(
+    tt_cmap_unicode_class_rec,
+
+      sizeof ( PS_UnicodesRec ),
+
+      (FT_CMap_InitFunc)     tt_cmap_unicode_init,        /* init       */
+      (FT_CMap_DoneFunc)     tt_cmap_unicode_done,        /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
+
+    -1,
+    (TT_CMap_ValidateFunc)NULL,  /* validate      */
+    (TT_CMap_Info_GetFunc)NULL   /* get_cmap_info */
+  )
+
 #else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
 
   /* ANSI C doesn't like empty source files */
diff --git a/src/sfnt/ttpost.h b/src/sfnt/ttpost.h
index 722485e..0706584 100644
--- a/src/sfnt/ttpost.h
+++ b/src/sfnt/ttpost.h
@@ -22,6 +22,7 @@
 
 
 #include <ft2build.h>
+#include "ttcmap.h"
 #include FT_CONFIG_CONFIG_H
 #include FT_INTERNAL_TRUETYPE_TYPES_H
 
@@ -38,6 +39,10 @@ FT_BEGIN_HEADER
   tt_face_free_ps_names( TT_Face  face );
 
 
+  /* synthetic unicode charmap */
+  FT_CALLBACK_TABLE const  TT_CMap_ClassRec tt_cmap_unicode_class_rec;
+
+
 FT_END_HEADER
 
 #endif /* TTPOST_H_ */
_______________________________________________
Freetype-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/freetype-devel

Reply via email to