2 ttf.cc -- implement ttf -> pfa routine.
4 source file of the GNU LilyPond music typesetter
6 (c) 2005--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
11 #include <freetype/tttables.h>
13 #include "memory-stream.hh"
15 #include "lily-guile.hh"
17 #include "open-type-font.hh"
21 make_index_to_charcode_map (FT_Face face)
23 Index_to_charcode_map m;
27 FT_CharMap current_cmap = face->charmap;
28 FT_Select_Charmap (face, FT_ENCODING_UNICODE);
31 for (charcode = FT_Get_First_Char (face, &gindex); gindex != 0;
32 charcode = FT_Get_Next_Char (face, charcode, &gindex))
37 FT_Set_Charmap (face, current_cmap);
44 Based on ttfps by Juliusz Chroboczek
47 print_header (void *out, FT_Face face)
49 lily_cookie_fprintf (out, "%%!PS-TrueTypeFont\n");
52 = (TT_Postscript *) FT_Get_Sfnt_Table (face, ft_sfnt_post);
55 lily_cookie_fprintf (out, "%%%%VMUsage: %d %d\n", 0, 0);
57 lily_cookie_fprintf (out, "%d dict begin\n", 11);
58 lily_cookie_fprintf (out, "/FontName /%s def\n",
59 FT_Get_Postscript_Name (face));
61 lily_cookie_fprintf (out, "/Encoding StandardEncoding def\n");
62 lily_cookie_fprintf (out, "/PaintType 0 def\n");
63 lily_cookie_fprintf (out, "/FontMatrix [1 0 0 1 0 0] def\n");
66 = (TT_Header *)FT_Get_Sfnt_Table (face, ft_sfnt_head);
68 lily_cookie_fprintf (out, "/FontBBox [%ld %ld %ld %ld] def\n",
69 ht->xMin *1000L / ht->Units_Per_EM,
70 ht->yMin *1000L / ht->Units_Per_EM,
71 ht->xMax *1000L / ht->Units_Per_EM,
72 ht->yMax *1000L / ht->Units_Per_EM);
74 lily_cookie_fprintf (out, "/FontType 42 def\n");
75 lily_cookie_fprintf (out, "/FontInfo 8 dict dup begin\n");
76 lily_cookie_fprintf (out, "/version (%d.%d) def\n",
77 int (ht->Font_Revision >> 16),
78 int (ht->Font_Revision &((1 << 16) -1)));
83 lily_cookie_fprintf (out, "/Notice (");
84 fputpss (strings[0], out);
85 lily_cookie_fprintf (out, ") def\n");
89 lily_cookie_fprintf (out, "/FullName (");
90 fputpss (strings[4], out);
91 lily_cookie_fprintf (out, ") def\n");
95 lily_cookie_fprintf (out, "/FamilyName (");
96 fputpss (strings[1], out);
97 lily_cookie_fprintf (out, ") def\n");
101 lily_cookie_fprintf (out, "/isFixedPitch %s def\n",
102 pt->isFixedPitch ? "true" : "false");
103 lily_cookie_fprintf (out, "/UnderlinePosition %ld def\n",
104 pt->underlinePosition *1000L / ht->Units_Per_EM);
105 lily_cookie_fprintf (out, "/UnderlineThickness %ld def\n",
106 pt->underlineThickness *1000L / ht->Units_Per_EM);
107 lily_cookie_fprintf (out, "end readonly def\n");
110 #define CHUNKSIZE 65534
113 print_body (void *out, string name)
115 FILE *fd = fopen (name.c_str (), "rb");
117 static char xdigits[] = "0123456789ABCDEF";
119 unsigned char *buffer;
122 buffer = new unsigned char[CHUNKSIZE];
123 lily_cookie_fprintf (out, "/sfnts [");
126 i = fread (buffer, 1, CHUNKSIZE, fd);
129 lily_cookie_fprintf (out, "\n<");
130 for (j = 0; j < i; j++)
132 if (j != 0 && j % 36 == 0)
133 lily_cookie_putc ('\n', out);
134 /* lily_cookie_fprintf (out,"%02X",(int)buffer[j]) is too slow */
135 lily_cookie_putc (xdigits[ (buffer[j] & 0xF0) >> 4], out);
136 lily_cookie_putc (xdigits[buffer[j] & 0x0F], out);
138 lily_cookie_fprintf (out, "00>"); /* Adobe bug? */
142 lily_cookie_fprintf (out, "\n] def\n");
149 void t42_write_sting (void *out, unsigned char const * buffer, size_t s)
151 lily_cookie_fprintf (out, "\n<");
153 static char xdigits[] = "0123456789ABCDEF";
154 for (size_t j = 0; j < s; j++)
156 if (j != 0 && j % 36 == 0)
157 lily_cookie_putc ('\n', out);
159 if (l ++ >= CHUNKSIZE)
160 lily_cookie_fprintf (out, "00>\n<");
162 /* lily_cookie_fprintf (out,"%02X",(int)buffer[j]) is too slow */
163 lily_cookie_putc (xdigits[ (buffer[j] & 0xF0) >> 4], out);
164 lily_cookie_putc (xdigits[buffer[j] & 0x0F], out);
166 lily_cookie_fprintf (out, "00>"); /* Adobe bug? */
171 new_print_body (void *out, FT_Face face)
175 FT_ULong tag, length;
177 lily_cookie_fprintf (out, "/sfnts [");
178 while (FT_Sfnt_Table_Info(face, idx, &tag, &length)!=
179 FT_Err_Table_Missing)
181 unsigned char *buf = new unsigned char[length];
182 FT_Error error = FT_Load_Sfnt_Table(face, tag, 0, buf, NULL);
184 t42_write_sting (out, buf, length);
189 lily_cookie_fprintf (out, "\n] def\n");
194 print_trailer (void *out,
197 const int GLYPH_NAME_LEN = 256;
198 char glyph_name[GLYPH_NAME_LEN];
201 = (TT_MaxProfile *)FT_Get_Sfnt_Table (face, ft_sfnt_maxp);
203 lily_cookie_fprintf (out, "/CharStrings %d dict dup begin\n", mp->numGlyphs);
205 Index_to_charcode_map ic_map (make_index_to_charcode_map (face));
207 int output_count = 0;
208 for (int i = 0; i < mp->numGlyphs; i++)
211 if (face->face_flags & FT_FACE_FLAG_GLYPH_NAMES)
213 FT_Error error = FT_Get_Glyph_Name (face, i, glyph_name,
217 programming_error ("FT_Get_Glyph_Name (): error.");
222 if (!glyph_name[0] && ic_map.find (i) != ic_map.end ())
224 FT_ULong ucode = ic_map[i];
225 get_unicode_name (glyph_name, ucode);
228 if (glyph_name == string (".notdef"))
229 glyph_name[0] = '\0';
234 get_glyph_index_name (glyph_name, i);
239 lily_cookie_fprintf (out, "/%s %d def ", glyph_name, i);
244 programming_error (to_string ("no name for glyph %d", i));
247 if (! (output_count % 5))
248 lily_cookie_fprintf (out, "\n");
251 lily_cookie_fprintf (out, "end readonly def\n");
252 lily_cookie_fprintf (out, "FontName currentdict end definefont pop\n");
256 create_type42_font (void *out, string name)
258 FT_Face face = open_ft_face (name);
260 print_header (out, face);
261 // new_print_body (out, face);
262 print_body (out, name);
263 print_trailer (out, face);
269 LY_DEFINE (ly_ttf_ps_name, "ly:ttf-ps-name",
270 1, 0, 0, (SCM ttf_file_name),
271 "Extract the PostScript name from a TrueType font.")
273 LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
274 string file_name = ly_scm2string (ttf_file_name);
275 if (be_verbose_global)
276 progress_indication ("[" + file_name);
278 FT_Face face = open_ft_face (file_name);
279 char const *ps_name_str0 = FT_Get_Postscript_Name (face);
280 SCM ps_name = scm_from_locale_string (ps_name_str0 ? ps_name_str0 : "");
284 if (be_verbose_global)
285 progress_indication ("]");
292 LY_DEFINE (ly_ttf_2_pfa, "ly:ttf->pfa",
293 1, 0, 0, (SCM ttf_file_name),
294 "Convert the contents of a TTF file to Type42 PFA, returning it as "
297 LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
299 string file_name = ly_scm2string (ttf_file_name);
300 if (be_verbose_global)
301 progress_indication ("[" + file_name);
303 Memory_out_stream stream;
305 create_type42_font (&stream, file_name);
306 SCM asscm = scm_from_locale_stringn (stream.get_string (),
307 stream.get_length ());
309 if (be_verbose_global)
310 progress_indication ("]");