]> git.donarmstrong.com Git - lilypond.git/blob - lily/ttf.cc
(notice): add GPL notice
[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 Han-Wen Nienhuys <hanwen@xs4all.nl>
7
8 */
9
10 #include "freetype.hh"
11
12 #include <freetype/tttables.h>
13
14 #include "lily-proto.hh"
15 #include "memory-stream.hh"
16 #include "warn.hh"
17 #include "lily-guile.hh"
18 #include "main.hh"
19
20
21 /*
22   Based on ttfps by Juliusz Chroboczek
23  */
24 static void
25 print_header (void *out, FT_Face face)
26 {
27   lily_cookie_fprintf (out, "%%!PS-TrueTypeFont\n");
28
29   TT_Postscript *pt =
30     (TT_Postscript*) FT_Get_Sfnt_Table(face, ft_sfnt_post);
31
32   if (pt->maxMemType42)
33     lily_cookie_fprintf (out, "%%%%VMUsage: %ld %ld\n", 0, 0);
34   
35   lily_cookie_fprintf (out, "%d dict begin\n", 11);
36   lily_cookie_fprintf (out, "/FontName /%s def\n",
37            FT_Get_Postscript_Name (face));
38
39   lily_cookie_fprintf (out, "/Encoding StandardEncoding def\n");
40   lily_cookie_fprintf (out, "/PaintType 0 def\n");
41   lily_cookie_fprintf (out, "/FontMatrix [1 0 0 1 0 0] def\n");
42
43   TT_Header *ht =
44     (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head);
45   
46   lily_cookie_fprintf (out, "/FontBBox [%ld %ld %ld %ld] def\n",
47            ht->xMin * 1000L / ht->Units_Per_EM,
48            ht->yMin * 1000L / ht->Units_Per_EM,
49            ht->xMax * 1000L / ht->Units_Per_EM,
50            ht->yMax * 1000L / ht->Units_Per_EM);
51   
52   lily_cookie_fprintf (out, "/FontType 42 def\n");
53   lily_cookie_fprintf (out, "/FontInfo 8 dict dup begin\n");
54   lily_cookie_fprintf (out, "/version (%d.%d) def\n",
55                        (ht->Font_Revision >> 16),
56                        (ht->Font_Revision & ((1 << 16) -1)));
57
58 #if 0
59   if (strings[0])
60     {
61       lily_cookie_fprintf (out, "/Notice (");
62       fputpss (strings[0], out);
63       lily_cookie_fprintf (out, ") def\n");
64     }
65   if (strings[4])
66     {
67       lily_cookie_fprintf (out, "/FullName (");
68       fputpss (strings[4], out);
69       lily_cookie_fprintf (out, ") def\n");
70     }
71   if (strings[1])
72     {
73       lily_cookie_fprintf (out, "/FamilyName (");
74       fputpss (strings[1], out);
75       lily_cookie_fprintf (out, ") def\n");
76     }
77 #endif
78   
79   lily_cookie_fprintf (out, "/isFixedPitch %s def\n",
80            pt->isFixedPitch ? "true" : "false");
81   lily_cookie_fprintf (out, "/UnderlinePosition %ld def\n",
82            pt->underlinePosition * 1000L / ht->Units_Per_EM);
83   lily_cookie_fprintf (out, "/UnderlineThickness %ld def\n",
84            pt->underlineThickness * 1000L / ht->Units_Per_EM);
85   lily_cookie_fprintf (out, "end readonly def\n");
86 }
87
88
89
90 #define CHUNKSIZE 65534
91
92 static void
93 print_body (void *out, String name)
94 {
95   FILE *fd = fopen (name.to_str0 (), "rb");
96   
97   static char xdigits[] = "0123456789ABCDEF";
98
99   unsigned char *buffer;
100   int i, j;
101
102   buffer = new unsigned char[CHUNKSIZE];
103   lily_cookie_fprintf (out, "/sfnts [");
104   for (;;)
105     {
106       i = fread (buffer, 1, CHUNKSIZE, fd);
107       if (i == 0)
108         break;
109       lily_cookie_fprintf (out, "\n<");
110       for (j = 0; j < i; j++)
111         {
112           if (j != 0 && j % 36 == 0)
113             lily_cookie_putc ('\n', out);
114           /* lily_cookie_fprintf (out,"%02X",(int)buffer[j]) is too slow */
115           lily_cookie_putc (xdigits[(buffer[j] & 0xF0) >> 4], out);
116           lily_cookie_putc (xdigits[buffer[j] & 0x0F], out);
117         }
118       lily_cookie_fprintf (out, "00>"); /* Adobe bug? */
119       if (i < CHUNKSIZE)
120         break;
121     }
122   lily_cookie_fprintf (out, "\n] def\n");
123   delete[] buffer;
124   fclose (fd);
125 }
126
127 static void
128 print_trailer (void *out,
129                FT_Face face)
130 {
131   const int GLYPH_NAME_LEN = 256;
132   char glyph_name[GLYPH_NAME_LEN];
133
134   TT_MaxProfile * mp = 
135     (TT_MaxProfile *)FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
136   
137   lily_cookie_fprintf (out, "/CharStrings %d dict dup begin\n", mp->numGlyphs);
138   for (int i = 0; i < mp->numGlyphs; i++)
139     {
140       FT_Error error = FT_Get_Glyph_Name (face, i, glyph_name, GLYPH_NAME_LEN);
141
142       if (error)
143         programming_error ("FT_Get_Glyph_Name() returned error");
144       else
145         lily_cookie_fprintf (out, "/%s %d def ", glyph_name, i);
146
147       if (!(i % 5))
148         lily_cookie_fprintf (out, "\n");
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
164
165 LY_DEFINE (ly_ttf_to_pfa, "ly:ttf->pfa",
166            1, 0, 0, (SCM ttf_file_name),
167            "Convert the contents of a TTF file to Type42 PFA, returning it as "
168            " a string.")
169 {
170   SCM_ASSERT_TYPE (scm_is_string (ttf_file_name), ttf_file_name,
171                    SCM_ARG1, __FUNCTION__, "string");
172
173   String file_name = ly_scm2string (ttf_file_name);
174   if (be_verbose_global)
175     progress_indication ("[" + file_name);
176   
177   Memory_out_stream stream;
178
179   create_type42_font (&stream, file_name);
180   SCM asscm = scm_from_locale_stringn (stream.get_string (),
181                                        stream.get_length ());
182
183   if (be_verbose_global)
184     progress_indication ("]");
185   
186   return asscm;
187 }