1 /*
2  * Support for sfnt-housed fonts for Halibut
3  *
4  * sfnt-housed fonts include TrueType, OpenType, sfnt-housed Type 1
5  * fonts and a couple of bitmap formats.
6  *
7  * The various tables that can appear in sfnt-housed fonts are defined
8  * in several places.  These include:
9  *
10  * The OpenType Specification:
11  * <http://partners.adobe.com/public/developer/opentype/index_spec.html>
12  *
13  * The TrueType Reference Manual:
14  * <http://developer.apple.com/textfonts/TTRefMan/>
15  *
16  * Microsoft typography specifications:
17  * <http://www.microsoft.com/typography/SpecificationsOverview.mspx>
18  */
19 
20 #include <assert.h>
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include "halibut.h"
25 #include "paper.h"
26 
27 typedef struct sfnt_decode_Tag sfnt_decode;
28 struct sfnt_decode_Tag {
29     void (*decoder)(void *src, void *dest);
30     size_t src_len;
31     size_t dest_offset;
32 };
33 
34 #if 0 /* unused */
35 static void decode_uint8(void *src, void *dest) {
36     *(unsigned int *)dest = *(unsigned char *)src;
37 }
38 #define d_uint8 decode_uint8, 1
39 #endif
40 
41 #if 0 /* unused */
42 static void decode_int8(void *src, void *dest) {
43     *(int *)dest = *(signed char *)src;
44 }
45 #define d_int8 decode_int8, 1
46 #endif
47 
decode_uint16(void * src,void * dest)48 static void decode_uint16(void *src, void *dest) {
49     unsigned char *cp = src;
50     *(unsigned int *)dest = (cp[0] << 8)  + cp[1];
51 }
52 #define d_uint16 decode_uint16, 2
53 
decode_int16(void * src,void * dest)54 static void decode_int16(void *src, void *dest) {
55     signed char *cp = src;
56     unsigned char *ucp = src;
57     *(int *)dest = (cp[0] << 8)  + ucp[1];
58 }
59 #define d_int16 decode_int16, 2
60 
decode_uint32(void * src,void * dest)61 static void decode_uint32(void *src, void *dest) {
62     unsigned char *cp = src;
63     *(unsigned int *)dest =
64 	(cp[0] << 24) + (cp[1] << 16) + (cp[2] << 8)  + cp[3];
65 }
66 #define d_uint32 decode_uint32, 4
67 
decode_int32(void * src,void * dest)68 static void decode_int32(void *src, void *dest) {
69     signed char *cp = src;
70     unsigned char *ucp = src;
71     *(int *)dest = (cp[0] << 24) + (ucp[1] << 16) + (ucp[2] << 8)  + ucp[3];
72 }
73 #define d_int32 decode_int32, 4
74 
decode_skip(void * src,void * dest)75 static void decode_skip(void *src, void *dest) {
76     IGNORE(src);
77     IGNORE(dest);
78     /* do nothing */
79 }
80 #define d_skip(n) decode_skip, (n), 0
81 
decode_end(void * src,void * dest)82 static void decode_end(void *src, void *dest) {
83     IGNORE(src);
84     IGNORE(dest);
85     /* never called */
86 }
87 #define d_end decode_end, 0, 0
88 
decode(sfnt_decode * dec,void * src,void * end,void * dest)89 static void *decode(sfnt_decode *dec, void *src, void *end, void *dest) {
90     while (dec->decoder != decode_end) {
91 	if ((char *)src + dec->src_len > (char *)end) return NULL;
92 	dec->decoder(src, (char *)dest + dec->dest_offset);
93 	src = (char *)src + dec->src_len;
94 	dec++;
95     }
96     return src;
97 }
98 
decoden(sfnt_decode * dec,void * src,void * end,void * dest,size_t size,size_t n)99 static void *decoden(sfnt_decode *dec, void *src, void *end, void *dest,
100 		     size_t size, size_t n) {
101     while (n-- && src) {
102 	src = decode(dec, src, end, dest);
103 	dest = (char *)dest + size;
104     }
105     return src;
106 }
107 
108 /* Decoding specs for simple data types */
109 sfnt_decode uint16_decode[] = { { d_uint16, 0 }, { d_end } };
110 sfnt_decode int16_decode[]  = { { d_int16,  0 }, { d_end } };
111 sfnt_decode uint32_decode[] = { { d_uint32, 0 }, { d_end } };
112 
113 /* Offset subdirectory -- the start of the file */
114 typedef struct offsubdir_Tag offsubdir;
115 struct offsubdir_Tag {
116     unsigned scaler_type;
117     unsigned numTables;
118 };
119 sfnt_decode offsubdir_decode[] = {
120     { d_uint32,	offsetof(offsubdir, scaler_type) },
121     { d_uint16, offsetof(offsubdir, numTables) },
122     { d_skip(6) },
123     { d_end }
124 };
125 
126 #define sfnt_00010000	0x00010000
127 #define TAG_OS_2	0x4f532f32
128 #define TAG_cmap	0x636d6170
129 #define TAG_glyf	0x676c7966
130 #define TAG_head	0x68656164
131 #define TAG_hhea	0x68686561
132 #define TAG_hmtx	0x686d7478
133 #define TAG_kern	0x6b65726e
134 #define TAG_loca	0x6c6f6361
135 #define TAG_maxp	0x6d617870
136 #define TAG_name	0x6e616d65
137 #define TAG_post	0x706f7374
138 #define sfnt_true	0x74727565
139 
140 /* Table directory */
141 typedef struct tabledir_Tag tabledir;
142 struct tabledir_Tag {
143     unsigned tag;
144     unsigned checkSum;
145     unsigned offset;
146     unsigned length;
147 };
148 sfnt_decode tabledir_decode[] = {
149     { d_uint32,	offsetof(tabledir, tag) },
150     { d_uint32, offsetof(tabledir, checkSum) },
151     { d_uint32, offsetof(tabledir, offset) },
152     { d_uint32, offsetof(tabledir, length) },
153     { d_end }
154 };
155 
156 /* OS/2 and Windows compatibility table */
157 typedef struct t_OS_2_Tag t_OS_2;
158 struct t_OS_2_Tag {
159     unsigned version;
160     int sTypoAscender, sTypoDescender;
161     int sxHeight, sCapHeight;
162 };
163 sfnt_decode t_OS_2_v0_decode[] = {
164     { d_uint16, offsetof(t_OS_2, version) },
165     { d_skip(66) }, /* xAvgCharWidth, usWeightClass, usWidthClass, fsType, */
166     /* ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, */
167     /* ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, */
168     /* ySuperscriptXOffset, ySupercriptYOffset, sFamilyClass, panose, */
169     /* ulUnicodeRange1, ulUnicodeRange2, ulUnicodeRange3, ulUnicodeRange4, */
170     /* achVendID, fsSelection, usFirstCharIndex, usLastCharIndex */
171     { d_end }
172 };
173 sfnt_decode t_OS_2_v1_decode[] = {
174     { d_uint16, offsetof(t_OS_2, version) },
175     { d_skip(66) }, /* xAvgCharWidth, usWeightClass, usWidthClass, fsType, */
176     /* ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, */
177     /* ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, */
178     /* ySuperscriptXOffset, ySupercriptYOffset, sFamilyClass, panose, */
179     /* ulUnicodeRange1, ulUnicodeRange2, ulUnicodeRange3, ulUnicodeRange4, */
180     /* achVendID, fsSelection, usFirstCharIndex, usLastCharIndex */
181     { d_int16, offsetof(t_OS_2, sTypoAscender) },
182     { d_int16, offsetof(t_OS_2, sTypoDescender) },
183     { d_skip(14) }, /* sTypoLineGap, usWinAscent, usWinDescent, */
184     /* ulCodePageRange1, ulCodePageRange2 */
185     { d_end }
186 };
187 sfnt_decode t_OS_2_v2_decode[] = {
188     { d_uint16, offsetof(t_OS_2, version) },
189     { d_skip(66) }, /* xAvgCharWidth, usWeightClass, usWidthClass, fsType, */
190     /* ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, */
191     /* ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, */
192     /* ySuperscriptXOffset, ySupercriptYOffset, sFamilyClass, panose, */
193     /* ulUnicodeRange1, ulUnicodeRange2, ulUnicodeRange3, ulUnicodeRange4, */
194     /* achVendID, fsSelection, usFirstCharIndex, usLastCharIndex */
195     { d_int16, offsetof(t_OS_2, sTypoAscender) },
196     { d_int16, offsetof(t_OS_2, sTypoDescender) },
197     { d_skip(14) }, /* sTypoLineGap, usWinAscent, usWinDescent, */
198     /* ulCodePageRange1, ulCodePageRange2 */
199     { d_int16, offsetof(t_OS_2, sxHeight) },
200     { d_int16, offsetof(t_OS_2, sCapHeight) },
201     { d_skip(6) }, /* usDefaultChar, usBreakChar, usMaxContext */
202     { d_end }
203 };
204 
205 /* Character to Glyph ('cmap') table */
206 typedef struct t_cmap_Tag t_cmap;
207 struct t_cmap_Tag {
208     unsigned numTables;
209 };
210 sfnt_decode t_cmap_decode[] = {
211     { d_skip(2) },
212     { d_uint16, offsetof(t_cmap, numTables) },
213     { d_end }
214 };
215 typedef struct encodingrec_Tag encodingrec;
216 struct encodingrec_Tag {
217     unsigned platformID;
218     unsigned encodingID;
219     unsigned offset;
220 };
221 sfnt_decode encodingrec_decode[] = {
222     { d_uint16, offsetof(encodingrec, platformID) },
223     { d_uint16, offsetof(encodingrec, encodingID) },
224     { d_uint32, offsetof(encodingrec, offset) },
225     { d_end }
226 };
227 typedef struct cmap4_Tag cmap4;
228 struct cmap4_Tag {
229     unsigned length;
230     unsigned segCountX2;
231 };
232 sfnt_decode cmap4_decode[] = {
233     { d_skip(2) }, /* format */
234     { d_uint16, offsetof(cmap4, length) },
235     { d_skip(2) }, /* language */
236     { d_uint16, offsetof(cmap4, segCountX2) },
237     { d_skip(6) }, /* searchRange, entrySelector, rangeShift */
238     { d_end }
239 };
240 
241 /* Font Header ('head') table */
242 typedef struct t_head_Tag t_head;
243 struct t_head_Tag {
244     unsigned version;
245     unsigned fontRevision;
246     unsigned flags;
247     unsigned unitsPerEm;
248     int xMin, yMin, xMax, yMax;
249     int indexToLocFormat;
250 };
251 sfnt_decode t_head_decode[] = {
252     { d_uint32, offsetof(t_head, version) },
253     { d_uint32, offsetof(t_head, fontRevision) },
254     { d_skip(8) }, /* checkSumAdjustment, magicNumber, flags */
255     { d_uint16, offsetof(t_head, flags) },
256     { d_uint16, offsetof(t_head, unitsPerEm) },
257     { d_skip(16) }, /* created, modified */
258     { d_int16, offsetof(t_head, xMin) },
259     { d_int16, offsetof(t_head, yMin) },
260     { d_int16, offsetof(t_head, xMax) },
261     { d_int16, offsetof(t_head, yMax) },
262     { d_skip(6) }, /* macStyle, lowestRecPPEM, fontDirectionHint */
263     { d_int16, offsetof(t_head, indexToLocFormat) },
264     { d_skip(2) },
265     { d_end }
266 };
267 
268 /* Horizontal Header ('hhea') table */
269 typedef struct t_hhea_Tag t_hhea;
270 struct t_hhea_Tag {
271     unsigned version;
272     int ascent;
273     int descent;
274     int lineGap;
275     int metricDataFormat;
276     unsigned numOfLongHorMetrics;
277 };
278 sfnt_decode t_hhea_decode[] = {
279     { d_uint32, offsetof(t_hhea, version) },
280     { d_int16,	offsetof(t_hhea, ascent) },
281     { d_int16,	offsetof(t_hhea, descent) },
282     { d_int16,	offsetof(t_hhea, lineGap) },
283     { d_skip(22) },
284     { d_int16,	offsetof(t_hhea, metricDataFormat) },
285     { d_uint16,	offsetof(t_hhea, numOfLongHorMetrics) },
286     { d_end }
287 };
288 
289 /* Horizontal Metrics ('hmtx') table */
290 sfnt_decode longhormetric_decode[] = {
291     { d_uint16, 0 },
292     { d_skip(2) },
293     { d_end }
294 };
295 
296 /* Kerning ('kern') table */
297 typedef struct t_kern_Tag t_kern;
298 struct t_kern_Tag {
299     unsigned version;
300     unsigned nTables;
301 };
302 sfnt_decode t_kern_v0_decode[] = {
303     { d_uint16, offsetof(t_kern, version) },
304     { d_uint16, offsetof(t_kern, nTables) },
305     { d_end }
306 };
307 typedef struct kern_v0_subhdr_Tag kern_v0_subhdr;
308 struct kern_v0_subhdr_Tag {
309     unsigned version;
310     unsigned length;
311     unsigned coverage;
312 };
313 sfnt_decode kern_v0_subhdr_decode[] = {
314     { d_uint16, offsetof(kern_v0_subhdr, version) },
315     { d_uint16, offsetof(kern_v0_subhdr, length) },
316     { d_uint16, offsetof(kern_v0_subhdr, coverage) },
317     { d_end }
318 };
319 #define KERN_V0_HORIZ		0x0001
320 #define KERN_V0_MINIMUM		0x0002
321 #define KERN_V0_CROSSSTREAM	0x0004
322 #define KERN_V0_OVERRIDE	0x0008
323 #define KERN_V0_FORMAT		0xff00
324 #define KERN_V0_FORMAT_0	0x0000
325 sfnt_decode t_kern_v1_decode[] = {
326     { d_uint32, offsetof(t_kern, version) },
327     { d_uint32, offsetof(t_kern, nTables) },
328     { d_end }
329 };
330 typedef struct kern_v1_subhdr_Tag kern_v1_subhdr;
331 struct kern_v1_subhdr_Tag {
332     unsigned length;
333     unsigned coverage;
334 };
335 sfnt_decode kern_v1_subhdr_decode[] = {
336     { d_uint32, offsetof(kern_v1_subhdr, length) },
337     { d_uint16, offsetof(kern_v1_subhdr, coverage) },
338     { d_skip(2) }, /* tupleIndex */
339     { d_end }
340 };
341 #define KERN_V1_VERTICAL	0x8000
342 #define KERN_V1_CROSSSTREAM	0x4000
343 #define KERN_V1_VARIATION	0x2000
344 #define KERN_V1_FORMAT		0x00ff
345 #define KERN_V1_FORMAT_0	0x0000
346 typedef struct kern_f0_Tag kern_f0;
347 struct kern_f0_Tag {
348     unsigned nPairs;
349 };
350 sfnt_decode kern_f0_decode[] = {
351     { d_uint16, offsetof(kern_f0, nPairs) },
352     { d_skip(6) }, /* searchRange, entrySelector, rangeShift */
353     { d_end }
354 };
355 typedef struct kern_f0_pair_Tag kern_f0_pair;
356 struct kern_f0_pair_Tag {
357     unsigned left;
358     unsigned right;
359     int value;
360 };
361 sfnt_decode kern_f0_pair_decode[] = {
362     { d_uint16, offsetof(kern_f0_pair, left) },
363     { d_uint16, offsetof(kern_f0_pair, right) },
364     { d_int16, offsetof(kern_f0_pair, value) },
365     { d_end }
366 };
367 
368 /* Maximum profile ('maxp') table */
369 typedef struct t_maxp_Tag t_maxp;
370 struct t_maxp_Tag {
371     unsigned version;
372     unsigned numGlyphs;
373 };
374 sfnt_decode t_maxp_decode[] = {
375     { d_uint32, offsetof(t_maxp, version) },
376     { d_uint16, offsetof(t_maxp, numGlyphs) },
377     { d_end }
378 };
379 
380 /* Naming ('name') table  */
381 typedef struct t_name_Tag t_name;
382 typedef struct namerecord_Tag namerecord;
383 struct t_name_Tag {
384     unsigned format;
385     unsigned count;
386     unsigned stringOffset;
387     namerecord *nameRecord;
388 };
389 sfnt_decode t_name_decode[] = {
390     { d_uint16,	offsetof(t_name, format) },
391     { d_uint16,	offsetof(t_name, count) },
392     { d_uint16,	offsetof(t_name, stringOffset) },
393     { d_end }
394 };
395 struct namerecord_Tag {
396     unsigned platformID;
397     unsigned encodingID;
398     unsigned languageID;
399     unsigned nameID;
400     unsigned length;
401     unsigned offset;
402 };
403 sfnt_decode namerecord_decode[] = {
404     { d_uint16, offsetof(namerecord, platformID) },
405     { d_uint16, offsetof(namerecord, encodingID) },
406     { d_uint16, offsetof(namerecord, languageID) },
407     { d_uint16, offsetof(namerecord, nameID) },
408     { d_uint16, offsetof(namerecord, length) },
409     { d_uint16, offsetof(namerecord, offset) },
410     { d_end }
411 };
412 
413 /* PostScript compatibility ('post') table */
414 typedef struct t_post_Tag t_post;
415 struct t_post_Tag {
416     unsigned format;
417     int italicAngle;
418     int underlinePosition;
419     int underlineThickness;
420     unsigned isFixedPitch;
421     unsigned minMemType42;
422     unsigned maxMemType42;
423 };
424 sfnt_decode t_post_decode[] = {
425     { d_uint32, offsetof(t_post, format) },
426     { d_int32,  offsetof(t_post, italicAngle) },
427     { d_int16,	offsetof(t_post, underlinePosition) },
428     { d_int16,	offsetof(t_post, underlineThickness) },
429     { d_uint32,	offsetof(t_post, isFixedPitch) },
430     { d_uint32, offsetof(t_post, minMemType42) },
431     { d_uint32, offsetof(t_post, maxMemType42) },
432     { d_skip(8) }, /* minMemType1, maxMemType1 */
433     { d_end }
434 };
435 
436 typedef struct {
437     glyph name;
438     unsigned short index;
439 } glyphmap;
440 
441 struct sfnt_Tag {
442     void *data;
443     size_t len;
444     void *end;
445     filepos pos;
446     offsubdir osd;
447     tabledir *td;
448     t_head head;
449     unsigned nglyphs;
450     glyph *glyphsbyindex;
451     unsigned short *glyphsbyname;
452     unsigned minmem, maxmem;
453 };
454 
sfnt_findtable(sfnt * sf,unsigned tag,void ** startp,void ** endp)455 static int sfnt_findtable(sfnt *sf, unsigned tag,
456 			  void **startp, void **endp) {
457     size_t i;
458 
459     for (i = 0; i < sf->osd.numTables; i++) {
460 	if (sf->td[i].tag == tag) {
461 	    *startp = (char *)sf->data + sf->td[i].offset;
462 	    *endp = (char *)*startp + sf->td[i].length;
463 	    return TRUE;
464 	}
465     }
466     return FALSE;
467 }
468 
sfnt_psname(font_info * fi)469 static char *sfnt_psname(font_info *fi) {
470     sfnt *sf = fi->fontfile;
471     t_name name;
472     void *ptr, *end;
473     size_t i;
474     char *psname;
475     namerecord *nr;
476 
477     if (!sfnt_findtable(sf, TAG_name, &ptr, &end)) {
478 	err_sfntnotable(&sf->pos, "name");
479 	return NULL;
480     }
481     ptr = decode(t_name_decode, ptr, end, &name);
482     name.nameRecord = snewn(name.count, namerecord);
483     ptr = decoden(namerecord_decode, ptr, sf->end, name.nameRecord,
484 		  sizeof(*name.nameRecord), name.count);
485     for (i = 0; i < name.count; i++) {
486 	nr = name.nameRecord + i;
487 	if (nr->nameID == 6) {
488 	    /* PostScript name, but can we make sense of it? */
489 	    if (nr->platformID == 1 && nr->encodingID == 0) {
490 		/* Mac Roman, which is ASCII for our purposes */
491 		psname = snewn(nr->length + 1, char);
492 		memcpy(psname, (char *)ptr + nr->offset, nr->length);
493 		psname[nr->length] = 0;
494 		sfree(name.nameRecord);
495 		return psname;
496 	    }
497 	}
498     }
499     err_sfntnopsname(&sf->pos);
500     return NULL;
501 }
502 
503 static unsigned short *cmp_glyphsbyindex;
glyphsbyname_cmp(void const * a,void const * b)504 static int glyphsbyname_cmp(void const *a, void const *b) {
505     glyph ga = cmp_glyphsbyindex[*(unsigned short *)a];
506     glyph gb = cmp_glyphsbyindex[*(unsigned short *)b];
507     if (ga < gb) return -1;
508     if (ga > gb) return 1;
509     /* For de-duping, we'd prefer to have the first glyph stay first */
510     if (*(unsigned short *)a < *(unsigned short *)b) return -1;
511     if (*(unsigned short *)a > *(unsigned short *)b) return 1;
512     return 0;
513 }
glyphsbyname_cmp_search(void const * a,void const * b)514 static int glyphsbyname_cmp_search(void const *a, void const *b) {
515     glyph ga = *(glyph *)a;
516     glyph gb = cmp_glyphsbyindex[*(unsigned short *)b];
517     if (ga < gb) return -1;
518     if (ga > gb) return 1;
519     return 0;
520 }
521 
522 /* Generate an name for a glyph that doesn't have one. */
genglyph(unsigned idx)523 static glyph genglyph(unsigned idx) {
524     char buf[11];
525     if (idx == 0) return glyph_intern(".notdef");
526     sprintf(buf, "glyph%u", idx);
527     return glyph_intern(buf);
528 }
529 
530 /*
531  * Extract data from the 'post' table (mostly glyph mappings)
532  *
533  * TODO: cope better with duplicated glyph names (usually .notdef)
534  * TODO: when presented with format 3.0, try to use 'CFF' if present.
535  */
sfnt_mapglyphs(font_info * fi)536 static void sfnt_mapglyphs(font_info *fi) {
537     sfnt *sf = fi->fontfile;
538     t_post post;
539     void *ptr, *end;
540     unsigned char *sptr;
541     char tmp[256];
542     glyph *extraglyphs, prev, this;
543     unsigned nextras, i, g, suflen;
544 
545     sf->glyphsbyname = sf->glyphsbyindex = NULL;
546     if (sfnt_findtable(sf, TAG_post, &ptr, &end)) {
547 	ptr = decode(t_post_decode, ptr, end, &post);
548 	if (ptr == NULL) {
549 	    err_sfntbadtable(&sf->pos, "post");
550 	    goto noglyphs;
551 	}
552 
553 	sf->minmem = post.minMemType42;
554 	sf->maxmem = post.maxMemType42;
555 	fi->italicangle = post.italicAngle / 65536.0;
556 	switch (post.format) {
557 	  case 0x00010000:
558 	    if (sf->nglyphs != 258) {
559 		err_sfntbadtable(&sf->pos, "post");
560 		break;
561 	    }
562 	    sf->glyphsbyindex = (glyph *)tt_std_glyphs;
563 	    break;
564 	  case 0x00020000:
565 	    if ((char *)ptr + 2 > (char *)end) {
566 		err_sfntbadtable(&sf->pos, "post");
567 		break;
568 	    }
569 	    ptr = (char *)ptr + 2;
570 	    if ((char *)ptr + 2*sf->nglyphs > (char *)end) {
571 		err_sfntbadtable(&sf->pos, "post");
572 		break;
573 	    }
574 	    nextras = 0;
575 	    for (sptr = (unsigned char *)ptr + 2*sf->nglyphs;
576 		 sptr < (unsigned char *)end;
577 		 sptr += *sptr+1)
578 		nextras++;
579 	    extraglyphs = snewn(nextras, glyph);
580 	    i = 0;
581 	    for (sptr = (unsigned char *)ptr + 2*sf->nglyphs;
582 		 sptr < (unsigned char *)end;
583 		 sptr += *sptr+1) {
584 		memcpy(tmp, sptr + 1, *sptr);
585 		tmp[*sptr] = 0;
586 		assert(i < nextras);
587 		extraglyphs[i++] = glyph_intern(tmp);
588 	    }
589 	    sf->glyphsbyindex = snewn(sf->nglyphs, glyph);
590 	    for (i = 0; i < sf->nglyphs; i++) {
591 		decode_uint16((char *)ptr + 2*i, &g);
592 		if (g <= 257)
593 		    sf->glyphsbyindex[i] = tt_std_glyphs[g];
594 		else if (g < 258 + nextras)
595 		    sf->glyphsbyindex[i] = extraglyphs[g - 258];
596 		else {
597 		    err_sfntbadtable(&sf->pos, "post");
598 		    sf->glyphsbyindex[i] = genglyph(i);
599 		}
600 	    }
601 	    sfree(extraglyphs);
602 	    break;
603 	  case 0x00030000:
604 	    break;
605 	  default:
606 	    err_sfnttablevers(&sf->pos, "post");
607 	    break;
608 	}
609     }
610   noglyphs:
611     if (!sf->glyphsbyindex) {
612 	sf->glyphsbyindex = snewn(sf->nglyphs, glyph);
613 	for (i = 0; i < sf->nglyphs; i++)
614 	    sf->glyphsbyindex[i] = genglyph(i);
615     }
616     /* Construct glyphsbyname */
617     sf->glyphsbyname = snewn(sf->nglyphs, unsigned short);
618     for (i = 0; i < sf->nglyphs; i++)
619 	sf->glyphsbyname[i] = i;
620     cmp_glyphsbyindex = sf->glyphsbyindex;
621     qsort(sf->glyphsbyname, sf->nglyphs, sizeof(*sf->glyphsbyname),
622 	  glyphsbyname_cmp);
623     /*
624      * It's possible for fonts to specify the same name for multiple
625      * glyphs, which would make one of them inaccessible.  Check for
626      * that, and rename all but one of each set.
627      *
628      * To ensure that we don't clash with any existing glyph names,
629      * our renaming involves appending the glyph number formatted with
630      * enough leading zeroes to make it longer than any all-digit
631      * suffix that already exists in the font.
632      */
633     suflen = 4;
634     for (i = 0; i < sf->nglyphs; i++) {
635 	char const *p;
636 	p = strrchr(glyph_extern(sfnt_indextoglyph(sf, i)), '.');
637 	if (p && !(p+1)[strspn(p+1, "0123456789")] && strlen(p+1) > suflen)
638 	    suflen = strlen(p+1);
639     }
640     suflen++;
641     prev = sfnt_indextoglyph(sf, sf->glyphsbyname[0]);
642     for (i = 1; i < sf->nglyphs; i++) {
643 	if (prev == (this = sfnt_indextoglyph(sf, sf->glyphsbyname[i]))) {
644 	    char const *basename;
645 	    char *buf;
646 	    basename = glyph_extern(this);
647 	    buf = snewn(strlen(basename) + 2 + suflen, char);
648 	    strcpy(buf, basename);
649 	    sprintf(buf + strlen(basename), ".%0*hu", suflen,
650 		    sf->glyphsbyname[i]);
651 	    sf->glyphsbyindex[sf->glyphsbyname[i]] = glyph_intern(buf);
652 	    sfree(buf);
653 	}
654 	prev = this;
655     }
656     /* We may have renamed some glyphs, so re-sort the array. */
657     qsort(sf->glyphsbyname, sf->nglyphs, sizeof(*sf->glyphsbyname),
658 	  glyphsbyname_cmp);
659 }
660 
sfnt_indextoglyph(sfnt * sf,unsigned idx)661 glyph sfnt_indextoglyph(sfnt *sf, unsigned idx) {
662     return sf->glyphsbyindex[idx];
663 }
664 
sfnt_nglyphs(sfnt * sf)665 unsigned sfnt_nglyphs(sfnt *sf) {
666     return sf->nglyphs;
667 }
668 
sfnt_glyphtoindex(sfnt * sf,glyph g)669 unsigned sfnt_glyphtoindex(sfnt *sf, glyph g) {
670     cmp_glyphsbyindex = sf->glyphsbyindex;
671     return *(unsigned short *)bsearch(&g, sf->glyphsbyname, sf->nglyphs,
672 				      sizeof(*sf->glyphsbyname),
673 				      glyphsbyname_cmp_search);
674 }
675 
676 /*
677  * Get data from 'hhea', 'hmtx', and 'OS/2' tables
678  */
sfnt_getmetrics(font_info * fi)679 void sfnt_getmetrics(font_info *fi) {
680     sfnt *sf = fi->fontfile;
681     t_hhea hhea;
682     t_OS_2 OS_2;
683     void *ptr, *end;
684     unsigned i, j;
685     unsigned *hmtx;
686 
687     /* First, the bounding box from the 'head' table. */
688     fi->fontbbox[0] = sf->head.xMin * FUNITS_PER_PT /  sf->head.unitsPerEm;
689     fi->fontbbox[1] = sf->head.yMin * FUNITS_PER_PT /  sf->head.unitsPerEm;
690     fi->fontbbox[2] = sf->head.xMax * FUNITS_PER_PT /  sf->head.unitsPerEm;
691     fi->fontbbox[3] = sf->head.yMax * FUNITS_PER_PT /  sf->head.unitsPerEm;
692     if (!sfnt_findtable(sf, TAG_hhea, &ptr, &end)) {
693 	err_sfntnotable(&sf->pos, "hhea");
694 	return;
695     }
696     if (decode(t_hhea_decode, ptr, end, &hhea) == NULL) {
697 	err_sfntbadtable(&sf->pos, "hhea");
698 	return;
699     }
700     if ((hhea.version & 0xffff0000) != 0x00010000) {
701 	err_sfnttablevers(&sf->pos, "hhea");
702 	return;
703     }
704     fi->ascent = hhea.ascent;
705     fi->descent = hhea.descent;
706     if (hhea.metricDataFormat != 0) {
707 	err_sfnttablevers(&sf->pos, "hmtx");
708 	return;
709     }
710     if (!sfnt_findtable(sf, TAG_hmtx, &ptr, &end)) {
711 	err_sfntnotable(&sf->pos, "hmtx");
712 	return;
713     }
714     hmtx = snewn(hhea.numOfLongHorMetrics, unsigned);
715     if (decoden(longhormetric_decode, ptr, end, hmtx, sizeof(*hmtx),
716 		hhea.numOfLongHorMetrics) == NULL) {
717 	err_sfntbadtable(&sf->pos, "hmtx");
718 	return;
719     }
720     for (i = 0; i < sf->nglyphs; i++) {
721 	glyph_width *w = snew(glyph_width);
722 	w->glyph = sfnt_indextoglyph(sf, i);
723 	j = i < hhea.numOfLongHorMetrics ? i : hhea.numOfLongHorMetrics - 1;
724 	w->width = hmtx[j] * UNITS_PER_PT / sf->head.unitsPerEm;
725 	add234(fi->widths, w);
726     }
727     /* Now see if the 'OS/2' table has any useful metrics */
728     if (!sfnt_findtable(sf, TAG_OS_2, &ptr, &end))
729 	return;
730     if (decode(uint16_decode, ptr, end, &OS_2.version) == NULL)
731 	goto bados2;
732     if (OS_2.version >= 2) {
733 	if (decode(t_OS_2_v2_decode, ptr, end, &OS_2) == NULL)
734 	    goto bados2;
735 	fi->xheight = OS_2.sxHeight * FUNITS_PER_PT / sf->head.unitsPerEm;
736 	fi->capheight = OS_2.sCapHeight * FUNITS_PER_PT / sf->head.unitsPerEm;
737     } else if (OS_2.version == 1) {
738 	if (decode(t_OS_2_v1_decode, ptr, end, &OS_2) == NULL)
739 	    goto bados2;
740     } else
741 	return;
742     fi->ascent = OS_2.sTypoAscender * FUNITS_PER_PT / sf->head.unitsPerEm;
743     fi->descent = OS_2.sTypoDescender * FUNITS_PER_PT / sf->head.unitsPerEm;
744     return;
745   bados2:
746     err_sfntbadtable(&sf->pos, "OS/2");
747 }
748 
749 /*
750  * Get kerning data from a 'kern' table
751  *
752  * 'kern' tables have two gratuitously different header formats, one
753  * used by Apple and one by Microsoft.  Happily, the kerning tables
754  * themselves use the same formats.  Halibut only supports simple kern
755  * pairs for horizontal kerning of horizontal text, and ignores
756  * everything else.
757  */
sfnt_getkern(font_info * fi)758 static void sfnt_getkern(font_info *fi) {
759     sfnt *sf = fi->fontfile;
760     t_kern kern;
761     unsigned version, i, j;
762     void *ptr, *end;
763 
764     if (!sfnt_findtable(sf, TAG_kern, &ptr, &end))
765 	return;
766     if (!decode(uint16_decode, ptr, end, &version))
767 	goto bad;
768     if (version == 0)
769 	ptr = decode(t_kern_v0_decode, ptr, end, &kern);
770     else if (version == 1)
771 	ptr = decode(t_kern_v1_decode, ptr, end, &kern);
772     else return;
773     if (ptr == NULL) goto bad;
774     for (i = 0; i < kern.nTables; i++) {
775 	kern_f0 f0;
776 	kern_pair *kerns;
777 	if (version == 0) {
778 	    kern_v0_subhdr sub;
779 	    ptr = decode(kern_v0_subhdr_decode, ptr, end, &sub);
780 	    if (ptr == NULL) goto bad;
781 	    if (sub.version != 0 ||
782 		(sub.coverage & (KERN_V0_HORIZ | KERN_V0_MINIMUM |
783 				 KERN_V0_CROSSSTREAM | KERN_V0_FORMAT)) !=
784 		(KERN_V0_HORIZ | KERN_V0_FORMAT_0)) {
785 		ptr = (char *)ptr + sub.length - 6;
786 		continue;
787 	    }
788 	} else {
789 	    kern_v1_subhdr sub;
790 	    ptr = decode(kern_v1_subhdr_decode, ptr, end, &sub);
791 	    if (ptr == NULL) goto bad;
792 	    if ((sub.coverage & (KERN_V1_VERTICAL | KERN_V1_CROSSSTREAM |
793 				KERN_V1_VARIATION | KERN_V1_FORMAT)) !=
794 		KERN_V0_FORMAT_0) {
795 		ptr = (char *)ptr + sub.length - 8;
796 		continue;
797 	    }
798 	}
799 	ptr = decode(kern_f0_decode, ptr, end, &f0);
800 	if (ptr == NULL) goto bad;
801 	kerns = snewn(f0.nPairs, kern_pair);
802 	for (j = 0; j < f0.nPairs; j++) {
803 	    kern_f0_pair p;
804 	    kern_pair *kp = kerns + j;
805 	    ptr = decode(kern_f0_pair_decode, ptr, end, &p);
806 	    if (ptr == NULL) goto bad;
807 	    if (p.left >= sf->nglyphs || p.right >= sf->nglyphs) goto bad;
808 	    kp->left = sfnt_indextoglyph(sf, p.left);
809 	    kp->right = sfnt_indextoglyph(sf, p.right);
810 	    kp->kern = p.value * UNITS_PER_PT / (int)sf->head.unitsPerEm;
811 	    add234(fi->kerns, kp);
812 	}
813     }
814     return;
815   bad:
816     err_sfntbadtable(&sf->pos, "kern");
817     return;
818 }
819 
820 /*
821  * Get mapping data from 'cmap' table
822  *
823  * We look for either a (0, 0), (0, 2), (0, 3), or (3, 1) table, all
824  * of these being versions of UCS-2.  We ignore (0, 1), since it's
825  * Unicode 1.1 with precomposed Hangul syllables.  We only handle
826  * format 4 of this table, since that seems to be the only one in use.
827  */
sfnt_getmap(font_info * fi)828 void sfnt_getmap(font_info *fi) {
829     sfnt *sf = fi->fontfile;
830     t_cmap cmap;
831     encodingrec *esd;
832     void *base, *ptr, *end;
833     unsigned i;
834     unsigned format;
835 
836 
837     for (i = 0; i < lenof(fi->bmp); i++)
838 	    fi->bmp[i] = 0xFFFF;
839     if (!sfnt_findtable(sf, TAG_cmap, &ptr, &end)) {
840 	err_sfntnotable(&sf->pos, "cmap");
841     }
842     base = ptr;
843     ptr = decode(t_cmap_decode, ptr, end, &cmap);
844     if (ptr == NULL) goto bad;
845     esd = snewn(cmap.numTables, encodingrec);
846     ptr = decoden(encodingrec_decode, ptr, end, esd, sizeof(*esd),
847 		  cmap.numTables);
848     if (ptr == NULL) goto bad;
849     for (i = 0; i < cmap.numTables; i++) {
850 	if (!decode(uint16_decode, (char *)base + esd[i].offset, end, &format))
851 	    goto bad;
852 	if ((esd[i].platformID == 0 && esd[i].encodingID == 0) ||
853 	    (esd[i].platformID == 0 && esd[i].encodingID == 2) ||
854 	    (esd[i].platformID == 0 && esd[i].encodingID == 3) ||
855 	    (esd[i].platformID == 3 && esd[i].encodingID == 1)) {
856 	    /* UCS-2 encoding */
857 	    if (!decode(uint16_decode, (char *)base + esd[i].offset, end,
858 			&format))
859 		goto bad;
860 	    if (format == 4) {
861 		unsigned *data, *endCode, *startCode, *idDelta, *idRangeOffset;
862 		unsigned *glyphIndexArray;
863 		unsigned segcount, nword, nglyphindex, j;
864 		cmap4 cmap4;
865 
866 		ptr = decode(cmap4_decode, (char *)base + esd[i].offset, end,
867 			     &cmap4);
868 		if (!ptr) goto bad;
869 		segcount = cmap4.segCountX2 / 2;
870 		nword = cmap4.length / 2 - 7;
871 		data = snewn(nword, unsigned);
872 		if (!decoden(uint16_decode, ptr, (char *)ptr + nword * 2,
873 			     data, sizeof(*data), nword)) goto bad;
874 		endCode = data;
875 		startCode = data + segcount + 1;
876 		idDelta = startCode + segcount;
877 		idRangeOffset = idDelta + segcount;
878 		glyphIndexArray = idRangeOffset + segcount;
879 		nglyphindex = nword - segcount * 4 - 1;
880 
881 		for (j = 0; j < segcount; j++) {
882 		    unsigned k, idx;
883 
884 		    if (idRangeOffset[j] == 0) {
885 			for (k = startCode[j]; k <= endCode[j]; k++) {
886 			    idx = (k + idDelta[j]) & 0xffff;
887 			    if (idx != 0) {
888 				if (idx > sf->nglyphs)  {
889 				    err_sfntbadglyph(&sf->pos, k);
890 				    continue;
891 				}
892 				fi->bmp[k] = sfnt_indextoglyph(sf, idx);
893 			    }
894 			}
895 		    } else {
896 			unsigned startidx = idRangeOffset[j]/2 - segcount + j;
897 			for (k = startCode[j]; k <= endCode[j]; k++) {
898 			    if (startidx + k - startCode[j] >=
899 				nglyphindex) {
900 				err_sfntbadglyph(&sf->pos, k);
901 				continue;
902 			    }
903 			    idx = glyphIndexArray[startidx + k - startCode[j]];
904 			    if (idx != 0) {
905 				idx = (idx + idDelta[j]) & 0xffff;
906 				if (idx > sf->nglyphs) {
907 				    err_sfntbadglyph(&sf->pos, k);
908 				    continue;
909 				}
910 				fi->bmp[k] = sfnt_indextoglyph(sf, idx);
911 			    }
912 			}
913 		    }
914 		}
915 		sfree(data);
916 		return;
917 	    }
918 	}
919     }
920     err_sfntnounicmap(&sf->pos);
921     return;
922   bad:
923     err_sfntbadtable(&sf->pos, "cmap");
924 }
925 
read_sfnt_file(input * in)926 void read_sfnt_file(input *in) {
927     sfnt *sf = snew(sfnt);
928     size_t off = 0, got;
929     FILE *fp = in->currfp;
930     font_info *fi = snew(font_info);
931     void *ptr, *end;
932     t_maxp maxp;
933 
934     fi->name = NULL;
935     fi->widths = newtree234(width_cmp);
936     fi->kerns = newtree234(kern_cmp);
937     fi->ligs = newtree234(lig_cmp);
938     fi->fontbbox[0] = fi->fontbbox[1] = fi->fontbbox[2] = fi->fontbbox[3] = 0;
939     fi->capheight = fi->xheight = fi->ascent = fi->descent = 0;
940     fi->stemh = fi->stemv = fi->italicangle = 0;
941     fi->fontfile = sf;
942     fi->filetype = TRUETYPE;
943 
944     sf->len = 32768;
945     sf->data = snewn(sf->len, unsigned char);
946     for (;;) {
947 	got = fread((char *)sf->data + off, 1, sf->len - off, fp);
948 	off += got;
949 	if (off != sf->len) break;
950 	sf->len *= 2;
951 	sf->data = sresize(sf->data, sf->len, unsigned char);
952     }
953     fclose(in->currfp);
954     sf->len = off;
955     sf->data = sresize(sf->data, sf->len, unsigned char);
956     sf->end = (char *)sf->data + sf->len;
957     sf->pos = in->pos;
958     sf->pos.line = 0;
959     sf->nglyphs = 0;
960     ptr = decode(offsubdir_decode, sf->data, sf->end, &sf->osd);
961     if (ptr == NULL) {
962 	err_sfntbadhdr(&sf->pos);
963 	return;
964     }
965     sf->td = snewn(sf->osd.numTables, tabledir);
966     ptr = decoden(tabledir_decode, ptr, sf->end, sf->td, sizeof(*sf->td),
967 		  sf->osd.numTables);
968     if (ptr == NULL) {
969 	err_sfntbadhdr(&sf->pos);
970 	return;
971     }
972     if (!sfnt_findtable(sf, TAG_head, &ptr, &end)) {
973 	err_sfntnotable(&sf->pos, "head");
974 	return;
975     }
976     if (decode(t_head_decode, ptr, end, &sf->head) == NULL) {
977 	err_sfntbadtable(&sf->pos, "head");
978 	return;
979     }
980     if ((sf->head.version & 0xffff0000) != 0x00010000) {
981 	err_sfnttablevers(&sf->pos, "head");
982 	return;
983     }
984     if (!sfnt_findtable(sf, TAG_maxp, &ptr, &end)) {
985 	err_sfntnotable(&sf->pos, "maxp");
986 	return;
987     }
988     if (decode(t_maxp_decode, ptr, end, &maxp) == NULL) {
989 	err_sfntbadtable(&sf->pos, "maxp");
990 	return;
991     }
992     if (maxp.version < 0x00005000 || maxp.version > 0x0001ffff) {
993 	err_sfnttablevers(&sf->pos, "maxp");
994 	return;
995     }
996     sf->nglyphs = maxp.numGlyphs;
997     fi->name = sfnt_psname(fi);
998     if (fi->name == NULL) return;
999     sfnt_mapglyphs(fi);
1000     sfnt_getmetrics(fi);
1001     sfnt_getkern(fi);
1002     sfnt_getmap(fi);
1003     fi->next = all_fonts;
1004     all_fonts = fi;
1005 }
1006 
sizecmp(const void * a,const void * b)1007 static int sizecmp(const void *a, const void *b) {
1008     if (*(size_t *)a < *(size_t *)b) return -1;
1009     if (*(size_t *)a > *(size_t *)b) return 1;
1010     return 0;
1011 }
1012 
1013 /*
1014  * The format for embedding TrueType fonts in Postscript is defined in
1015  * Adobe Technical Note #5012: The Type 42 Font Format Specification.
1016  * <http://partners.adobe.com/public/developer/en/font/5012.Type42_Spec.pdf>
1017  */
1018 
sfnt_writeps(font_info const * fi,FILE * ofp)1019 void sfnt_writeps(font_info const *fi, FILE *ofp) {
1020     unsigned i, j, lastbreak;
1021     sfnt *sf = fi->fontfile;
1022     size_t *breaks, glyfoff, glyflen;
1023     void *glyfptr, *glyfend, *locaptr, *locaend;
1024     unsigned *loca;
1025     int cc = 0;
1026 
1027     /* XXX Unclear that this is the correct format. */
1028     fprintf(ofp, "%%!PS-TrueTypeFont-%u-%u\n", sf->osd.scaler_type,
1029 	    sf->head.fontRevision);
1030     if (sf->minmem)
1031 	fprintf(ofp, "%%%%VMUsage: %u %u\n", sf->minmem, sf->maxmem);
1032     fprintf(ofp, "9 dict dup begin\n");
1033     fprintf(ofp, "/FontType 42 def\n");
1034     fprintf(ofp, "/FontMatrix [1 0 0 1 0 0] def\n");
1035     fprintf(ofp, "/FontName /%s def\n", fi->name);
1036     fprintf(ofp, "/Encoding StandardEncoding def\n");
1037     if ((sf->head.flags & 0x0003) == 0x0003) {
1038 	/*
1039 	 * Sensible font with the origin in the right place, such that
1040 	 * the bounding box is meaningful.
1041 	 */
1042 	fprintf(ofp, "/FontBBox [%g %g %g %g] readonly def\n",
1043 		(double)sf->head.xMin / sf->head.unitsPerEm,
1044 		(double)sf->head.yMin / sf->head.unitsPerEm,
1045 		(double)sf->head.xMax / sf->head.unitsPerEm,
1046 		(double)sf->head.yMax / sf->head.unitsPerEm);
1047     } else {
1048 	/* Non-sensible font. */
1049 	fprintf(ofp, "/FontBBox [0 0 0 0] readonly def\n");
1050     }
1051     fprintf(ofp, "/PaintType 0 def\n");
1052     fprintf(ofp, "/CharStrings %u dict dup begin\n", sf->nglyphs);
1053     fprintf(ofp, "0 1 %u{currentfile token pop exch def}bind for\n",
1054 	sf->nglyphs - 1);
1055     for (i = 0; i < sf->nglyphs; i++)
1056 	ps_token(ofp, &cc, "/%s", glyph_extern(sfnt_indextoglyph(sf, i)));
1057     fprintf(ofp, "\nend readonly def\n");
1058     fprintf(ofp, "/sfnts [<");
1059     breaks = snewn(sf->osd.numTables + sf->nglyphs, size_t);
1060     for (i = 0; i < sf->osd.numTables; i++) {
1061 	breaks[i] = sf->td[i].offset;
1062     }
1063     if (!sfnt_findtable(sf, TAG_glyf, &glyfptr, &glyfend)) {
1064 	err_sfntnotable(&sf->pos, "glyf");
1065 	return;
1066     }
1067     glyfoff = (char *)glyfptr - (char *)sf->data;
1068     glyflen = (char *)glyfend - (char *)glyfptr;
1069     if (!sfnt_findtable(sf, TAG_loca, &locaptr, &locaend)) {
1070 	err_sfntnotable(&sf->pos, "loca");
1071 	return;
1072     }
1073     loca = snewn(sf->nglyphs, unsigned);
1074     if (sf->head.indexToLocFormat == 0) {
1075 	if (!decoden(uint16_decode, locaptr, locaend, loca, sizeof(*loca),
1076 		     sf->nglyphs)) goto badloca;
1077 	for (i = 0; i < sf->nglyphs; i++) loca[i] *= 2;
1078     } else {
1079 	if (!decoden(uint32_decode, locaptr, locaend, loca, sizeof(*loca),
1080 		     sf->nglyphs)) goto badloca;
1081     }
1082     for (i = 1; i < sf->nglyphs; i++) {
1083 	if (loca[i] > glyflen) goto badloca;
1084 	breaks[sf->osd.numTables + i - 1] = loca[i] + glyfoff;
1085     }
1086     breaks[sf->osd.numTables + sf->nglyphs - 1] = sf->len;
1087     qsort(breaks, sf->osd.numTables + sf->nglyphs, sizeof(*breaks), sizecmp);
1088     j = lastbreak = 0;
1089     for (i = 0; i < sf->len; i++) {
1090 	if ((i - lastbreak) % 38 == 0) fprintf(ofp, "\n");
1091 	if (i == breaks[j]) {
1092 	    while (i == breaks[j]) j++;
1093 	    lastbreak = i;
1094 	    fprintf(ofp, "00><\n");
1095 	}
1096 	fprintf(ofp, "%02x", *((unsigned char *)sf->data + i));
1097     }
1098     fprintf(ofp, "00>] readonly def\n");
1099     sfree(breaks);
1100     fprintf(ofp, "end /%s exch definefont\n", fi->name);
1101     return;
1102   badloca:
1103     err_sfntbadtable(&sf->pos, "loca");
1104 }
1105 
sfnt_data(font_info * fi,char ** bufp,size_t * lenp)1106 void sfnt_data(font_info *fi, char **bufp, size_t *lenp) {
1107     sfnt *sf = fi->fontfile;
1108     *bufp = sf->data;
1109     *lenp = sf->len;
1110 }
1111