]> git.donarmstrong.com Git - lilypond.git/blob - lily/ttf.cc
(local-install-outfiles): only create directory if
[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--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "freetype.hh"
10
11 #include <freetype/tttables.h>
12
13 #include "lily-proto.hh"
14 #include "memory-stream.hh"
15 #include "warn.hh"
16 #include "lily-guile.hh"
17 #include "main.hh"
18
19 /*
20   Based on ttfps by Juliusz Chroboczek
21 */
22 static void
23 print_header (void *out, FT_Face face)
24 {
25   lily_cookie_fprintf (out, "%%!PS-TrueTypeFont\n");
26
27   TT_Postscript *pt
28     = (TT_Postscript *) FT_Get_Sfnt_Table (face, ft_sfnt_post);
29
30   if (pt->maxMemType42)
31     lily_cookie_fprintf (out, "%%%%VMUsage: %ld %ld\n", 0, 0);
32
33   lily_cookie_fprintf (out, "%d dict begin\n", 11);
34   lily_cookie_fprintf (out, "/FontName /%s def\n",
35                        FT_Get_Postscript_Name (face));
36
37   lily_cookie_fprintf (out, "/Encoding StandardEncoding def\n");
38   lily_cookie_fprintf (out, "/PaintType 0 def\n");
39   lily_cookie_fprintf (out, "/FontMatrix [1 0 0 1 0 0] def\n");
40
41   TT_Header *ht
42     = (TT_Header *)FT_Get_Sfnt_Table (face, ft_sfnt_head);
43
44   lily_cookie_fprintf (out, "/FontBBox [%ld %ld %ld %ld] def\n",
45                        ht->xMin *1000L / ht->Units_Per_EM,
46                        ht->yMin *1000L / ht->Units_Per_EM,
47                        ht->xMax *1000L / ht->Units_Per_EM,
48                        ht->yMax *1000L / ht->Units_Per_EM);
49
50   lily_cookie_fprintf (out, "/FontType 42 def\n");
51   lily_cookie_fprintf (out, "/FontInfo 8 dict dup begin\n");
52   lily_cookie_fprintf (out, "/version (%d.%d) def\n",
53                        (ht->Font_Revision >> 16),
54                        (ht->Font_Revision &((1 << 16) -1)));
55
56 #if 0
57   if (strings[0])
58     {
59       lily_cookie_fprintf (out, "/Notice (");
60       fputpss (strings[0], out);
61       lily_cookie_fprintf (out, ") def\n");
62     }
63   if (strings[4])
64     {
65       lily_cookie_fprintf (out, "/FullName (");
66       fputpss (strings[4], out);
67       lily_cookie_fprintf (out, ") def\n");
68     }
69   if (strings[1])
70     {
71       lily_cookie_fprintf (out, "/FamilyName (");
72       fputpss (strings[1], out);
73       lily_cookie_fprintf (out, ") def\n");
74     }
75 #endif
76
77   lily_cookie_fprintf (out, "/isFixedPitch %s def\n",
78                        pt->isFixedPitch ? "true" : "false");
79   lily_cookie_fprintf (out, "/UnderlinePosition %ld def\n",
80                        pt->underlinePosition *1000L / ht->Units_Per_EM);
81   lily_cookie_fprintf (out, "/UnderlineThickness %ld def\n",
82                        pt->underlineThickness *1000L / ht->Units_Per_EM);
83   lily_cookie_fprintf (out, "end readonly def\n");
84 }
85
86 #define CHUNKSIZE 65534
87
88 static void
89 print_body (void *out, String name)
90 {
91   FILE *fd = fopen (name.to_str0 (), "rb");
92
93   static char xdigits[] = "0123456789ABCDEF";
94
95   unsigned char *buffer;
96   int i, j;
97
98   buffer = new unsigned char[CHUNKSIZE];
99   lily_cookie_fprintf (out, "/sfnts [");
100   for (;;)
101     {
102       i = fread (buffer, 1, CHUNKSIZE, fd);
103       if (i == 0)
104         break;
105       lily_cookie_fprintf (out, "\n<");
106       for (j = 0; j < i; j++)
107         {
108           if (j != 0 && j % 36 == 0)
109             lily_cookie_putc ('\n', out);
110           /* lily_cookie_fprintf (out,"%02X",(int)buffer[j]) is too slow */
111           lily_cookie_putc (xdigits[ (buffer[j] & 0xF0) >> 4], out);
112           lily_cookie_putc (xdigits[buffer[j] & 0x0F], out);
113         }
114       lily_cookie_fprintf (out, "00>"); /* Adobe bug? */
115       if (i < CHUNKSIZE)
116         break;
117     }
118   lily_cookie_fprintf (out, "\n] def\n");
119   delete[] buffer;
120   fclose (fd);
121 }
122
123 static void
124 print_trailer (void *out,
125                FT_Face face)
126 {
127   const int GLYPH_NAME_LEN = 256;
128   char glyph_name[GLYPH_NAME_LEN];
129
130   TT_MaxProfile *mp
131     = (TT_MaxProfile *)FT_Get_Sfnt_Table (face, ft_sfnt_maxp);
132
133   lily_cookie_fprintf (out, "/CharStrings %d dict dup begin\n", mp->numGlyphs);
134
135
136   if (face->face_flags & FT_FACE_FLAG_GLYPH_NAMES)
137     for (int i = 0; i < mp->numGlyphs; i++)
138       {
139         FT_Error error = FT_Get_Glyph_Name (face, i, glyph_name,
140                                             GLYPH_NAME_LEN);
141         if (error)
142           programming_error ("print_trailer(): FT_Get_Glyph_Name() returned error");
143         else
144           lily_cookie_fprintf (out, "/%s %d def ", glyph_name, i);
145
146         if (! (i % 5))
147           lily_cookie_fprintf (out, "\n");
148       }
149
150   lily_cookie_fprintf (out, "end readonly def\n");
151   lily_cookie_fprintf (out, "FontName currentdict end definefont pop\n");
152 }
153
154 static void
155 create_type42_font (void *out, String name)
156 {
157   FT_Face face = open_ft_face (name);
158
159   print_header (out, face);
160   print_body (out, name);
161   print_trailer (out, face);
162
163   FT_Done_Face (face);
164 }
165
166 LY_DEFINE (ly_font_glyph_list, "ly:font-glyph-list",
167            1, 0, 0, (SCM font_file_name),
168            "Return a list of glyphnames for @var{font-file-name}.")
169 {
170   SCM_ASSERT_TYPE (scm_is_string (font_file_name), font_file_name,
171                    SCM_ARG1, __FUNCTION__, "string");
172
173   String file_name = ly_scm2string (font_file_name);
174   if (be_verbose_global)
175     progress_indication ("[" + file_name);
176
177   SCM retval = SCM_EOL;
178   SCM *tail = &retval;
179   
180   FT_Face face = open_ft_face (file_name);
181   for (int i = 0; i < face->num_glyphs; i++)
182     {
183       const int len = 256;
184       char name[len];
185       int code = FT_Get_Glyph_Name (face, i, name, len);
186       if (code)
187         warning (_f ("FT_Get_Glyph_Name() returned error: %d", code));
188
189       *tail = scm_cons (scm_makfrom0str (name), SCM_EOL);
190       tail = SCM_CDRLOC (*tail);
191     }
192   
193   FT_Done_Face (face);
194
195   if (be_verbose_global)
196     progress_indication ("]");  
197   return retval;
198 }
199
200 LY_DEFINE (ly_ttf_ps_name, "ly:ttf-ps-name",
201            1, 0, 0, (SCM ttf_file_name),
202            "Extract the PostScript name from a TrueType font.")
203 {
204   SCM_ASSERT_TYPE (scm_is_string (ttf_file_name), ttf_file_name,
205                    SCM_ARG1, __FUNCTION__, "string");
206   String file_name = ly_scm2string (ttf_file_name);
207   if (be_verbose_global)
208     progress_indication ("[" + file_name);
209
210   FT_Face face = open_ft_face (file_name);
211   char const *ps_name_str0 = FT_Get_Postscript_Name (face);
212   
213   FT_Done_Face (face);
214   
215   if (be_verbose_global)
216     progress_indication ("]");
217
218   return scm_makfrom0str (ps_name_str0 ? ps_name_str0 : "");
219 }
220
221
222
223 LY_DEFINE (ly_ttf_to_pfa, "ly:ttf->pfa",
224            1, 0, 0, (SCM ttf_file_name),
225            "Convert the contents of a TTF file to Type42 PFA, returning it as "
226            " a string.")
227 {
228   SCM_ASSERT_TYPE (scm_is_string (ttf_file_name), ttf_file_name,
229                    SCM_ARG1, __FUNCTION__, "string");
230
231   String file_name = ly_scm2string (ttf_file_name);
232   if (be_verbose_global)
233     progress_indication ("[" + file_name);
234
235   Memory_out_stream stream;
236
237   create_type42_font (&stream, file_name);
238   SCM asscm = scm_from_locale_stringn (stream.get_string (),
239                                        stream.get_length ());
240
241   if (be_verbose_global)
242     progress_indication ("]");
243
244   return asscm;
245 }