2 ttf.cc -- implement ttf -> pfa routine.
4 source file of the GNU LilyPond music typesetter
6 (c) 2005--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
11 #include <freetype/tttables.h>
13 #include "lily-proto.hh"
14 #include "memory-stream.hh"
16 #include "lily-guile.hh"
18 #include "open-type-font.hh"
22 make_index_to_charcode_map (FT_Face face)
24 Index_to_charcode_map m;
28 FT_CharMap current_cmap = face->charmap;
29 FT_Select_Charmap(face, FT_ENCODING_UNICODE);
30 for (charcode = FT_Get_First_Char (face, &gindex); gindex != 0;
31 charcode = FT_Get_Next_Char (face, charcode, &gindex))
33 FT_Set_Charmap (face, current_cmap);
39 Based on ttfps by Juliusz Chroboczek
42 print_header (void *out, FT_Face face)
44 lily_cookie_fprintf (out, "%%!PS-TrueTypeFont\n");
47 = (TT_Postscript *) FT_Get_Sfnt_Table (face, ft_sfnt_post);
50 lily_cookie_fprintf (out, "%%%%VMUsage: %ld %ld\n", 0, 0);
52 lily_cookie_fprintf (out, "%d dict begin\n", 11);
53 lily_cookie_fprintf (out, "/FontName /%s def\n",
54 FT_Get_Postscript_Name (face));
56 lily_cookie_fprintf (out, "/Encoding StandardEncoding def\n");
57 lily_cookie_fprintf (out, "/PaintType 0 def\n");
58 lily_cookie_fprintf (out, "/FontMatrix [1 0 0 1 0 0] def\n");
61 = (TT_Header *)FT_Get_Sfnt_Table (face, ft_sfnt_head);
63 lily_cookie_fprintf (out, "/FontBBox [%ld %ld %ld %ld] def\n",
64 ht->xMin *1000L / ht->Units_Per_EM,
65 ht->yMin *1000L / ht->Units_Per_EM,
66 ht->xMax *1000L / ht->Units_Per_EM,
67 ht->yMax *1000L / ht->Units_Per_EM);
69 lily_cookie_fprintf (out, "/FontType 42 def\n");
70 lily_cookie_fprintf (out, "/FontInfo 8 dict dup begin\n");
71 lily_cookie_fprintf (out, "/version (%d.%d) def\n",
72 (ht->Font_Revision >> 16),
73 (ht->Font_Revision &((1 << 16) -1)));
78 lily_cookie_fprintf (out, "/Notice (");
79 fputpss (strings[0], out);
80 lily_cookie_fprintf (out, ") def\n");
84 lily_cookie_fprintf (out, "/FullName (");
85 fputpss (strings[4], out);
86 lily_cookie_fprintf (out, ") def\n");
90 lily_cookie_fprintf (out, "/FamilyName (");
91 fputpss (strings[1], out);
92 lily_cookie_fprintf (out, ") def\n");
96 lily_cookie_fprintf (out, "/isFixedPitch %s def\n",
97 pt->isFixedPitch ? "true" : "false");
98 lily_cookie_fprintf (out, "/UnderlinePosition %ld def\n",
99 pt->underlinePosition *1000L / ht->Units_Per_EM);
100 lily_cookie_fprintf (out, "/UnderlineThickness %ld def\n",
101 pt->underlineThickness *1000L / ht->Units_Per_EM);
102 lily_cookie_fprintf (out, "end readonly def\n");
105 #define CHUNKSIZE 65534
108 print_body (void *out, string name)
110 FILE *fd = fopen (name.c_str (), "rb");
112 static char xdigits[] = "0123456789ABCDEF";
114 unsigned char *buffer;
117 buffer = new unsigned char[CHUNKSIZE];
118 lily_cookie_fprintf (out, "/sfnts [");
121 i = fread (buffer, 1, CHUNKSIZE, fd);
124 lily_cookie_fprintf (out, "\n<");
125 for (j = 0; j < i; j++)
127 if (j != 0 && j % 36 == 0)
128 lily_cookie_putc ('\n', out);
129 /* lily_cookie_fprintf (out,"%02X",(int)buffer[j]) is too slow */
130 lily_cookie_putc (xdigits[ (buffer[j] & 0xF0) >> 4], out);
131 lily_cookie_putc (xdigits[buffer[j] & 0x0F], out);
133 lily_cookie_fprintf (out, "00>"); /* Adobe bug? */
137 lily_cookie_fprintf (out, "\n] def\n");
143 print_trailer (void *out,
146 const int GLYPH_NAME_LEN = 256;
147 char glyph_name[GLYPH_NAME_LEN];
150 = (TT_MaxProfile *)FT_Get_Sfnt_Table (face, ft_sfnt_maxp);
152 lily_cookie_fprintf (out, "/CharStrings %d dict dup begin\n", mp->numGlyphs);
154 Index_to_charcode_map ic_map (make_index_to_charcode_map (face));
156 int output_count = 0;
157 for (int i = 0; i < mp->numGlyphs; i++)
160 if (face->face_flags & FT_FACE_FLAG_GLYPH_NAMES)
162 FT_Error error = FT_Get_Glyph_Name (face, i, glyph_name,
166 programming_error ("print_trailer(): FT_Get_Glyph_Name() returned error");
171 if (!glyph_name[0] && ic_map.find (i) != ic_map.end ())
173 FT_ULong ucode = ic_map[i];
174 get_unicode_name (glyph_name, ucode);
179 lily_cookie_fprintf (out, "/%s %d def ", glyph_name, i);
183 if (! (output_count % 5))
184 lily_cookie_fprintf (out, "\n");
187 lily_cookie_fprintf (out, "end readonly def\n");
188 lily_cookie_fprintf (out, "FontName currentdict end definefont pop\n");
192 create_type42_font (void *out, string name)
194 FT_Face face = open_ft_face (name);
196 print_header (out, face);
197 print_body (out, name);
198 print_trailer (out, face);
204 LY_DEFINE (ly_ttf_ps_name, "ly:ttf-ps-name",
205 1, 0, 0, (SCM ttf_file_name),
206 "Extract the PostScript name from a TrueType font.")
208 SCM_ASSERT_TYPE (scm_is_string (ttf_file_name), ttf_file_name,
209 SCM_ARG1, __FUNCTION__, "string");
210 string file_name = ly_scm2string (ttf_file_name);
211 if (be_verbose_global)
212 progress_indication ("[" + file_name);
214 FT_Face face = open_ft_face (file_name);
215 char const *ps_name_str0 = FT_Get_Postscript_Name (face);
216 SCM ps_name = scm_makfrom0str (ps_name_str0 ? ps_name_str0 : "");
220 if (be_verbose_global)
221 progress_indication ("]");
228 LY_DEFINE (ly_ttf_to_pfa, "ly:ttf->pfa",
229 1, 0, 0, (SCM ttf_file_name),
230 "Convert the contents of a TTF file to Type42 PFA, returning it as "
233 SCM_ASSERT_TYPE (scm_is_string (ttf_file_name), ttf_file_name,
234 SCM_ARG1, __FUNCTION__, "string");
236 string file_name = ly_scm2string (ttf_file_name);
237 if (be_verbose_global)
238 progress_indication ("[" + file_name);
240 Memory_out_stream stream;
242 create_type42_font (&stream, file_name);
243 SCM asscm = scm_from_locale_stringn (stream.get_string (),
244 stream.get_length ());
246 if (be_verbose_global)
247 progress_indication ("]");