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