#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;
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
+ {
+ // FreeType 2.6 and 2.6.1 cannot get PS name from pure-CFF.
+ // (FreeType 2.5.5 and earlier does not have this issue.
+ // FreeType 2.6.2+ has this bug fixed.)
+ // So we need direct parsing of the 'CFF' table, in this case.
+
+ debug_output (_f ("Directly parsing 'CFF' table of font %s.",
+ face_ps_name.c_str ()));
+
+ // See Adobe technote '5176.CFF.pdf', sections 2 and 5-7.
+ size_t hdrsize = static_cast<unsigned char>(cff_table.at(2));
+ string::iterator it = cff_table.begin () + hdrsize;
+
+ unsigned int name_index_count;
+ name_index_count = static_cast<unsigned char>(*it++) << 8;
+ name_index_count |= static_cast<unsigned char>(*it++);
+
+ size_t offsize = static_cast<unsigned char>(*it++);
+
+ if (name_index_count && 1 <= offsize && offsize <= 4)
+ {
+ // We get the first name in the CFF's name index
+ // because this CFF (derived from OTF and OTC)
+ // has only one name.
+ size_t off1 = 0, off2 = 0;
+ for (size_t t = 0; t < offsize; t++)
+ off1 = ( off1 << 8 ) | static_cast<unsigned char>(*it++);
+ if (off1)
+ {
+ for (size_t t = 0; t < offsize; t++)
+ off2 = ( off2 << 8 ) | static_cast<unsigned char>(*it++);
+ }
+ if (off1 && off1 < off2)
+ {
+ ret.assign (&cff_table.at(hdrsize + 3
+ + offsize * (name_index_count + 1)
+ + off1 - 1),
+ &cff_table.at(hdrsize + 3
+ + offsize * (name_index_count + 1)
+ + off2 - 1));
+ }
+ }
+
+ if (ret.empty ())
+ {
+ 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)
{
return otf->self_scm ();
}
-Open_type_font::Open_type_font (FT_Face face)
+Preinit_Open_type_font::Preinit_Open_type_font ()
{
- face_ = face;
lily_character_table_ = SCM_EOL;
lily_global_table_ = SCM_EOL;
lily_subfonts_ = SCM_EOL;
lily_index_to_bbox_table_ = SCM_EOL;
+}
+
+Open_type_font::Open_type_font (FT_Face face)
+{
+ face_ = face;
lily_character_table_ = alist_to_hashq (load_scheme_table ("LILC", face_));
lily_global_table_ = alist_to_hashq (load_scheme_table ("LILY", face_));
index_to_charcode_map_ = make_index_to_charcode_map (face_);
lily_index_to_bbox_table_ = scm_c_make_hash_table (257);
+
+ postscript_name_ = get_postscript_name (face_);
}
void
string
Open_type_font::font_name () const
{
- return FT_Get_Postscript_Name (face_);
+ return postscript_name_;
}
SCM