]> git.donarmstrong.com Git - lilypond.git/blob - lily/ttf.cc
Merge branch 'master' of ssh://hanwen@git.sv.gnu.org/srv/git/lilypond
[lilypond.git] / lily / ttf.cc
1 /*
2   ttf.cc --  implement ttf -> pfa routine.
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "freetype.hh"
10
11 #include <freetype/tttables.h>
12
13 #include "memory-stream.hh"
14 #include "warn.hh"
15 #include "lily-guile.hh"
16 #include "main.hh"
17 #include "open-type-font.hh"
18
19
20 Index_to_charcode_map
21 make_index_to_charcode_map (FT_Face face)
22 {
23   Index_to_charcode_map m;
24   FT_ULong charcode;
25   FT_UInt gindex;
26
27   FT_CharMap current_cmap = face->charmap;
28   FT_Select_Charmap (face, FT_ENCODING_UNICODE);
29
30   int j = 0;
31   for (charcode = FT_Get_First_Char (face, &gindex); gindex != 0;
32        charcode = FT_Get_Next_Char (face, charcode, &gindex))
33     {
34       m[gindex] = charcode;
35       j++;
36     }
37   FT_Set_Charmap (face, current_cmap);
38
39   
40   return m;
41 }
42
43 /*
44   Based on ttfps by Juliusz Chroboczek
45 */
46 static void
47 print_header (void *out, FT_Face face)
48 {
49   lily_cookie_fprintf (out, "%%!PS-TrueTypeFont\n");
50
51   TT_Postscript *pt
52     = (TT_Postscript *) FT_Get_Sfnt_Table (face, ft_sfnt_post);
53
54   if (pt->maxMemType42)
55     lily_cookie_fprintf (out, "%%%%VMUsage: %d %d\n", 0, 0);
56
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));
60
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");
64
65   TT_Header *ht
66     = (TT_Header *)FT_Get_Sfnt_Table (face, ft_sfnt_head);
67
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);
73
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)));
79
80 #if 0
81   if (strings[0])
82     {
83       lily_cookie_fprintf (out, "/Notice (");
84       fputpss (strings[0], out);
85       lily_cookie_fprintf (out, ") def\n");
86     }
87   if (strings[4])
88     {
89       lily_cookie_fprintf (out, "/FullName (");
90       fputpss (strings[4], out);
91       lily_cookie_fprintf (out, ") def\n");
92     }
93   if (strings[1])
94     {
95       lily_cookie_fprintf (out, "/FamilyName (");
96       fputpss (strings[1], out);
97       lily_cookie_fprintf (out, ") def\n");
98     }
99 #endif
100
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");
108 }
109
110 #define CHUNKSIZE 65534
111
112 static void
113 print_body (void *out, string name)
114 {
115   FILE *fd = fopen (name.c_str (), "rb");
116
117   static char xdigits[] = "0123456789ABCDEF";
118
119   unsigned char *buffer;
120   int i, j;
121
122   buffer = new unsigned char[CHUNKSIZE];
123   lily_cookie_fprintf (out, "/sfnts [");
124   for (;;)
125     {
126       i = fread (buffer, 1, CHUNKSIZE, fd);
127       if (i == 0)
128         break;
129       lily_cookie_fprintf (out, "\n<");
130       for (j = 0; j < i; j++)
131         {
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);
137         }
138       lily_cookie_fprintf (out, "00>"); /* Adobe bug? */
139       if (i < CHUNKSIZE)
140         break;
141     }
142   lily_cookie_fprintf (out, "\n] def\n");
143   delete[] buffer;
144   fclose (fd);
145 }
146
147 #if 0
148 static
149 void t42_write_sting (void *out, unsigned char const * buffer, size_t s)
150 {
151   lily_cookie_fprintf (out, "\n<");
152   int l = 0;
153   static char xdigits[] = "0123456789ABCDEF";
154   for (size_t j = 0; j < s; j++)
155     {
156       if (j != 0 && j % 36 == 0)
157         lily_cookie_putc ('\n', out);
158
159       if (l ++ >= CHUNKSIZE)
160         lily_cookie_fprintf (out, "00>\n<");
161
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);
165     }
166   lily_cookie_fprintf (out, "00>");     /* Adobe bug? */
167 }
168
169
170 static void
171 new_print_body (void *out,  FT_Face face)
172 {
173   FT_UInt idx = 0;
174
175   FT_ULong tag, length;
176   
177   lily_cookie_fprintf (out, "/sfnts [");
178   while (FT_Sfnt_Table_Info(face, idx, &tag, &length)!=
179          FT_Err_Table_Missing)
180     {
181       unsigned char *buf = new unsigned char[length];
182       FT_Error error = FT_Load_Sfnt_Table(face, tag, 0, buf, NULL); 
183
184       t42_write_sting (out, buf, length);
185
186       delete[] buf;
187       idx ++;
188     }
189   lily_cookie_fprintf (out, "\n] def\n");
190 }
191 #endif
192
193 static void
194 print_trailer (void *out,
195                FT_Face face)
196 {
197   const int GLYPH_NAME_LEN = 256;
198   char glyph_name[GLYPH_NAME_LEN];
199
200   TT_MaxProfile *mp
201     = (TT_MaxProfile *)FT_Get_Sfnt_Table (face, ft_sfnt_maxp);
202
203   lily_cookie_fprintf (out, "/CharStrings %d dict dup begin\n", mp->numGlyphs);
204
205   Index_to_charcode_map ic_map (make_index_to_charcode_map (face));
206
207   int output_count = 0;
208   for (int i = 0; i < mp->numGlyphs; i++)
209     {
210       glyph_name[0] = 0;
211       if (face->face_flags & FT_FACE_FLAG_GLYPH_NAMES)
212         {
213           FT_Error error = FT_Get_Glyph_Name (face, i, glyph_name,
214                                               GLYPH_NAME_LEN);
215           if (error)
216             {
217               programming_error ("FT_Get_Glyph_Name (): error.");
218               glyph_name[0] = 0;
219             }
220         }
221
222       if (!glyph_name[0] && ic_map.find (i) != ic_map.end ())
223         {
224           FT_ULong ucode = ic_map[i];
225           get_unicode_name (glyph_name, ucode);
226         }
227
228       if (glyph_name == string (".notdef"))
229         glyph_name[0] = '\0';
230
231       
232       if (!glyph_name[0])
233         {
234           get_glyph_index_name (glyph_name, i);
235         }
236       
237       if (glyph_name[0])
238         {
239           lily_cookie_fprintf (out, "/%s %d def ", glyph_name, i);
240           output_count ++;
241         }
242       else
243         {
244           programming_error (to_string ("no name for glyph %d", i));
245         }
246                              
247       if (! (output_count % 5))
248         lily_cookie_fprintf (out, "\n");
249     }
250
251   lily_cookie_fprintf (out, "end readonly def\n");
252   lily_cookie_fprintf (out, "FontName currentdict end definefont pop\n");
253 }
254
255 static void
256 create_type42_font (void *out, string name)
257 {
258   FT_Face face = open_ft_face (name);
259
260   print_header (out, face);
261   // new_print_body (out, face);
262   print_body (out, name);
263   print_trailer (out, face);
264
265   FT_Done_Face (face);
266 }
267
268
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.")
272 {
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);
277
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 : "");
281   
282   FT_Done_Face (face);
283   
284   if (be_verbose_global)
285     progress_indication ("]");
286   
287   return ps_name;
288 }
289
290
291
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 "
295            " a string.")
296 {
297   LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
298
299   string file_name = ly_scm2string (ttf_file_name);
300   if (be_verbose_global)
301     progress_indication ("[" + file_name);
302
303   Memory_out_stream stream;
304
305   create_type42_font (&stream, file_name);
306   SCM asscm = scm_from_locale_stringn (stream.get_string (),
307                                        stream.get_length ());
308
309   if (be_verbose_global)
310     progress_indication ("]");
311
312   return asscm;
313 }