Correct left text alignment of DynamicTextSpanner.
[lilypond.git] / lily / ttf.cc
blobd4bb86968bc048d606272475b80262c5ee1d0b9e
1 /*
2 ttf.cc -- implement ttf -> pfa routine.
4 source file of the GNU LilyPond music typesetter
6 (c) 2005--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
9 #include "freetype.hh"
11 #include <freetype/tttables.h>
13 #include "memory-stream.hh"
14 #include "warn.hh"
15 #include "lily-guile.hh"
16 #include "main.hh"
17 #include "open-type-font.hh"
20 Index_to_charcode_map
21 make_index_to_charcode_map (FT_Face face)
23 Index_to_charcode_map m;
24 FT_ULong charcode;
25 FT_UInt gindex;
27 FT_CharMap current_cmap = face->charmap;
28 FT_Select_Charmap (face, FT_ENCODING_UNICODE);
30 int j = 0;
31 for (charcode = FT_Get_First_Char (face, &gindex); gindex != 0;
32 charcode = FT_Get_Next_Char (face, charcode, &gindex))
34 m[gindex] = charcode;
35 j ++;
37 FT_Set_Charmap (face, current_cmap);
39 return m;
43 Based on ttfps by Juliusz Chroboczek
45 static void
46 print_header (void *out, FT_Face face)
48 lily_cookie_fprintf (out, "%%!PS-TrueTypeFont\n");
50 TT_Postscript *pt
51 = (TT_Postscript *) FT_Get_Sfnt_Table (face, ft_sfnt_post);
53 if (pt->maxMemType42)
54 lily_cookie_fprintf (out, "%%%%VMUsage: %d %d\n", 0, 0);
56 lily_cookie_fprintf (out, "%d dict begin\n", 11);
57 lily_cookie_fprintf (out, "/FontName /%s def\n",
58 FT_Get_Postscript_Name (face));
60 lily_cookie_fprintf (out, "/Encoding StandardEncoding def\n");
61 lily_cookie_fprintf (out, "/PaintType 0 def\n");
62 lily_cookie_fprintf (out, "/FontMatrix [1 0 0 1 0 0] def\n");
64 TT_Header *ht
65 = (TT_Header *)FT_Get_Sfnt_Table (face, ft_sfnt_head);
67 lily_cookie_fprintf (out, "/FontBBox [%lf %lf %lf %lf] def\n",
68 float (ht->xMin) / ht->Units_Per_EM,
69 float (ht->yMin) / ht->Units_Per_EM,
70 float (ht->xMax) / ht->Units_Per_EM,
71 float (ht->yMax) / ht->Units_Per_EM);
73 lily_cookie_fprintf (out, "/FontType 42 def\n");
74 lily_cookie_fprintf (out, "/FontInfo 8 dict dup begin\n");
75 lily_cookie_fprintf (out, "/version (%.3f) def\n",
76 ht->Font_Revision / 65536.0);
78 #if 0
79 if (strings[0])
81 lily_cookie_fprintf (out, "/Notice (");
82 fputpss (strings[0], out);
83 lily_cookie_fprintf (out, ") def\n");
85 if (strings[4])
87 lily_cookie_fprintf (out, "/FullName (");
88 fputpss (strings[4], out);
89 lily_cookie_fprintf (out, ") def\n");
91 if (strings[1])
93 lily_cookie_fprintf (out, "/FamilyName (");
94 fputpss (strings[1], out);
95 lily_cookie_fprintf (out, ") def\n");
97 #endif
99 lily_cookie_fprintf (out, "/isFixedPitch %s def\n",
100 pt->isFixedPitch ? "true" : "false");
101 lily_cookie_fprintf (out, "/UnderlinePosition %lf def\n",
102 float (pt->underlinePosition) / ht->Units_Per_EM);
103 lily_cookie_fprintf (out, "/UnderlineThickness %lf def\n",
104 float (pt->underlineThickness) / ht->Units_Per_EM);
105 lily_cookie_fprintf (out, "end readonly def\n");
108 #define CHUNKSIZE 65534
110 const FT_ULong FT_ENC_TAG (glyf_tag, 'g', 'l', 'y', 'f');
111 const FT_ULong FT_ENC_TAG (head_tag, 'h', 'e', 'a', 'd');
112 const FT_ULong FT_ENC_TAG (loca_tag, 'l', 'o', 'c', 'a');
114 static
115 void t42_write_table (void *out, FT_Face face, unsigned char const *buffer,
116 size_t s, bool is_glyf,
117 FT_ULong head_length, FT_ULong loca_length)
119 vector<FT_UShort> chunks;
121 if (is_glyf)
123 /* compute chunk sizes */
124 unsigned char *head_buf = new unsigned char[head_length];
125 FT_Error error = FT_Load_Sfnt_Table (face, head_tag, 0, head_buf, NULL);
126 if (error)
127 programming_error ("FT_Load_Sfnt_Table (): error.");
129 /* we access the lower byte of indexToLocFormat */
130 bool long_offsets = head_buf[4*4 + 2*2 + 2*8 + 4*2 + 3*2 + 1] == 1;
132 delete[] head_buf;
134 unsigned char *loca_buf = new unsigned char[loca_length];
135 error = FT_Load_Sfnt_Table (face, loca_tag, 0, loca_buf, NULL);
136 if (error)
137 programming_error ("FT_Load_Sfnt_Table (): error.");
139 unsigned char *p = loca_buf;
140 unsigned char *endp = loca_buf + loca_length;
142 FT_ULong offset = 0, last_offset = 0, last_chunk = 0;
143 while (p < endp)
145 if (long_offsets)
147 offset = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
148 p += 4;
150 else
152 offset = ((p[0] << 8) | p[1]) << 1;
153 p += 2;
155 if (offset > last_offset + CHUNKSIZE)
157 if (last_chunk != last_offset)
158 chunks.push_back (last_offset - last_chunk);
160 a single glyph with more than 64k data
161 is a pathological case but...
163 FT_ULong rest = offset - last_offset;
164 while (rest > CHUNKSIZE)
166 chunks.push_back (CHUNKSIZE);
167 rest -= CHUNKSIZE;
169 chunks.push_back (rest);
170 last_chunk = offset;
172 else if (offset > last_chunk + CHUNKSIZE)
174 chunks.push_back (last_offset - last_chunk);
175 last_chunk = last_offset;
178 last_offset = offset;
180 chunks.push_back (s - last_chunk);
182 delete[] loca_buf;
184 else if (s > CHUNKSIZE)
186 FT_ULong rest = s;
187 while (rest > CHUNKSIZE)
189 chunks.push_back (CHUNKSIZE);
190 rest -= CHUNKSIZE;
192 chunks.push_back (rest);
194 else
195 chunks.push_back (CHUNKSIZE);
197 lily_cookie_fprintf (out, "\n"
198 " <");
200 int l = 0;
201 static char xdigits[] = "0123456789ABCDEF";
203 int cur_chunk_idx = 0;
204 for (size_t j = 0; j < s; j++)
206 if (l >= chunks[cur_chunk_idx])
208 lily_cookie_fprintf (out, "\n"
209 " 00>\n"
210 " <");
211 l = 0;
212 cur_chunk_idx ++;
215 if (l % 31 == 0)
216 lily_cookie_fprintf (out, "\n"
217 " ");
219 /* lily_cookie_fprintf (out,"%02X",(int)buffer[j]) is too slow */
220 lily_cookie_putc (xdigits[(buffer[j] & 0xF0) >> 4], out);
221 lily_cookie_putc (xdigits[buffer[j] & 0x0F], out);
223 l ++;
226 /* pad to four-byte boundary */
227 while ((s ++) % 4 != 0)
228 lily_cookie_fprintf (out, "00");
230 lily_cookie_fprintf (out, "\n"
231 " 00\n"
232 " >");
235 static void
236 print_body (void *out, FT_Face face)
238 FT_UInt idx = 0;
239 FT_ULong head_length = 0, loca_length = 0;
240 FT_ULong tag, length;
241 vector<FT_ULong> lengths, tags;
244 we must build our own TTF header -- the original font
245 might be a TTC where tables are not contiguous, or the font
246 contains tables which aren't indexed at all
248 while (FT_Sfnt_Table_Info (face, idx, &tag, &length)
249 != FT_Err_Table_Missing)
251 lengths.push_back (length);
252 tags.push_back (tag);
253 if (tag == head_tag)
254 head_length = length;
255 else if (tag == loca_tag)
256 loca_length = length;
257 idx ++;
260 FT_ULong hlength = 12 + 16 * idx;
262 unsigned char *hbuf = new unsigned char[hlength];
263 unsigned char *p;
265 hbuf[0] = 0x00; /* version */
266 hbuf[1] = 0x01;
267 hbuf[2] = 0x00;
268 hbuf[3] = 0x00;
269 hbuf[4] = (idx & 0xFF00) >> 8; /* numTables */
270 hbuf[5] = idx & 0x00FF;
272 FT_UInt searchRange, entrySelector, rangeShift;
273 FT_UInt i, j;
274 for (i = 1, j = 2; j <= idx; i++, j <<= 1)
276 entrySelector = i - 1;
277 searchRange = 0x10 << entrySelector;
278 rangeShift = (idx << 4) - searchRange;
280 hbuf[6] = (searchRange & 0xFF00) >> 8;
281 hbuf[7] = searchRange & 0x00FF;
282 hbuf[8] = (entrySelector & 0xFF00) >> 8;
283 hbuf[9] = entrySelector & 0x00FF;
284 hbuf[10] = (rangeShift & 0xFF00) >> 8;
285 hbuf[11] = rangeShift & 0x00FF;
287 p = &hbuf[12];
289 FT_ULong checksum, font_checksum = 0;
291 FT_ULong offset = hlength; /* first table offset */
293 for (FT_UInt i = 0; i < idx; i++)
295 /* here, the buffer length must be a multiple of 4 */
296 FT_ULong len = (lengths[i] + 3) & ~3;
297 unsigned char *buf = new unsigned char[len];
299 buf[len - 1] = 0x00; /* assure padding with zeros */
300 buf[len - 2] = 0x00;
301 buf[len - 3] = 0x00;
303 FT_Error error = FT_Load_Sfnt_Table (face, tags[i], 0, buf, NULL);
304 if (error)
305 programming_error ("FT_Load_Sfnt_Table (): error.");
307 if (tag == head_tag)
310 first pass of computing the font checksum
311 needs checkSumAdjustment = 0
313 buf[8] = 0x00;
314 buf[9] = 0x00;
315 buf[10] = 0x00;
316 buf[11] = 0x00;
319 checksum = 0;
320 unsigned char *endq = buf + len;
321 for (unsigned char *q = buf; q < endq; q += 4)
322 checksum += (q[0] << 24) | (q[1] << 16) | (q[2] << 8) | q[3];
323 font_checksum += checksum;
325 delete[] buf;
327 *(p++) = (tags[i] & 0xFF000000UL) >> 24;
328 *(p++) = (tags[i] & 0x00FF0000UL) >> 16;
329 *(p++) = (tags[i] & 0x0000FF00UL) >> 8;
330 *(p++) = tags[i] & 0x000000FFUL;
332 *(p++) = (checksum & 0xFF000000UL) >> 24;
333 *(p++) = (checksum & 0x00FF0000UL) >> 16;
334 *(p++) = (checksum & 0x0000FF00UL) >> 8;
335 *(p++) = checksum & 0x000000FFUL;
337 *(p++) = (offset & 0xFF000000UL) >> 24;
338 *(p++) = (offset & 0x00FF0000UL) >> 16;
339 *(p++) = (offset & 0x0000FF00UL) >> 8;
340 *(p++) = offset & 0x000000FFUL;
342 *(p++) = (lengths[i] & 0xFF000000UL) >> 24;
343 *(p++) = (lengths[i] & 0x00FF0000UL) >> 16;
344 *(p++) = (lengths[i] & 0x0000FF00UL) >> 8;
345 *(p++) = lengths[i] & 0x000000FFUL;
347 /* offset must be a multiple of 4 */
348 offset += (lengths[i] + 3) & ~3;
351 /* add checksum of TTF header */
352 checksum = 0;
353 for (unsigned char *q = hbuf; q < p; q += 4)
354 checksum += (q[0] << 24) | (q[1] << 16) | (q[2] << 8) | q[3];
355 font_checksum += checksum;
356 font_checksum = 0xB1B0AFBAUL - font_checksum;
359 see Adobe technical note 5012.Type42_Spec.pdf for details how
360 the /sfnts array must be constructed
362 lily_cookie_fprintf (out, "/sfnts [");
363 t42_write_table (out, face, hbuf, hlength, false,
364 head_length, loca_length);
365 delete[] hbuf;
367 idx = 0;
369 while (FT_Sfnt_Table_Info (face, idx, &tag, &length)
370 != FT_Err_Table_Missing)
372 unsigned char *buf = new unsigned char[length];
373 FT_Error error = FT_Load_Sfnt_Table (face, tag, 0, buf, NULL);
374 if (error)
375 programming_error ("FT_Load_Sfnt_Table (): error.");
377 if (tag == head_tag)
379 /* in the second pass simply store the computed font checksum */
380 buf[8] = (font_checksum & 0xFF000000UL) >> 24;
381 buf[9] = (font_checksum & 0x00FF0000UL) >> 16;
382 buf[10] = (font_checksum & 0x0000FF00UL) >> 8;
383 buf[11] = font_checksum & 0x000000FFUL;
386 bool is_glyf_table = tag == glyf_tag && length > CHUNKSIZE;
387 t42_write_table (out, face, buf, length, is_glyf_table,
388 head_length, loca_length);
390 delete[] buf;
391 idx ++;
393 lily_cookie_fprintf (out, "\n] def\n");
396 static void
397 print_trailer (void *out,
398 FT_Face face)
400 const int GLYPH_NAME_LEN = 256;
401 char glyph_name[GLYPH_NAME_LEN];
403 TT_MaxProfile *mp
404 = (TT_MaxProfile *)FT_Get_Sfnt_Table (face, ft_sfnt_maxp);
406 lily_cookie_fprintf (out, "/CharStrings %d dict dup begin\n", mp->numGlyphs);
408 Index_to_charcode_map ic_map (make_index_to_charcode_map (face));
410 int output_count = 0;
411 for (int i = 0; i < mp->numGlyphs; i++)
413 glyph_name[0] = 0;
414 if (face->face_flags & FT_FACE_FLAG_GLYPH_NAMES)
416 FT_Error error = FT_Get_Glyph_Name (face, i, glyph_name,
417 GLYPH_NAME_LEN);
418 if (error)
420 programming_error ("FT_Get_Glyph_Name (): error.");
421 glyph_name[0] = 0;
425 if (!glyph_name[0] && ic_map.find (i) != ic_map.end ())
427 FT_ULong ucode = ic_map[i];
428 get_unicode_name (glyph_name, ucode);
431 if (i == 0)
432 sprintf (glyph_name, ".notdef");
433 else if (glyph_name == string (".notdef"))
434 glyph_name[0] = '\0';
436 if (!glyph_name[0])
437 get_glyph_index_name (glyph_name, i);
439 if (glyph_name[0])
441 lily_cookie_fprintf (out, "/%s %d def ", glyph_name, i);
442 output_count ++;
444 else
445 programming_error (to_string ("no name for glyph %d", i));
447 if (! (output_count % 5))
448 lily_cookie_fprintf (out, "\n");
451 lily_cookie_fprintf (out, "end readonly def\n");
452 lily_cookie_fprintf (out, "FontName currentdict end definefont pop\n");
455 static void
456 create_type42_font (void *out, string name)
458 FT_Face face = open_ft_face (name);
460 print_header (out, face);
461 print_body (out, face);
462 print_trailer (out, face);
464 FT_Done_Face (face);
468 LY_DEFINE (ly_ttf_ps_name, "ly:ttf-ps-name",
469 1, 0, 0, (SCM ttf_file_name),
470 "Extract the PostScript name from a TrueType font.")
472 LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
473 string file_name = ly_scm2string (ttf_file_name);
474 if (be_verbose_global)
475 progress_indication ("[" + file_name);
477 FT_Face face = open_ft_face (file_name);
478 char const *ps_name_str0 = FT_Get_Postscript_Name (face);
479 SCM ps_name = scm_from_locale_string (ps_name_str0 ? ps_name_str0 : "");
481 FT_Done_Face (face);
483 if (be_verbose_global)
484 progress_indication ("]");
486 return ps_name;
491 LY_DEFINE (ly_ttf_2_pfa, "ly:ttf->pfa",
492 1, 0, 0, (SCM ttf_file_name),
493 "Convert the contents of a TTF file to Type42 PFA, returning it as"
494 " a string.")
496 LY_ASSERT_TYPE (scm_is_string, ttf_file_name, 1);
498 string file_name = ly_scm2string (ttf_file_name);
499 if (be_verbose_global)
500 progress_indication ("[" + file_name);
502 Memory_out_stream stream;
504 create_type42_font (&stream, file_name);
505 SCM asscm = scm_from_locale_stringn (stream.get_string (),
506 stream.get_length ());
508 if (be_verbose_global)
509 progress_indication ("]");
511 return asscm;