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