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