]> git.donarmstrong.com Git - lilypond.git/blob - lily/ttf.cc
Merge branch 'master' into lilypond/translation
[lilypond.git] / lily / ttf.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2005--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <cstdio>
21 #include "freetype.hh"
22
23 #include <freetype/tttables.h>
24
25 #include "international.hh"
26 #include "memory-stream.hh"
27 #include "warn.hh"
28 #include "lily-guile.hh"
29 #include "main.hh"
30 #include "open-type-font.hh"
31
32
33 Index_to_charcode_map
34 make_index_to_charcode_map (FT_Face face)
35 {
36   Index_to_charcode_map m;
37   FT_ULong charcode;
38   FT_UInt gindex;
39
40   FT_CharMap current_cmap = face->charmap;
41   FT_Select_Charmap (face, FT_ENCODING_UNICODE);
42
43   int j = 0;
44   for (charcode = FT_Get_First_Char (face, &gindex); gindex != 0;
45        charcode = FT_Get_Next_Char (face, charcode, &gindex))
46     {
47       m[gindex] = charcode;
48       j ++;
49     }
50   FT_Set_Charmap (face, current_cmap);
51
52   return m;
53 }
54
55 /*
56   Based on ttfps by Juliusz Chroboczek
57 */
58 static void
59 print_header (void *out, FT_Face face)
60 {
61   lily_cookie_fprintf (out, "%%!PS-TrueTypeFont\n");
62
63   TT_Postscript *pt
64     = (TT_Postscript *) FT_Get_Sfnt_Table (face, ft_sfnt_post);
65
66   if (pt->maxMemType42)
67     lily_cookie_fprintf (out, "%%%%VMUsage: %d %d\n", 0, 0);
68
69   lily_cookie_fprintf (out, "%d dict begin\n", 11);
70   lily_cookie_fprintf (out, "/FontName /%s def\n",
71                        FT_Get_Postscript_Name (face));
72
73   lily_cookie_fprintf (out, "/Encoding StandardEncoding def\n");
74   lily_cookie_fprintf (out, "/PaintType 0 def\n");
75   lily_cookie_fprintf (out, "/FontMatrix [1 0 0 1 0 0] def\n");
76
77   TT_Header *ht
78     = (TT_Header *)FT_Get_Sfnt_Table (face, ft_sfnt_head);
79
80   lily_cookie_fprintf (out, "/FontBBox [%lf %lf %lf %lf] def\n",
81                        float (ht->xMin) / float (ht->Units_Per_EM),
82                        float (ht->yMin) / float (ht->Units_Per_EM),
83                        float (ht->xMax) / float (ht->Units_Per_EM),
84                        float (ht->yMax) / float (ht->Units_Per_EM));
85
86   lily_cookie_fprintf (out, "/FontType 42 def\n");
87   lily_cookie_fprintf (out, "/FontInfo 8 dict dup begin\n");
88   lily_cookie_fprintf (out, "/version (%.3f) def\n",
89                        ht->Font_Revision / 65536.0);
90
91 #if 0
92   if (strings[0])
93     {
94       lily_cookie_fprintf (out, "/Notice (");
95       fputpss (strings[0], out);
96       lily_cookie_fprintf (out, ") def\n");
97     }
98   if (strings[4])
99     {
100       lily_cookie_fprintf (out, "/FullName (");
101       fputpss (strings[4], out);
102       lily_cookie_fprintf (out, ") def\n");
103     }
104   if (strings[1])
105     {
106       lily_cookie_fprintf (out, "/FamilyName (");
107       fputpss (strings[1], out);
108       lily_cookie_fprintf (out, ") def\n");
109     }
110 #endif
111
112   lily_cookie_fprintf (out, "/isFixedPitch %s def\n",
113                        pt->isFixedPitch ? "true" : "false");
114   lily_cookie_fprintf (out, "/UnderlinePosition %lf def\n",
115                        float (pt->underlinePosition)
116                        / float (ht->Units_Per_EM));
117   lily_cookie_fprintf (out, "/UnderlineThickness %lf def\n",
118                        float (pt->underlineThickness)
119                        / float (ht->Units_Per_EM));
120   lily_cookie_fprintf (out, "end readonly def\n");
121 }
122
123 #define CHUNKSIZE 65534
124
125 const FT_ULong FT_ENC_TAG (glyf_tag, 'g', 'l', 'y', 'f');
126 const FT_ULong FT_ENC_TAG (head_tag, 'h', 'e', 'a', 'd');
127 const FT_ULong FT_ENC_TAG (loca_tag, 'l', 'o', 'c', 'a');
128
129 static
130 void t42_write_table (void *out, FT_Face face, unsigned char const *buffer,
131                       size_t s, bool is_glyf,
132                       FT_ULong head_length, FT_ULong loca_length)
133 {
134   vector<FT_UShort> chunks;
135
136   if (is_glyf)
137     {
138       /* compute chunk sizes */
139       unsigned char *head_buf = new unsigned char[head_length];
140       FT_Error error = FT_Load_Sfnt_Table (face, head_tag, 0, head_buf, NULL);
141       if (error)
142         programming_error ("FT_Load_Sfnt_Table (): error.");
143
144       /* we access the lower byte of indexToLocFormat */
145       bool long_offsets = head_buf[4*4 + 2*2 + 2*8 + 4*2 + 3*2 + 1] == 1;
146
147       delete[] head_buf;
148
149       unsigned char *loca_buf = new unsigned char[loca_length];
150       error = FT_Load_Sfnt_Table (face, loca_tag, 0, loca_buf, NULL);
151       if (error)
152         programming_error ("FT_Load_Sfnt_Table (): error.");
153
154       unsigned char *p = loca_buf;
155       unsigned char *endp = loca_buf + loca_length;
156
157       FT_ULong offset = 0, last_offset = 0, last_chunk = 0;
158       while (p < endp)
159       {
160         if (long_offsets)
161           {
162             offset = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
163             p += 4;
164           }
165         else
166           {
167             offset = ((p[0] << 8) | p[1]) << 1;
168             p += 2;
169           }
170         if (offset > last_offset + CHUNKSIZE)
171           {
172             if (last_chunk != last_offset)
173               chunks.push_back (FT_UShort (last_offset - last_chunk));
174             /*
175               a single glyph with more than 64k data
176               is a pathological case but...
177              */
178             FT_ULong rest = offset - last_offset;
179             while (rest > CHUNKSIZE)
180               {
181                 chunks.push_back (CHUNKSIZE);
182                 rest -= CHUNKSIZE;
183               }
184             chunks.push_back (FT_UShort (rest));
185             last_chunk = offset;
186           }
187         else if (offset > last_chunk + CHUNKSIZE)
188           {
189             chunks.push_back (FT_UShort (last_offset - last_chunk));
190             last_chunk = last_offset;
191           }
192
193         last_offset = offset;
194       }
195       chunks.push_back (FT_UShort (s - last_chunk));
196
197       delete[] loca_buf;
198     }
199   else if (s > CHUNKSIZE)
200     {
201       FT_ULong rest = s;
202       while (rest > CHUNKSIZE)
203         {
204           chunks.push_back (CHUNKSIZE);
205           rest -= CHUNKSIZE;
206         }
207       chunks.push_back (FT_UShort (rest));
208     }
209   else
210     chunks.push_back (CHUNKSIZE);
211
212   lily_cookie_fprintf (out, "\n"
213                             " <");
214
215   int l = 0;
216   static char xdigits[] = "0123456789ABCDEF";
217
218   int cur_chunk_idx = 0;
219   for (size_t j = 0; j < s; j++)
220     {
221       if (l >= chunks[cur_chunk_idx])
222         {
223           lily_cookie_fprintf (out, "\n"
224                                     " 00>\n"
225                                     " <");
226           l = 0;
227           cur_chunk_idx ++;
228         }
229
230       if (l % 31 == 0)
231         lily_cookie_fprintf (out, "\n"
232                                   "  ");
233
234       /* lily_cookie_fprintf (out,"%02X",(int)buffer[j]) is too slow */
235       lily_cookie_putc (xdigits[(buffer[j] & 0xF0) >> 4], out);
236       lily_cookie_putc (xdigits[buffer[j] & 0x0F], out);
237
238       l ++;
239     }
240
241   /* pad to four-byte boundary */
242   while ((s ++) % 4 != 0)
243     lily_cookie_fprintf (out, "00");
244
245   lily_cookie_fprintf (out, "\n"
246                             "  00\n"
247                             " >");
248 }
249
250 static void
251 print_body (void *out, FT_Face face)
252 {
253   FT_UInt idx = 0;
254   FT_ULong head_length = 0, loca_length = 0;
255   FT_ULong tag, length;
256   vector<FT_ULong> lengths, tags;
257
258   /*
259     we must build our own TTF header -- the original font
260     might be a TTC where tables are not contiguous, or the font
261     contains tables which aren't indexed at all
262    */
263   while (FT_Sfnt_Table_Info (face, idx, &tag, &length)
264          != FT_Err_Table_Missing)
265   {
266     lengths.push_back (length);
267     tags.push_back (tag);
268     if (tag == head_tag)
269       head_length = length;
270     else if (tag == loca_tag)
271       loca_length = length;
272     idx ++;
273   }
274
275   FT_ULong hlength = 12 + 16 * idx;
276
277   unsigned char *hbuf = new unsigned char[hlength];
278   unsigned char *p;
279
280   hbuf[0] = 0x00;                                       /* version */
281   hbuf[1] = 0x01;
282   hbuf[2] = 0x00;
283   hbuf[3] = 0x00;
284   hbuf[4] = (unsigned char) ((idx & 0xFF00) >> 8);      /* numTables */
285   hbuf[5] = idx & 0x00FF;
286
287   FT_UInt searchRange, entrySelector, rangeShift;
288   FT_UInt i, j;
289   for (i = 1, j = 2; j <= idx; i++, j <<= 1)
290     ;
291   entrySelector = i - 1;
292   searchRange = 0x10 << entrySelector;
293   rangeShift = (idx << 4) - searchRange;
294
295   hbuf[6] = (unsigned char) ((searchRange & 0xFF00) >> 8);
296   hbuf[7] = searchRange & 0x00FF;
297   hbuf[8] = (unsigned char) ((entrySelector & 0xFF00) >> 8);
298   hbuf[9] = entrySelector & 0x00FF;
299   hbuf[10] = (unsigned char) ((rangeShift & 0xFF00) >> 8);
300   hbuf[11] = rangeShift & 0x00FF;
301
302   p = &hbuf[12];
303
304   FT_ULong checksum, font_checksum = 0;
305
306   FT_ULong offset = hlength;            /* first table offset */
307
308   for (FT_UInt i = 0; i < idx; i++)
309   {
310     /* here, the buffer length must be a multiple of 4 */
311     FT_ULong len = (lengths[i] + 3) & ~3;
312     unsigned char *buf = new unsigned char[len];
313
314     buf[len - 1] = 0x00;                /* assure padding with zeros */
315     buf[len - 2] = 0x00;
316     buf[len - 3] = 0x00;
317
318     FT_Error error = FT_Load_Sfnt_Table (face, tags[i], 0, buf, NULL);
319     if (error)
320       programming_error ("FT_Load_Sfnt_Table (): error.");
321
322     if (tag == head_tag)
323       {
324         /*
325           first pass of computing the font checksum
326           needs checkSumAdjustment = 0
327          */
328         buf[8] = 0x00;
329         buf[9] = 0x00;
330         buf[10] = 0x00;
331         buf[11] = 0x00;
332       }
333
334     checksum = 0;
335     unsigned char *endq = buf + len;
336     for (unsigned char *q = buf; q < endq; q += 4)
337       checksum += (q[0] << 24) | (q[1] << 16) | (q[2] << 8) | q[3];
338     font_checksum += checksum;
339
340     delete[] buf;
341
342     *(p++) = (unsigned char) ((tags[i] & 0xFF000000UL) >> 24);
343     *(p++) = (unsigned char) ((tags[i] & 0x00FF0000UL) >> 16);
344     *(p++) = (unsigned char) ((tags[i] & 0x0000FF00UL) >> 8);
345     *(p++) = tags[i] & 0x000000FFUL;
346
347     *(p++) = (unsigned char) ((checksum & 0xFF000000UL) >> 24);
348     *(p++) = (unsigned char) ((checksum & 0x00FF0000UL) >> 16);
349     *(p++) = (unsigned char) ((checksum & 0x0000FF00UL) >> 8);
350     *(p++) = checksum & 0x000000FFUL;
351
352     *(p++) = (unsigned char) ((offset & 0xFF000000UL) >> 24);
353     *(p++) = (unsigned char) ((offset & 0x00FF0000UL) >> 16);
354     *(p++) = (unsigned char) ((offset & 0x0000FF00UL) >> 8);
355     *(p++) = offset & 0x000000FFUL;
356
357     *(p++) = (unsigned char) ((lengths[i] & 0xFF000000UL) >> 24);
358     *(p++) = (unsigned char) ((lengths[i] & 0x00FF0000UL) >> 16);
359     *(p++) = (unsigned char) ((lengths[i] & 0x0000FF00UL) >> 8);
360     *(p++) = lengths[i] & 0x000000FFUL;
361
362     /* offset must be a multiple of 4 */
363     offset += (lengths[i] + 3) & ~3;
364   }
365
366   /* add checksum of TTF header */
367   checksum = 0;
368   for (unsigned char *q = hbuf; q < p; q += 4)
369     checksum += (q[0] << 24) | (q[1] << 16) | (q[2] << 8) | q[3];
370   font_checksum += checksum;
371   font_checksum = 0xB1B0AFBAUL - font_checksum;
372
373   /*
374     see Adobe technical note 5012.Type42_Spec.pdf for details how
375     the /sfnts array must be constructed
376    */
377   lily_cookie_fprintf (out, "/sfnts [");
378   t42_write_table (out, face, hbuf, hlength, false,
379                    head_length, loca_length);
380   delete[] hbuf;
381
382   idx = 0;
383
384   while (FT_Sfnt_Table_Info (face, idx, &tag, &length)
385          != FT_Err_Table_Missing)
386     {
387       unsigned char *buf = new unsigned char[length];
388       FT_Error error = FT_Load_Sfnt_Table (face, tag, 0, buf, NULL);
389       if (error)
390         programming_error ("FT_Load_Sfnt_Table (): error.");
391
392       if (tag == head_tag)
393         {
394           /* in the second pass simply store the computed font checksum */
395           buf[8] = (unsigned char) ((font_checksum & 0xFF000000UL) >> 24);
396           buf[9] = (unsigned char) ((font_checksum & 0x00FF0000UL) >> 16);
397           buf[10] = (unsigned char) ((font_checksum & 0x0000FF00UL) >> 8);
398           buf[11] = font_checksum & 0x000000FFUL;
399         }
400
401       bool is_glyf_table = tag == glyf_tag && length > CHUNKSIZE;
402       t42_write_table (out, face, buf, length, is_glyf_table,
403                        head_length, loca_length);
404
405       delete[] buf;
406       idx ++;
407     }
408   lily_cookie_fprintf (out, "\n] def\n");
409 }
410
411 static void
412 print_trailer (void *out,
413                FT_Face face)
414 {
415   const int GLYPH_NAME_LEN = 256;
416   char glyph_name[GLYPH_NAME_LEN];
417
418   TT_MaxProfile *mp
419     = (TT_MaxProfile *)FT_Get_Sfnt_Table (face, ft_sfnt_maxp);
420
421   lily_cookie_fprintf (out, "/CharStrings %d dict dup begin\n", mp->numGlyphs);
422
423   Index_to_charcode_map ic_map (make_index_to_charcode_map (face));
424
425   int output_count = 0;
426   for (int i = 0; i < mp->numGlyphs; i++)
427     {
428       glyph_name[0] = 0;
429       if (face->face_flags & FT_FACE_FLAG_GLYPH_NAMES)
430         {
431           FT_Error error = FT_Get_Glyph_Name (face, i, glyph_name,
432                                               GLYPH_NAME_LEN);
433           if (error)
434             {
435               programming_error ("FT_Get_Glyph_Name (): error.");
436               glyph_name[0] = 0;
437             }
438         }
439
440       if (!glyph_name[0] && ic_map.find (i) != ic_map.end ())
441         {
442           FT_ULong ucode = ic_map[i];
443           get_unicode_name (glyph_name, ucode);
444         }
445
446       if (i == 0)
447         sprintf (glyph_name, ".notdef");
448       else if (glyph_name == string (".notdef"))
449         glyph_name[0] = '\0';
450
451       if (!glyph_name[0])
452         get_glyph_index_name (glyph_name, i);
453
454       if (glyph_name[0])
455         {
456           lily_cookie_fprintf (out, "/%s %d def ", glyph_name, i);
457           output_count ++;
458         }
459       else
460         programming_error (to_string ("no name for glyph %d", i));
461                         
462       if (! (output_count % 5))
463         lily_cookie_fprintf (out, "\n");
464     }
465
466   lily_cookie_fprintf (out, "end readonly def\n");
467   lily_cookie_fprintf (out, "FontName currentdict end definefont pop\n");
468 }
469
470 static void
471 create_type42_font (void *out, string name, int idx)
472 {
473   FT_Face face;
474
475   /* check whether font index is valid */
476   if (idx > 0)
477     {
478       face = open_ft_face (name, -1);
479       if (idx >= face->num_faces)
480         {
481           warning (_f ("font index %d too large for font `%s', using index 0",
482                        idx, name.c_str()));
483           idx = 0;
484         }
485       FT_Done_Face (face);
486     }
487
488   face = open_ft_face (name, idx);
489
490   print_header (out, face);
491   print_body (out, face);
492   print_trailer (out, face);
493
494   FT_Done_Face (face);
495 }
496
497 LY_DEFINE (ly_ttf_ps_name, "ly:ttf-ps-name",
498            1, 1, 0, (SCM ttf_file_name, SCM idx),
499            "Extract the PostScript name from a TrueType font.  The optional"
500            " @var{idx} argument is useful for TrueType collections (TTC)"
501            " only; it specifies the font index within the TTC.  The default"
502            " value of @var{idx} is@tie{}0.")
503 {
504   LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
505
506   int i = 0;
507   if (idx != SCM_UNDEFINED)
508     {
509       LY_ASSERT_TYPE (scm_is_integer, idx, 2);
510       i = scm_to_int (idx);
511       if (i < 0)
512         {
513           warning (_ ("font index must be non-negative, using index 0"));
514           i = 0;
515         }
516     }
517
518   string file_name = ly_scm2string (ttf_file_name);
519   if (be_verbose_global)
520     progress_indication ("\n[" + file_name);
521
522   FT_Face face;
523
524   /* check whether font index is valid */
525   if (i > 0)
526     {
527       face = open_ft_face (file_name, -1);
528       if (i >= face->num_faces)
529         {
530           warning (_f ("font index %d too large for font `%s', using index 0",
531                        i, file_name.c_str()));
532           i = 0;
533         }
534       FT_Done_Face (face);
535     }
536
537   face = open_ft_face (file_name, i);
538   char const *ps_name_str0 = FT_Get_Postscript_Name (face);
539   SCM ps_name = scm_from_locale_string (ps_name_str0 ? ps_name_str0 : "");
540   FT_Done_Face (face);
541
542   if (be_verbose_global)
543     progress_indication ("]");
544
545   return ps_name;
546 }
547
548 LY_DEFINE (ly_ttf_2_pfa, "ly:ttf->pfa",
549            1, 1, 0, (SCM ttf_file_name, SCM idx),
550            "Convert the contents of a TrueType font file to PostScript"
551            " Type@tie{}42 font, returning it as a string.  The optional"
552            " @var{idx} argument is useful for TrueType collections (TTC)"
553            " only; it specifies the font index within the TTC.  The default"
554            " value of @var{idx} is@tie{}0.")
555 {
556   LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
557
558   int i = 0;
559   if (idx != SCM_UNDEFINED)
560     {
561       LY_ASSERT_TYPE (scm_is_integer, idx, 2);
562       i = scm_to_int (idx);
563       if (i < 0)
564         {
565           warning (_ ("font index must be non-negative, using index 0"));
566           i = 0;
567         }
568     }
569
570   string file_name = ly_scm2string (ttf_file_name);
571   if (be_verbose_global)
572     progress_indication ("\n[" + file_name);
573
574   Memory_out_stream stream;
575
576   create_type42_font (&stream, file_name, i);
577   SCM asscm = scm_from_locale_stringn (stream.get_string (),
578                                        stream.get_length ());
579
580   if (be_verbose_global)
581     progress_indication ("]");
582
583   return asscm;
584 }