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