1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package truetype
19
20 import (
21 "fmt"
22
23 "golang.org/x/image/math/fixed"
24 )
25
26
27 type Index uint16
28
29
30
31
32 type NameID uint16
33
34 const (
35 NameIDCopyright NameID = 0
36 NameIDFontFamily = 1
37 NameIDFontSubfamily = 2
38 NameIDUniqueSubfamilyID = 3
39 NameIDFontFullName = 4
40 NameIDNameTableVersion = 5
41 NameIDPostscriptName = 6
42 NameIDTrademarkNotice = 7
43 NameIDManufacturerName = 8
44 NameIDDesignerName = 9
45 NameIDFontDescription = 10
46 NameIDFontVendorURL = 11
47 NameIDFontDesignerURL = 12
48 NameIDFontLicense = 13
49 NameIDFontLicenseURL = 14
50 NameIDPreferredFamily = 16
51 NameIDPreferredSubfamily = 17
52 NameIDCompatibleName = 18
53 NameIDSampleText = 19
54 )
55
56 const (
57
58
59
60 unicodeEncodingBMPOnly = 0x00000003
61 unicodeEncodingFull = 0x00000004
62 microsoftSymbolEncoding = 0x00030000
63 microsoftUCS2Encoding = 0x00030001
64 microsoftUCS4Encoding = 0x0003000a
65 )
66
67
68 type HMetric struct {
69 AdvanceWidth, LeftSideBearing fixed.Int26_6
70 }
71
72
73 type VMetric struct {
74 AdvanceHeight, TopSideBearing fixed.Int26_6
75 }
76
77
78 type FormatError string
79
80 func (e FormatError) Error() string {
81 return "freetype: invalid TrueType format: " + string(e)
82 }
83
84
85
86 type UnsupportedError string
87
88 func (e UnsupportedError) Error() string {
89 return "freetype: unsupported TrueType feature: " + string(e)
90 }
91
92
93 func u32(b []byte, i int) uint32 {
94 return uint32(b[i])<<24 | uint32(b[i+1])<<16 | uint32(b[i+2])<<8 | uint32(b[i+3])
95 }
96
97
98 func u16(b []byte, i int) uint16 {
99 return uint16(b[i])<<8 | uint16(b[i+1])
100 }
101
102
103 func readTable(ttf []byte, offsetLength []byte) ([]byte, error) {
104 offset := int(u32(offsetLength, 0))
105 if offset < 0 {
106 return nil, FormatError(fmt.Sprintf("offset too large: %d", uint32(offset)))
107 }
108 length := int(u32(offsetLength, 4))
109 if length < 0 {
110 return nil, FormatError(fmt.Sprintf("length too large: %d", uint32(length)))
111 }
112 end := offset + length
113 if end < 0 || end > len(ttf) {
114 return nil, FormatError(fmt.Sprintf("offset + length too large: %d", uint32(offset)+uint32(length)))
115 }
116 return ttf[offset:end], nil
117 }
118
119
120
121
122
123
124
125
126 func parseSubtables(table []byte, name string, offset, size int, pred func([]byte) bool) (
127 bestOffset int, bestPID uint32, retErr error) {
128
129 if len(table) < 4 {
130 return 0, 0, FormatError(name + " too short")
131 }
132 nSubtables := int(u16(table, 2))
133 if len(table) < size*nSubtables+offset {
134 return 0, 0, FormatError(name + " too short")
135 }
136 ok := false
137 for i := 0; i < nSubtables; i, offset = i+1, offset+size {
138 if pred != nil && !pred(table[offset:]) {
139 continue
140 }
141
142
143 pidPsid := u32(table, offset)
144
145
146 if pidPsid == unicodeEncodingBMPOnly || pidPsid == unicodeEncodingFull {
147 bestOffset, bestPID, ok = offset, pidPsid>>16, true
148 break
149
150 } else if pidPsid == microsoftSymbolEncoding ||
151 pidPsid == microsoftUCS2Encoding ||
152 pidPsid == microsoftUCS4Encoding {
153
154 bestOffset, bestPID, ok = offset, pidPsid>>16, true
155
156 }
157 }
158 if !ok {
159 return 0, 0, UnsupportedError(name + " encoding")
160 }
161 return bestOffset, bestPID, nil
162 }
163
164 const (
165 locaOffsetFormatUnknown int = iota
166 locaOffsetFormatShort
167 locaOffsetFormatLong
168 )
169
170
171 type cm struct {
172 start, end, delta, offset uint32
173 }
174
175
176 type Font struct {
177
178
179 cmap, cvt, fpgm, glyf, hdmx, head, hhea, hmtx, kern, loca, maxp, name, os2, prep, vmtx []byte
180
181 cmapIndexes []byte
182
183
184 cm []cm
185 locaOffsetFormat int
186 nGlyph, nHMetric, nKern int
187 fUnitsPerEm int32
188 ascent int32
189 descent int32
190 bounds fixed.Rectangle26_6
191
192 maxTwilightPoints, maxStorage, maxFunctionDefs, maxStackElements uint16
193 }
194
195 func (f *Font) parseCmap() error {
196 const (
197 cmapFormat4 = 4
198 cmapFormat12 = 12
199 languageIndependent = 0
200 )
201
202 offset, _, err := parseSubtables(f.cmap, "cmap", 4, 8, nil)
203 if err != nil {
204 return err
205 }
206 offset = int(u32(f.cmap, offset+4))
207 if offset <= 0 || offset > len(f.cmap) {
208 return FormatError("bad cmap offset")
209 }
210
211 cmapFormat := u16(f.cmap, offset)
212 switch cmapFormat {
213 case cmapFormat4:
214 language := u16(f.cmap, offset+4)
215 if language != languageIndependent {
216 return UnsupportedError(fmt.Sprintf("language: %d", language))
217 }
218 segCountX2 := int(u16(f.cmap, offset+6))
219 if segCountX2%2 == 1 {
220 return FormatError(fmt.Sprintf("bad segCountX2: %d", segCountX2))
221 }
222 segCount := segCountX2 / 2
223 offset += 14
224 f.cm = make([]cm, segCount)
225 for i := 0; i < segCount; i++ {
226 f.cm[i].end = uint32(u16(f.cmap, offset))
227 offset += 2
228 }
229 offset += 2
230 for i := 0; i < segCount; i++ {
231 f.cm[i].start = uint32(u16(f.cmap, offset))
232 offset += 2
233 }
234 for i := 0; i < segCount; i++ {
235 f.cm[i].delta = uint32(u16(f.cmap, offset))
236 offset += 2
237 }
238 for i := 0; i < segCount; i++ {
239 f.cm[i].offset = uint32(u16(f.cmap, offset))
240 offset += 2
241 }
242 f.cmapIndexes = f.cmap[offset:]
243 return nil
244
245 case cmapFormat12:
246 if u16(f.cmap, offset+2) != 0 {
247 return FormatError(fmt.Sprintf("cmap format: % x", f.cmap[offset:offset+4]))
248 }
249 length := u32(f.cmap, offset+4)
250 language := u32(f.cmap, offset+8)
251 if language != languageIndependent {
252 return UnsupportedError(fmt.Sprintf("language: %d", language))
253 }
254 nGroups := u32(f.cmap, offset+12)
255 if length != 12*nGroups+16 {
256 return FormatError("inconsistent cmap length")
257 }
258 offset += 16
259 f.cm = make([]cm, nGroups)
260 for i := uint32(0); i < nGroups; i++ {
261 f.cm[i].start = u32(f.cmap, offset+0)
262 f.cm[i].end = u32(f.cmap, offset+4)
263 f.cm[i].delta = u32(f.cmap, offset+8) - f.cm[i].start
264 offset += 12
265 }
266 return nil
267 }
268 return UnsupportedError(fmt.Sprintf("cmap format: %d", cmapFormat))
269 }
270
271 func (f *Font) parseHead() error {
272 if len(f.head) != 54 {
273 return FormatError(fmt.Sprintf("bad head length: %d", len(f.head)))
274 }
275 f.fUnitsPerEm = int32(u16(f.head, 18))
276 f.bounds.Min.X = fixed.Int26_6(int16(u16(f.head, 36)))
277 f.bounds.Min.Y = fixed.Int26_6(int16(u16(f.head, 38)))
278 f.bounds.Max.X = fixed.Int26_6(int16(u16(f.head, 40)))
279 f.bounds.Max.Y = fixed.Int26_6(int16(u16(f.head, 42)))
280 switch i := u16(f.head, 50); i {
281 case 0:
282 f.locaOffsetFormat = locaOffsetFormatShort
283 case 1:
284 f.locaOffsetFormat = locaOffsetFormatLong
285 default:
286 return FormatError(fmt.Sprintf("bad indexToLocFormat: %d", i))
287 }
288 return nil
289 }
290
291 func (f *Font) parseHhea() error {
292 if len(f.hhea) != 36 {
293 return FormatError(fmt.Sprintf("bad hhea length: %d", len(f.hhea)))
294 }
295 f.ascent = int32(int16(u16(f.hhea, 4)))
296 f.descent = int32(int16(u16(f.hhea, 6)))
297 f.nHMetric = int(u16(f.hhea, 34))
298 if 4*f.nHMetric+2*(f.nGlyph-f.nHMetric) != len(f.hmtx) {
299 return FormatError(fmt.Sprintf("bad hmtx length: %d", len(f.hmtx)))
300 }
301 return nil
302 }
303
304 func (f *Font) parseKern() error {
305
306
307
308
309
310
311
312
313
314 if len(f.kern) == 0 {
315 if f.nKern != 0 {
316 return FormatError("bad kern table length")
317 }
318 return nil
319 }
320 if len(f.kern) < 18 {
321 return FormatError("kern data too short")
322 }
323 version, offset := u16(f.kern, 0), 2
324 if version != 0 {
325 return UnsupportedError(fmt.Sprintf("kern version: %d", version))
326 }
327
328 n, offset := u16(f.kern, offset), offset+2
329 if n == 0 {
330 return UnsupportedError("kern nTables: 0")
331 }
332
333
334
335
336
337
338
339
340 offset += 2
341 length, offset := int(u16(f.kern, offset)), offset+2
342 coverage, offset := u16(f.kern, offset), offset+2
343 if coverage != 0x0001 {
344
345 return UnsupportedError(fmt.Sprintf("kern coverage: 0x%04x", coverage))
346 }
347 f.nKern, offset = int(u16(f.kern, offset)), offset+2
348 if 6*f.nKern != length-14 {
349 return FormatError("bad kern table length")
350 }
351 return nil
352 }
353
354 func (f *Font) parseMaxp() error {
355 if len(f.maxp) != 32 {
356 return FormatError(fmt.Sprintf("bad maxp length: %d", len(f.maxp)))
357 }
358 f.nGlyph = int(u16(f.maxp, 4))
359 f.maxTwilightPoints = u16(f.maxp, 16)
360 f.maxStorage = u16(f.maxp, 18)
361 f.maxFunctionDefs = u16(f.maxp, 20)
362 f.maxStackElements = u16(f.maxp, 24)
363 return nil
364 }
365
366
367 func (f *Font) scale(x fixed.Int26_6) fixed.Int26_6 {
368 if x >= 0 {
369 x += fixed.Int26_6(f.fUnitsPerEm) / 2
370 } else {
371 x -= fixed.Int26_6(f.fUnitsPerEm) / 2
372 }
373 return x / fixed.Int26_6(f.fUnitsPerEm)
374 }
375
376
377 func (f *Font) Bounds(scale fixed.Int26_6) fixed.Rectangle26_6 {
378 b := f.bounds
379 b.Min.X = f.scale(scale * b.Min.X)
380 b.Min.Y = f.scale(scale * b.Min.Y)
381 b.Max.X = f.scale(scale * b.Max.X)
382 b.Max.Y = f.scale(scale * b.Max.Y)
383 return b
384 }
385
386
387 func (f *Font) FUnitsPerEm() int32 {
388 return f.fUnitsPerEm
389 }
390
391
392 func (f *Font) Index(x rune) Index {
393 c := uint32(x)
394 for i, j := 0, len(f.cm); i < j; {
395 h := i + (j-i)/2
396 cm := &f.cm[h]
397 if c < cm.start {
398 j = h
399 } else if cm.end < c {
400 i = h + 1
401 } else if cm.offset == 0 {
402 return Index(c + cm.delta)
403 } else {
404 offset := int(cm.offset) + 2*(h-len(f.cm)+int(c-cm.start))
405 return Index(u16(f.cmapIndexes, offset))
406 }
407 }
408 return 0
409 }
410
411
412
413 func (f *Font) Name(id NameID) string {
414 x, platformID, err := parseSubtables(f.name, "name", 6, 12, func(b []byte) bool {
415 return NameID(u16(b, 6)) == id
416 })
417 if err != nil {
418 return ""
419 }
420 offset, length := u16(f.name, 4)+u16(f.name, x+10), u16(f.name, x+8)
421
422
423 src := f.name[offset : offset+length]
424 var dst []byte
425 if platformID != 1 {
426 if len(src)&1 != 0 {
427 return ""
428 }
429 dst = make([]byte, len(src)/2)
430 for i := range dst {
431 dst[i] = printable(u16(src, 2*i))
432 }
433 } else {
434 dst = make([]byte, len(src))
435 for i, c := range src {
436 dst[i] = printable(uint16(c))
437 }
438 }
439 return string(dst)
440 }
441
442 func printable(r uint16) byte {
443 if 0x20 <= r && r < 0x7f {
444 return byte(r)
445 }
446 return '?'
447 }
448
449
450
451 func (f *Font) unscaledHMetric(i Index) (h HMetric) {
452 j := int(i)
453 if j < 0 || f.nGlyph <= j {
454 return HMetric{}
455 }
456 if j >= f.nHMetric {
457 p := 4 * (f.nHMetric - 1)
458 return HMetric{
459 AdvanceWidth: fixed.Int26_6(u16(f.hmtx, p)),
460 LeftSideBearing: fixed.Int26_6(int16(u16(f.hmtx, p+2*(j-f.nHMetric)+4))),
461 }
462 }
463 return HMetric{
464 AdvanceWidth: fixed.Int26_6(u16(f.hmtx, 4*j)),
465 LeftSideBearing: fixed.Int26_6(int16(u16(f.hmtx, 4*j+2))),
466 }
467 }
468
469
470 func (f *Font) HMetric(scale fixed.Int26_6, i Index) HMetric {
471 h := f.unscaledHMetric(i)
472 h.AdvanceWidth = f.scale(scale * h.AdvanceWidth)
473 h.LeftSideBearing = f.scale(scale * h.LeftSideBearing)
474 return h
475 }
476
477
478
479 func (f *Font) unscaledVMetric(i Index, yMax fixed.Int26_6) (v VMetric) {
480 j := int(i)
481 if j < 0 || f.nGlyph <= j {
482 return VMetric{}
483 }
484 if 4*j+4 <= len(f.vmtx) {
485 return VMetric{
486 AdvanceHeight: fixed.Int26_6(u16(f.vmtx, 4*j)),
487 TopSideBearing: fixed.Int26_6(int16(u16(f.vmtx, 4*j+2))),
488 }
489 }
490
491
492
493
494
495 if len(f.os2) >= 72 {
496 sTypoAscender := fixed.Int26_6(int16(u16(f.os2, 68)))
497 sTypoDescender := fixed.Int26_6(int16(u16(f.os2, 70)))
498 return VMetric{
499 AdvanceHeight: sTypoAscender - sTypoDescender,
500 TopSideBearing: sTypoAscender - yMax,
501 }
502 }
503 return VMetric{
504 AdvanceHeight: fixed.Int26_6(f.fUnitsPerEm),
505 TopSideBearing: 0,
506 }
507 }
508
509
510 func (f *Font) VMetric(scale fixed.Int26_6, i Index) VMetric {
511
512 v := f.unscaledVMetric(i, 0)
513 v.AdvanceHeight = f.scale(scale * v.AdvanceHeight)
514 v.TopSideBearing = f.scale(scale * v.TopSideBearing)
515 return v
516 }
517
518
519
520 func (f *Font) Kern(scale fixed.Int26_6, i0, i1 Index) fixed.Int26_6 {
521 if f.nKern == 0 {
522 return 0
523 }
524 g := uint32(i0)<<16 | uint32(i1)
525 lo, hi := 0, f.nKern
526 for lo < hi {
527 i := (lo + hi) / 2
528 ig := u32(f.kern, 18+6*i)
529 if ig < g {
530 lo = i + 1
531 } else if ig > g {
532 hi = i
533 } else {
534 return f.scale(scale * fixed.Int26_6(int16(u16(f.kern, 22+6*i))))
535 }
536 }
537 return 0
538 }
539
540
541
542
543 func Parse(ttf []byte) (font *Font, err error) {
544 return parse(ttf, 0)
545 }
546
547 func parse(ttf []byte, offset int) (font *Font, err error) {
548 if len(ttf)-offset < 12 {
549 err = FormatError("TTF data is too short")
550 return
551 }
552 originalOffset := offset
553 magic, offset := u32(ttf, offset), offset+4
554 switch magic {
555 case 0x00010000:
556
557 case 0x74746366:
558 if originalOffset != 0 {
559 err = FormatError("recursive TTC")
560 return
561 }
562 ttcVersion, offset := u32(ttf, offset), offset+4
563 if ttcVersion != 0x00010000 && ttcVersion != 0x00020000 {
564 err = FormatError("bad TTC version")
565 return
566 }
567 numFonts, offset := int(u32(ttf, offset)), offset+4
568 if numFonts <= 0 {
569 err = FormatError("bad number of TTC fonts")
570 return
571 }
572 if len(ttf[offset:])/4 < numFonts {
573 err = FormatError("TTC offset table is too short")
574 return
575 }
576
577
578
579 offset = int(u32(ttf, offset))
580 if offset <= 0 || offset > len(ttf) {
581 err = FormatError("bad TTC offset")
582 return
583 }
584 return parse(ttf, offset)
585 default:
586 err = FormatError("bad TTF version")
587 return
588 }
589 n, offset := int(u16(ttf, offset)), offset+2
590 offset += 6
591 if len(ttf) < 16*n+offset {
592 err = FormatError("TTF data is too short")
593 return
594 }
595 f := new(Font)
596
597 for i := 0; i < n; i++ {
598 x := 16*i + offset
599 switch string(ttf[x : x+4]) {
600 case "cmap":
601 f.cmap, err = readTable(ttf, ttf[x+8:x+16])
602 case "cvt ":
603 f.cvt, err = readTable(ttf, ttf[x+8:x+16])
604 case "fpgm":
605 f.fpgm, err = readTable(ttf, ttf[x+8:x+16])
606 case "glyf":
607 f.glyf, err = readTable(ttf, ttf[x+8:x+16])
608 case "hdmx":
609 f.hdmx, err = readTable(ttf, ttf[x+8:x+16])
610 case "head":
611 f.head, err = readTable(ttf, ttf[x+8:x+16])
612 case "hhea":
613 f.hhea, err = readTable(ttf, ttf[x+8:x+16])
614 case "hmtx":
615 f.hmtx, err = readTable(ttf, ttf[x+8:x+16])
616 case "kern":
617 f.kern, err = readTable(ttf, ttf[x+8:x+16])
618 case "loca":
619 f.loca, err = readTable(ttf, ttf[x+8:x+16])
620 case "maxp":
621 f.maxp, err = readTable(ttf, ttf[x+8:x+16])
622 case "name":
623 f.name, err = readTable(ttf, ttf[x+8:x+16])
624 case "OS/2":
625 f.os2, err = readTable(ttf, ttf[x+8:x+16])
626 case "prep":
627 f.prep, err = readTable(ttf, ttf[x+8:x+16])
628 case "vmtx":
629 f.vmtx, err = readTable(ttf, ttf[x+8:x+16])
630 }
631 if err != nil {
632 return
633 }
634 }
635
636 if err = f.parseHead(); err != nil {
637 return
638 }
639 if err = f.parseMaxp(); err != nil {
640 return
641 }
642 if err = f.parseCmap(); err != nil {
643 return
644 }
645 if err = f.parseKern(); err != nil {
646 return
647 }
648 if err = f.parseHhea(); err != nil {
649 return
650 }
651 font = f
652 return
653 }
654
View as plain text