Merge branch 'master' of git.sv.gnu.org:/srv/git/lilypond
[lilypond/mpolesky.git] / lily / ttf.cc
blobfc75e719fb56b61af4da4e078902c31c06c1eca1
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2005--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
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.
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.
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/>.
20 #include <cstdio>
21 #include "freetype.hh"
23 #include <freetype/tttables.h>
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"
33 Index_to_charcode_map
34 make_index_to_charcode_map (FT_Face face)
36 Index_to_charcode_map m;
37 FT_ULong charcode;
38 FT_UInt gindex;
40 FT_CharMap current_cmap = face->charmap;
41 FT_Select_Charmap (face, FT_ENCODING_UNICODE);
43 int j = 0;
44 for (charcode = FT_Get_First_Char (face, &gindex); gindex != 0;
45 charcode = FT_Get_Next_Char (face, charcode, &gindex))
47 m[gindex] = charcode;
48 j ++;
50 FT_Set_Charmap (face, current_cmap);
52 return m;
56 Based on ttfps by Juliusz Chroboczek
58 static void
59 print_header (void *out, FT_Face face)
61 lily_cookie_fprintf (out, "%%!PS-TrueTypeFont\n");
63 TT_Postscript *pt
64 = (TT_Postscript *) FT_Get_Sfnt_Table (face, ft_sfnt_post);
66 if (pt->maxMemType42)
67 lily_cookie_fprintf (out, "%%%%VMUsage: %d %d\n", 0, 0);
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));
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");
77 TT_Header *ht
78 = (TT_Header *)FT_Get_Sfnt_Table (face, ft_sfnt_head);
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));
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);
91 #if 0
92 if (strings[0])
94 lily_cookie_fprintf (out, "/Notice (");
95 fputpss (strings[0], out);
96 lily_cookie_fprintf (out, ") def\n");
98 if (strings[4])
100 lily_cookie_fprintf (out, "/FullName (");
101 fputpss (strings[4], out);
102 lily_cookie_fprintf (out, ") def\n");
104 if (strings[1])
106 lily_cookie_fprintf (out, "/FamilyName (");
107 fputpss (strings[1], out);
108 lily_cookie_fprintf (out, ") def\n");
110 #endif
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");
123 #define CHUNKSIZE 65534
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');
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)
134 vector<FT_UShort> chunks;
136 if (is_glyf)
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.");
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;
147 delete[] head_buf;
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.");
154 unsigned char *p = loca_buf;
155 unsigned char *endp = loca_buf + loca_length;
157 FT_ULong offset = 0, last_offset = 0, last_chunk = 0;
158 while (p < endp)
160 if (long_offsets)
162 offset = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
163 p += 4;
165 else
167 offset = ((p[0] << 8) | p[1]) << 1;
168 p += 2;
170 if (offset > last_offset + CHUNKSIZE)
172 if (last_chunk != last_offset)
173 chunks.push_back (FT_UShort (last_offset - last_chunk));
175 a single glyph with more than 64k data
176 is a pathological case but...
178 FT_ULong rest = offset - last_offset;
179 while (rest > CHUNKSIZE)
181 chunks.push_back (CHUNKSIZE);
182 rest -= CHUNKSIZE;
184 chunks.push_back (FT_UShort (rest));
185 last_chunk = offset;
187 else if (offset > last_chunk + CHUNKSIZE)
189 chunks.push_back (FT_UShort (last_offset - last_chunk));
190 last_chunk = last_offset;
193 last_offset = offset;
195 chunks.push_back (FT_UShort (s - last_chunk));
197 delete[] loca_buf;
199 else if (s > CHUNKSIZE)
201 FT_ULong rest = s;
202 while (rest > CHUNKSIZE)
204 chunks.push_back (CHUNKSIZE);
205 rest -= CHUNKSIZE;
207 chunks.push_back (FT_UShort (rest));
209 else
210 chunks.push_back (CHUNKSIZE);
212 lily_cookie_fprintf (out, "\n"
213 " <");
215 int l = 0;
216 static char xdigits[] = "0123456789ABCDEF";
218 int cur_chunk_idx = 0;
219 for (size_t j = 0; j < s; j++)
221 if (l >= chunks[cur_chunk_idx])
223 lily_cookie_fprintf (out, "\n"
224 " 00>\n"
225 " <");
226 l = 0;
227 cur_chunk_idx ++;
230 if (l % 31 == 0)
231 lily_cookie_fprintf (out, "\n"
232 " ");
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);
238 l ++;
241 /* pad to four-byte boundary */
242 while ((s ++) % 4 != 0)
243 lily_cookie_fprintf (out, "00");
245 lily_cookie_fprintf (out, "\n"
246 " 00\n"
247 " >");
250 static void
251 print_body (void *out, FT_Face face)
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;
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
263 while (FT_Sfnt_Table_Info (face, idx, &tag, &length)
264 != FT_Err_Table_Missing)
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 ++;
275 FT_ULong hlength = 12 + 16 * idx;
277 unsigned char *hbuf = new unsigned char[hlength];
278 unsigned char *p;
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;
287 FT_UInt searchRange, entrySelector, rangeShift;
288 FT_UInt i, j;
289 for (i = 1, j = 2; j <= idx; i++, j <<= 1)
291 entrySelector = i - 1;
292 searchRange = 0x10 << entrySelector;
293 rangeShift = (idx << 4) - searchRange;
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;
302 p = &hbuf[12];
304 FT_ULong checksum, font_checksum = 0;
306 FT_ULong offset = hlength; /* first table offset */
308 for (FT_UInt i = 0; i < idx; i++)
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];
314 buf[len - 1] = 0x00; /* assure padding with zeros */
315 buf[len - 2] = 0x00;
316 buf[len - 3] = 0x00;
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.");
322 if (tag == head_tag)
325 first pass of computing the font checksum
326 needs checkSumAdjustment = 0
328 buf[8] = 0x00;
329 buf[9] = 0x00;
330 buf[10] = 0x00;
331 buf[11] = 0x00;
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;
340 delete[] buf;
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;
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;
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;
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;
362 /* offset must be a multiple of 4 */
363 offset += (lengths[i] + 3) & ~3;
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;
374 see Adobe technical note 5012.Type42_Spec.pdf for details how
375 the /sfnts array must be constructed
377 lily_cookie_fprintf (out, "/sfnts [");
378 t42_write_table (out, face, hbuf, hlength, false,
379 head_length, loca_length);
380 delete[] hbuf;
382 idx = 0;
384 while (FT_Sfnt_Table_Info (face, idx, &tag, &length)
385 != FT_Err_Table_Missing)
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.");
392 if (tag == head_tag)
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;
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);
405 delete[] buf;
406 idx ++;
408 lily_cookie_fprintf (out, "\n] def\n");
411 static void
412 print_trailer (void *out,
413 FT_Face face)
415 const int GLYPH_NAME_LEN = 256;
416 char glyph_name[GLYPH_NAME_LEN];
418 TT_MaxProfile *mp
419 = (TT_MaxProfile *)FT_Get_Sfnt_Table (face, ft_sfnt_maxp);
421 lily_cookie_fprintf (out, "/CharStrings %d dict dup begin\n", mp->numGlyphs);
423 Index_to_charcode_map ic_map (make_index_to_charcode_map (face));
425 int output_count = 0;
426 for (int i = 0; i < mp->numGlyphs; i++)
428 glyph_name[0] = 0;
429 if (face->face_flags & FT_FACE_FLAG_GLYPH_NAMES)
431 FT_Error error = FT_Get_Glyph_Name (face, i, glyph_name,
432 GLYPH_NAME_LEN);
433 if (error)
435 programming_error ("FT_Get_Glyph_Name (): error.");
436 glyph_name[0] = 0;
440 if (!glyph_name[0] && ic_map.find (i) != ic_map.end ())
442 FT_ULong ucode = ic_map[i];
443 get_unicode_name (glyph_name, ucode);
446 if (i == 0)
447 sprintf (glyph_name, ".notdef");
448 else if (glyph_name == string (".notdef"))
449 glyph_name[0] = '\0';
451 if (!glyph_name[0])
452 get_glyph_index_name (glyph_name, i);
454 if (glyph_name[0])
456 lily_cookie_fprintf (out, "/%s %d def ", glyph_name, i);
457 output_count ++;
459 else
460 programming_error (to_string ("no name for glyph %d", i));
462 if (! (output_count % 5))
463 lily_cookie_fprintf (out, "\n");
466 lily_cookie_fprintf (out, "end readonly def\n");
467 lily_cookie_fprintf (out, "FontName currentdict end definefont pop\n");
470 static void
471 create_type42_font (void *out, string name, int idx)
473 FT_Face face;
475 /* check whether font index is valid */
476 if (idx > 0)
478 face = open_ft_face (name, -1);
479 if (idx >= face->num_faces)
481 warning (_f ("font index %d too large for font `%s', using index 0",
482 idx, name.c_str()));
483 idx = 0;
485 FT_Done_Face (face);
488 face = open_ft_face (name, idx);
490 print_header (out, face);
491 print_body (out, face);
492 print_trailer (out, face);
494 FT_Done_Face (face);
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.")
504 LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
506 int i = 0;
507 if (idx != SCM_UNDEFINED)
509 LY_ASSERT_TYPE (scm_is_integer, idx, 2);
510 i = scm_to_int (idx);
511 if (i < 0)
513 warning (_ ("font index must be non-negative, using index 0"));
514 i = 0;
518 string file_name = ly_scm2string (ttf_file_name);
519 if (be_verbose_global)
520 progress_indication ("\n[" + file_name);
522 FT_Face face;
524 /* check whether font index is valid */
525 if (i > 0)
527 face = open_ft_face (file_name, -1);
528 if (i >= face->num_faces)
530 warning (_f ("font index %d too large for font `%s', using index 0",
531 i, file_name.c_str()));
532 i = 0;
534 FT_Done_Face (face);
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);
542 if (be_verbose_global)
543 progress_indication ("]");
545 return ps_name;
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.")
556 LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
558 int i = 0;
559 if (idx != SCM_UNDEFINED)
561 LY_ASSERT_TYPE (scm_is_integer, idx, 2);
562 i = scm_to_int (idx);
563 if (i < 0)
565 warning (_ ("font index must be non-negative, using index 0"));
566 i = 0;
570 string file_name = ly_scm2string (ttf_file_name);
571 if (be_verbose_global)
572 progress_indication ("\n[" + file_name);
574 Memory_out_stream stream;
576 create_type42_font (&stream, file_name, i);
577 SCM asscm = scm_from_locale_stringn (stream.get_string (),
578 stream.get_length ());
580 if (be_verbose_global)
581 progress_indication ("]");
583 return asscm;