]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 4876/1: Add fontname replacing function for CFF (OTF/OTC) fonts
authorMasamichi Hosoda <trueroad@trueroad.jp>
Sat, 25 Jun 2016 01:52:44 +0000 (10:52 +0900)
committerMasamichi Hosoda <trueroad@trueroad.jp>
Mon, 4 Jul 2016 12:46:34 +0000 (21:46 +0900)
For CFF (OTF/OTC) fonts,
FT_Get_Postscript_Name ()
in FreeType 2.6+ gets the name in 'name' table.
However, we want the name in 'CFF' table instead of in 'name' table
because output postscript file is embedded only 'CFF' table of the font.

They are inconsistent for some OpenType/CFF Collection fonts (OTC).

This function can get the name in 'CFF' table.

TODO: Check conflicts between fonts which have same name in 'CFF' table
but different name in 'name' table.

lily/include/open-type-font.hh
lily/open-type-font.cc

index f08d4fa71c5e53e338056aa929416ffb64a4b415..bf36071e9139adc3f12b03f80dbe347a43c760fa 100644 (file)
@@ -65,5 +65,6 @@ public:
 
 string get_otf_table (FT_Face face, const string &tag);
 FT_Face open_ft_face (const string&, FT_Long idx);
+string get_postscript_name (FT_Face face);
 
 #endif /* OPEN_TYPE_FONT_HH */
index 3038df4331645f30dcb000be55cf3deb0830171d..e4fb5d5d988a585266884076bc40c727dc943ef3 100644 (file)
 #include "open-type-font.hh"
 #include "freetype.hh"
 
+#ifdef FT_FONT_FORMATS_H
+/* FreeType 2.6+ */
+#include FT_FONT_FORMATS_H
+#else
+/* FreeType 2.5.5 and earlier */
+#include FT_XFREE86_H
+#define FT_Get_Font_Format FT_Get_X11_Font_Format
+#endif
+
 #include <cstdio>
 
 using namespace std;
@@ -120,6 +129,74 @@ open_ft_face (const string &str, FT_Long idx)
   return face;
 }
 
+string
+get_postscript_name (FT_Face face)
+{
+  string face_ps_name;
+  const char *psname = FT_Get_Postscript_Name (face);
+  if (psname)
+    face_ps_name = psname;
+  else
+    {
+      warning (_ ("cannot get postscript name"));
+      return "";
+    }
+
+  const char *fmt = FT_Get_Font_Format (face);
+  if (fmt)
+    {
+      if (static_cast<string>(fmt) != "CFF")
+        return face_ps_name;  // For non-CFF font, pass it through.
+    }
+  else
+    {
+      warning (_f ("cannot get font %s format", face_ps_name.c_str ()));
+      return face_ps_name;
+    }
+
+  // For OTF and OTC fonts, we use data from the font's 'CFF' table only
+  // because other tables are not embedded in the output PS file.
+  string cff_table = get_otf_table (face, "CFF ");
+
+  FT_Open_Args args;
+  args.flags = FT_OPEN_MEMORY;
+  args.memory_base = static_cast<const FT_Byte*>
+    (static_cast<const void*>(cff_table.data ()));
+  args.memory_size = cff_table.size ();
+
+  FT_Face cff_face;
+  // According to OpenType Specification ver 1.7,
+  // the CFF (derived from OTF and OTC) has only one name.
+  // So we use zero as the font index.
+  FT_Error error_code = FT_Open_Face (freetype2_library, &args,
+                                      0 /* font index */,
+                                      &cff_face);
+  if (error_code)
+    {
+      warning (_f ("cannot read CFF %s: %s",
+                   face_ps_name,
+                   freetype_error_string (error_code).c_str ()));
+      return face_ps_name;
+    }
+
+  string ret;
+  const char *cffname = FT_Get_Postscript_Name (cff_face);
+  if (cffname)
+    ret = cffname;
+  else
+    {
+      warning (_f ("cannot get font %s CFF name", face_ps_name.c_str ()));
+      ret = face_ps_name;
+    }
+
+  debug_output (_f ("Replace font name from %s to %s.",
+                    face_ps_name.c_str (), ret.c_str ()));
+
+  FT_Done_Face (cff_face);
+
+  return ret;
+}
+
 SCM
 Open_type_font::make_otf (const string &str)
 {