1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package sfnt
32
33
34
35
36
37
38
39
40
41
42
43
44 import (
45 "errors"
46 "image"
47 "io"
48
49 "golang.org/x/image/font"
50 "golang.org/x/image/math/fixed"
51 "golang.org/x/text/encoding/charmap"
52 )
53
54
55
56 const (
57
58
59
60
61
62
63
64
65
66
67
68
69 maxCmapSegments = 20000
70
71
72
73 maxNumSubroutines = 40000
74
75 maxCompoundRecursionDepth = 8
76 maxCompoundStackSize = 64
77 maxGlyphDataLength = 64 * 1024
78 maxHintBits = 256
79 maxNumFontDicts = 256
80 maxNumFonts = 256
81 maxNumTables = 256
82 maxRealNumberStrLen = 64
83
84
85 maxTableLength = 1 << 29
86 maxTableOffset = 1 << 29
87 )
88
89 var (
90
91
92 ErrColoredGlyph = errors.New("sfnt: colored glyph")
93
94 ErrNotFound = errors.New("sfnt: not found")
95
96 errInvalidBounds = errors.New("sfnt: invalid bounds")
97 errInvalidCFFTable = errors.New("sfnt: invalid CFF table")
98 errInvalidCmapTable = errors.New("sfnt: invalid cmap table")
99 errInvalidDfont = errors.New("sfnt: invalid dfont")
100 errInvalidFont = errors.New("sfnt: invalid font")
101 errInvalidFontCollection = errors.New("sfnt: invalid font collection")
102 errInvalidGPOSTable = errors.New("sfnt: invalid GPOS table")
103 errInvalidGlyphData = errors.New("sfnt: invalid glyph data")
104 errInvalidGlyphDataLength = errors.New("sfnt: invalid glyph data length")
105 errInvalidHeadTable = errors.New("sfnt: invalid head table")
106 errInvalidHheaTable = errors.New("sfnt: invalid hhea table")
107 errInvalidHmtxTable = errors.New("sfnt: invalid hmtx table")
108 errInvalidKernTable = errors.New("sfnt: invalid kern table")
109 errInvalidLocaTable = errors.New("sfnt: invalid loca table")
110 errInvalidLocationData = errors.New("sfnt: invalid location data")
111 errInvalidMaxpTable = errors.New("sfnt: invalid maxp table")
112 errInvalidNameTable = errors.New("sfnt: invalid name table")
113 errInvalidOS2Table = errors.New("sfnt: invalid OS/2 table")
114 errInvalidPostTable = errors.New("sfnt: invalid post table")
115 errInvalidSingleFont = errors.New("sfnt: invalid single font (data is a font collection)")
116 errInvalidSourceData = errors.New("sfnt: invalid source data")
117 errInvalidTableOffset = errors.New("sfnt: invalid table offset")
118 errInvalidTableTagOrder = errors.New("sfnt: invalid table tag order")
119 errInvalidUCS2String = errors.New("sfnt: invalid UCS-2 string")
120
121 errUnsupportedCFFFDSelectTable = errors.New("sfnt: unsupported CFF FDSelect table")
122 errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
123 errUnsupportedClassDefFormat = errors.New("sfnt: unsupported class definition format")
124 errUnsupportedCmapEncodings = errors.New("sfnt: unsupported cmap encodings")
125 errUnsupportedCollection = errors.New("sfnt: unsupported collection")
126 errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
127 errUnsupportedCoverageFormat = errors.New("sfnt: unsupported coverage format")
128 errUnsupportedExtensionPosFormat = errors.New("sfnt: unsupported extension positioning format")
129 errUnsupportedGPOSTable = errors.New("sfnt: unsupported GPOS table")
130 errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
131 errUnsupportedKernTable = errors.New("sfnt: unsupported kern table")
132 errUnsupportedNumberOfCmapSegments = errors.New("sfnt: unsupported number of cmap segments")
133 errUnsupportedNumberOfFontDicts = errors.New("sfnt: unsupported number of font dicts")
134 errUnsupportedNumberOfFonts = errors.New("sfnt: unsupported number of fonts")
135 errUnsupportedNumberOfHints = errors.New("sfnt: unsupported number of hints")
136 errUnsupportedNumberOfSubroutines = errors.New("sfnt: unsupported number of subroutines")
137 errUnsupportedNumberOfTables = errors.New("sfnt: unsupported number of tables")
138 errUnsupportedPlatformEncoding = errors.New("sfnt: unsupported platform encoding")
139 errUnsupportedPostTable = errors.New("sfnt: unsupported post table")
140 errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
141 errUnsupportedTableOffsetLength = errors.New("sfnt: unsupported table offset or length")
142 errUnsupportedType2Charstring = errors.New("sfnt: unsupported Type 2 Charstring")
143 )
144
145
146 type GlyphIndex uint16
147
148
149
150
151
152 type NameID uint16
153
154 const (
155 NameIDCopyright NameID = 0
156 NameIDFamily NameID = 1
157 NameIDSubfamily NameID = 2
158 NameIDUniqueIdentifier NameID = 3
159 NameIDFull NameID = 4
160 NameIDVersion NameID = 5
161 NameIDPostScript NameID = 6
162 NameIDTrademark NameID = 7
163 NameIDManufacturer NameID = 8
164 NameIDDesigner NameID = 9
165 NameIDDescription NameID = 10
166 NameIDVendorURL NameID = 11
167 NameIDDesignerURL NameID = 12
168 NameIDLicense NameID = 13
169 NameIDLicenseURL NameID = 14
170 NameIDTypographicFamily NameID = 16
171 NameIDTypographicSubfamily NameID = 17
172 NameIDCompatibleFull NameID = 18
173 NameIDSampleText NameID = 19
174 NameIDPostScriptCID NameID = 20
175 NameIDWWSFamily NameID = 21
176 NameIDWWSSubfamily NameID = 22
177 NameIDLightBackgroundPalette NameID = 23
178 NameIDDarkBackgroundPalette NameID = 24
179 NameIDVariationsPostScriptPrefix NameID = 25
180 )
181
182
183
184
185
186 type Units int32
187
188
189
190 func scale(x fixed.Int26_6, unitsPerEm Units) fixed.Int26_6 {
191 if x >= 0 {
192 x += fixed.Int26_6(unitsPerEm) / 2
193 } else {
194 x -= fixed.Int26_6(unitsPerEm) / 2
195 }
196 return x / fixed.Int26_6(unitsPerEm)
197 }
198
199 func u16(b []byte) uint16 {
200 _ = b[1]
201 return uint16(b[0])<<8 | uint16(b[1])<<0
202 }
203
204 func u32(b []byte) uint32 {
205 _ = b[3]
206 return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])<<0
207 }
208
209
210
211
212
213
214
215
216 type source struct {
217 b []byte
218 r io.ReaderAt
219
220
221
222 }
223
224
225 func (s *source) valid() bool {
226 return (s.b == nil) != (s.r == nil)
227 }
228
229
230
231
232
233
234
235 func (s *source) viewBufferWritable() bool {
236 return s.b == nil
237 }
238
239
240
241
242
243
244
245 func (s *source) view(buf []byte, offset, length int) ([]byte, error) {
246 if 0 > offset || offset > offset+length {
247 return nil, errInvalidBounds
248 }
249
250
251 if s.b != nil {
252 if offset+length > len(s.b) {
253 return nil, errInvalidBounds
254 }
255 return s.b[offset : offset+length], nil
256 }
257
258
259 if length <= cap(buf) {
260 buf = buf[:length]
261 } else {
262
263
264 n := length
265 n += 1023
266 n &^= 1023
267 buf = make([]byte, length, n)
268 }
269 if n, err := s.r.ReadAt(buf, int64(offset)); n != length {
270 return nil, err
271 }
272 return buf, nil
273 }
274
275
276
277
278
279 func (s *source) varLenView(buf []byte, offset, staticLength, countOffset, itemLength int) ([]byte, int, error) {
280 if 0 > offset || offset > offset+staticLength {
281 return nil, 0, errInvalidBounds
282 }
283 if 0 > countOffset || countOffset+1 >= staticLength {
284 return nil, 0, errInvalidBounds
285 }
286
287
288 buf, err := s.view(buf, offset, staticLength)
289 if err != nil {
290 return nil, 0, err
291 }
292
293 count := int(u16(buf[countOffset:]))
294 buf, err = s.view(buf, offset, staticLength+count*itemLength)
295 if err != nil {
296 return nil, 0, err
297 }
298
299 return buf, count, nil
300 }
301
302
303
304
305 func (s *source) u16(buf []byte, t table, i int) (uint16, error) {
306 if i < 0 || uint(t.length) < uint(i+2) {
307 return 0, errInvalidBounds
308 }
309 buf, err := s.view(buf, int(t.offset)+i, 2)
310 if err != nil {
311 return 0, err
312 }
313 return u16(buf), nil
314 }
315
316
317
318
319 func (s *source) u32(buf []byte, t table, i int) (uint32, error) {
320 if i < 0 || uint(t.length) < uint(i+4) {
321 return 0, errInvalidBounds
322 }
323 buf, err := s.view(buf, int(t.offset)+i, 4)
324 if err != nil {
325 return 0, err
326 }
327 return u32(buf), nil
328 }
329
330
331 type table struct {
332 offset, length uint32
333 }
334
335
336
337
338
339
340
341
342
343 func ParseCollection(src []byte) (*Collection, error) {
344 c := &Collection{src: source{b: src}}
345 if err := c.initialize(); err != nil {
346 return nil, err
347 }
348 return c, nil
349 }
350
351
352
353
354
355
356
357
358
359 func ParseCollectionReaderAt(src io.ReaderAt) (*Collection, error) {
360 c := &Collection{src: source{r: src}}
361 if err := c.initialize(); err != nil {
362 return nil, err
363 }
364 return c, nil
365 }
366
367
368
369
370 type Collection struct {
371 src source
372 offsets []uint32
373 isDfont bool
374 }
375
376
377 func (c *Collection) NumFonts() int { return len(c.offsets) }
378
379 func (c *Collection) initialize() error {
380
381
382
383
384
385
386
387 buf, err := c.src.view(nil, 0, 16)
388 if err != nil {
389 return err
390 }
391
392 switch u32(buf) {
393 default:
394 return errInvalidFontCollection
395 case dfontResourceDataOffset:
396 return c.parseDfont(buf, u32(buf[4:]), u32(buf[12:]))
397 case 0x00010000, 0x4f54544f, 0x74727565:
398
399 c.offsets = []uint32{0}
400 case 0x74746366:
401 numFonts := u32(buf[8:])
402 if numFonts == 0 || numFonts > maxNumFonts {
403 return errUnsupportedNumberOfFonts
404 }
405 buf, err = c.src.view(nil, 12, int(4*numFonts))
406 if err != nil {
407 return err
408 }
409 c.offsets = make([]uint32, numFonts)
410 for i := range c.offsets {
411 o := u32(buf[4*i:])
412 if o > maxTableOffset {
413 return errUnsupportedTableOffsetLength
414 }
415 c.offsets[i] = o
416 }
417 }
418 return nil
419 }
420
421
422
423
424
425
426
427
428
429 const dfontResourceDataOffset = 0x00000100
430
431
432
433
434
435
436
437
438
439 func (c *Collection) parseDfont(buf []byte, resourceMapOffset, resourceMapLength uint32) error {
440 if resourceMapOffset > maxTableOffset || resourceMapLength > maxTableLength {
441 return errUnsupportedTableOffsetLength
442 }
443
444 const headerSize = 28
445 if resourceMapLength < headerSize {
446 return errInvalidDfont
447 }
448 buf, err := c.src.view(buf, int(resourceMapOffset+24), 2)
449 if err != nil {
450 return err
451 }
452 typeListOffset := int(int16(u16(buf)))
453
454 if typeListOffset < headerSize || resourceMapLength < uint32(typeListOffset)+2 {
455 return errInvalidDfont
456 }
457 buf, err = c.src.view(buf, int(resourceMapOffset)+typeListOffset, 2)
458 if err != nil {
459 return err
460 }
461 typeCount := int(int16(u16(buf)))
462
463 const tSize = 8
464 if typeCount < 0 || tSize*uint32(typeCount) > resourceMapLength-uint32(typeListOffset)-2 {
465 return errInvalidDfont
466 }
467 buf, err = c.src.view(buf, int(resourceMapOffset)+typeListOffset+2, tSize*typeCount)
468 if err != nil {
469 return err
470 }
471 resourceCount, resourceListOffset := 0, 0
472 for i := 0; i < typeCount; i++ {
473 if u32(buf[tSize*i:]) != 0x73666e74 {
474 continue
475 }
476
477 resourceCount = int(int16(u16(buf[tSize*i+4:])))
478 if resourceCount < 0 {
479 return errInvalidDfont
480 }
481
482
483
484 resourceCount++
485
486 resourceListOffset = int(int16(u16(buf[tSize*i+6:])))
487 if resourceListOffset < 0 {
488 return errInvalidDfont
489 }
490 break
491 }
492 if resourceCount == 0 {
493 return errInvalidDfont
494 }
495 if resourceCount > maxNumFonts {
496 return errUnsupportedNumberOfFonts
497 }
498
499 const rSize = 12
500 if o, n := uint32(typeListOffset+resourceListOffset), rSize*uint32(resourceCount); o > resourceMapLength || n > resourceMapLength-o {
501 return errInvalidDfont
502 } else {
503 buf, err = c.src.view(buf, int(resourceMapOffset+o), int(n))
504 if err != nil {
505 return err
506 }
507 }
508 c.offsets = make([]uint32, resourceCount)
509 for i := range c.offsets {
510 o := 0xffffff & u32(buf[rSize*i+4:])
511
512
513
514 o += dfontResourceDataOffset + 4
515 if o > maxTableOffset {
516 return errUnsupportedTableOffsetLength
517 }
518 c.offsets[i] = o
519 }
520 c.isDfont = true
521 return nil
522 }
523
524
525 func (c *Collection) Font(i int) (*Font, error) {
526 if i < 0 || len(c.offsets) <= i {
527 return nil, ErrNotFound
528 }
529 f := &Font{src: c.src}
530 if err := f.initialize(int(c.offsets[i]), c.isDfont); err != nil {
531 return nil, err
532 }
533 return f, nil
534 }
535
536
537
538
539
540
541 func Parse(src []byte) (*Font, error) {
542 f := &Font{src: source{b: src}}
543 if err := f.initialize(0, false); err != nil {
544 return nil, err
545 }
546 return f, nil
547 }
548
549
550
551
552
553
554 func ParseReaderAt(src io.ReaderAt) (*Font, error) {
555 f := &Font{src: source{r: src}}
556 if err := f.initialize(0, false); err != nil {
557 return nil, err
558 }
559 return f, nil
560 }
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590 type Font struct {
591 src source
592
593
594
595 initialOffset int32
596
597
598
599 cmap table
600 head table
601 hhea table
602 hmtx table
603 maxp table
604 name table
605 os2 table
606 post table
607
608
609
610
611
612
613 glyf table
614 loca table
615
616
617
618
619
620 cff table
621
622
623
624
625
626 cblc table
627
628
629
630
631
632 gpos table
633
634
635
636
637
638 kern table
639
640 cached struct {
641 ascent int32
642 capHeight int32
643 finalTableOffset int32
644 glyphData glyphData
645 glyphIndex glyphIndexFunc
646 bounds [4]int16
647 descent int32
648 indexToLocFormat bool
649 isColorBitmap bool
650 isPostScript bool
651 kernNumPairs int32
652 kernOffset int32
653 kernFuncs []kernFunc
654 lineGap int32
655 numHMetrics int32
656 post *PostTable
657 slope [2]int32
658 unitsPerEm Units
659 xHeight int32
660 }
661 }
662
663
664 func (f *Font) NumGlyphs() int { return len(f.cached.glyphData.locations) - 1 }
665
666
667 func (f *Font) UnitsPerEm() Units { return f.cached.unitsPerEm }
668
669 func (f *Font) initialize(offset int, isDfont bool) error {
670 if !f.src.valid() {
671 return errInvalidSourceData
672 }
673 buf, finalTableOffset, isPostScript, err := f.initializeTables(offset, isDfont)
674 if err != nil {
675 return err
676 }
677
678
679
680
681
682
683
684
685
686 buf, bounds, indexToLocFormat, unitsPerEm, err := f.parseHead(buf)
687 if err != nil {
688 return err
689 }
690 buf, numGlyphs, err := f.parseMaxp(buf, isPostScript)
691 if err != nil {
692 return err
693 }
694 buf, glyphData, isColorBitmap, err := f.parseGlyphData(buf, numGlyphs, indexToLocFormat, isPostScript)
695 if err != nil {
696 return err
697 }
698 buf, glyphIndex, err := f.parseCmap(buf)
699 if err != nil {
700 return err
701 }
702 buf, kernNumPairs, kernOffset, err := f.parseKern(buf)
703 if err != nil {
704 return err
705 }
706 buf, kernFuncs, err := f.parseGPOSKern(buf)
707 if err != nil {
708 return err
709 }
710 buf, ascent, descent, lineGap, run, rise, numHMetrics, err := f.parseHhea(buf, numGlyphs)
711 if err != nil {
712 return err
713 }
714 buf, err = f.parseHmtx(buf, numGlyphs, numHMetrics)
715 if err != nil {
716 return err
717 }
718 buf, hasXHeightCapHeight, xHeight, capHeight, err := f.parseOS2(buf)
719 if err != nil {
720 return err
721 }
722 buf, post, err := f.parsePost(buf, numGlyphs)
723 if err != nil {
724 return err
725 }
726
727 f.cached.ascent = ascent
728 f.cached.capHeight = capHeight
729 f.cached.finalTableOffset = finalTableOffset
730 f.cached.glyphData = glyphData
731 f.cached.glyphIndex = glyphIndex
732 f.cached.bounds = bounds
733 f.cached.descent = descent
734 f.cached.indexToLocFormat = indexToLocFormat
735 f.cached.isColorBitmap = isColorBitmap
736 f.cached.isPostScript = isPostScript
737 f.cached.kernNumPairs = kernNumPairs
738 f.cached.kernOffset = kernOffset
739 f.cached.kernFuncs = kernFuncs
740 f.cached.lineGap = lineGap
741 f.cached.numHMetrics = numHMetrics
742 f.cached.post = post
743 f.cached.slope = [2]int32{run, rise}
744 f.cached.unitsPerEm = unitsPerEm
745 f.cached.xHeight = xHeight
746
747 if !hasXHeightCapHeight {
748 xh, ch, err := f.initOS2VersionBelow2()
749 if err != nil {
750 return err
751 }
752 f.cached.xHeight = xh
753 f.cached.capHeight = ch
754 }
755
756 return nil
757 }
758
759 func (f *Font) initializeTables(offset int, isDfont bool) (buf1 []byte, finalTableOffset int32, isPostScript bool, err error) {
760 f.initialOffset = int32(offset)
761 if int(f.initialOffset) != offset {
762 return nil, 0, false, errUnsupportedTableOffsetLength
763 }
764
765
766
767 buf, err := f.src.view(nil, offset, 12)
768 if err != nil {
769 return nil, 0, false, err
770 }
771
772
773 switch u32(buf) {
774 default:
775 return nil, 0, false, errInvalidFont
776 case dfontResourceDataOffset:
777 return nil, 0, false, errInvalidSingleFont
778 case 0x00010000:
779
780 case 0x4f54544f:
781 isPostScript = true
782 case 0x74727565:
783
784 case 0x74746366:
785 return nil, 0, false, errInvalidSingleFont
786 }
787 numTables := int(u16(buf[4:]))
788 if numTables > maxNumTables {
789 return nil, 0, false, errUnsupportedNumberOfTables
790 }
791
792
793
794 buf, err = f.src.view(buf, offset+12, 16*numTables)
795 if err != nil {
796 return nil, 0, false, err
797 }
798 for b, first, prevTag := buf, true, uint32(0); len(b) > 0; b = b[16:] {
799 tag := u32(b)
800 if first {
801 first = false
802 } else if tag <= prevTag {
803 return nil, 0, false, errInvalidTableTagOrder
804 }
805 prevTag = tag
806
807 o, n := u32(b[8:12]), u32(b[12:16])
808
809
810 if isDfont {
811 origO := o
812 o += uint32(offset)
813 if o < origO {
814 return nil, 0, false, errUnsupportedTableOffsetLength
815 }
816 }
817 if o > maxTableOffset || n > maxTableLength {
818 return nil, 0, false, errUnsupportedTableOffsetLength
819 }
820
821
822 if o&3 != 0 {
823 return nil, 0, false, errInvalidTableOffset
824 }
825 if finalTableOffset < int32(o+n) {
826 finalTableOffset = int32(o + n)
827 }
828
829
830 switch tag {
831 case 0x43424c43:
832 f.cblc = table{o, n}
833 case 0x43464620:
834 f.cff = table{o, n}
835 case 0x4f532f32:
836 f.os2 = table{o, n}
837 case 0x636d6170:
838 f.cmap = table{o, n}
839 case 0x676c7966:
840 f.glyf = table{o, n}
841 case 0x47504f53:
842 f.gpos = table{o, n}
843 case 0x68656164:
844 f.head = table{o, n}
845 case 0x68686561:
846 f.hhea = table{o, n}
847 case 0x686d7478:
848 f.hmtx = table{o, n}
849 case 0x6b65726e:
850 f.kern = table{o, n}
851 case 0x6c6f6361:
852 f.loca = table{o, n}
853 case 0x6d617870:
854 f.maxp = table{o, n}
855 case 0x6e616d65:
856 f.name = table{o, n}
857 case 0x706f7374:
858 f.post = table{o, n}
859 }
860 }
861
862 if (f.src.b != nil) && (int(finalTableOffset) > len(f.src.b)) {
863 return nil, 0, false, errInvalidSourceData
864 }
865 return buf, finalTableOffset, isPostScript, nil
866 }
867
868 func (f *Font) parseCmap(buf []byte) (buf1 []byte, glyphIndex glyphIndexFunc, err error) {
869
870
871 const headerSize, entrySize = 4, 8
872 if f.cmap.length < headerSize {
873 return nil, nil, errInvalidCmapTable
874 }
875 u, err := f.src.u16(buf, f.cmap, 2)
876 if err != nil {
877 return nil, nil, err
878 }
879 numSubtables := int(u)
880 if f.cmap.length < headerSize+entrySize*uint32(numSubtables) {
881 return nil, nil, errInvalidCmapTable
882 }
883
884 var (
885 bestWidth int
886 bestOffset uint32
887 bestLength uint32
888 bestFormat uint16
889 )
890
891
892
893 for i := 0; i < numSubtables; i++ {
894 buf, err = f.src.view(buf, int(f.cmap.offset)+headerSize+entrySize*i, entrySize)
895 if err != nil {
896 return nil, nil, err
897 }
898 pid := u16(buf)
899 psid := u16(buf[2:])
900 width := platformEncodingWidth(pid, psid)
901 if width <= bestWidth {
902 continue
903 }
904 offset := u32(buf[4:])
905
906 if offset > f.cmap.length-4 {
907 return nil, nil, errInvalidCmapTable
908 }
909 buf, err = f.src.view(buf, int(f.cmap.offset+offset), 4)
910 if err != nil {
911 return nil, nil, err
912 }
913 format := u16(buf)
914 if !supportedCmapFormat(format, pid, psid) {
915 continue
916 }
917 length := uint32(u16(buf[2:]))
918
919 bestWidth = width
920 bestOffset = offset
921 bestLength = length
922 bestFormat = format
923 }
924
925 if bestWidth == 0 {
926 return nil, nil, errUnsupportedCmapEncodings
927 }
928 return f.makeCachedGlyphIndex(buf, bestOffset, bestLength, bestFormat)
929 }
930
931 func (f *Font) parseHead(buf []byte) (buf1 []byte, bounds [4]int16, indexToLocFormat bool, unitsPerEm Units, err error) {
932
933
934 if f.head.length != 54 {
935 return nil, [4]int16{}, false, 0, errInvalidHeadTable
936 }
937
938 u, err := f.src.u16(buf, f.head, 18)
939 if err != nil {
940 return nil, [4]int16{}, false, 0, err
941 }
942 if u == 0 {
943 return nil, [4]int16{}, false, 0, errInvalidHeadTable
944 }
945 unitsPerEm = Units(u)
946
947 for i := range bounds {
948 u, err := f.src.u16(buf, f.head, 36+2*i)
949 if err != nil {
950 return nil, [4]int16{}, false, 0, err
951 }
952 bounds[i] = int16(u)
953 }
954
955 u, err = f.src.u16(buf, f.head, 50)
956 if err != nil {
957 return nil, [4]int16{}, false, 0, err
958 }
959 indexToLocFormat = u != 0
960 return buf, bounds, indexToLocFormat, unitsPerEm, nil
961 }
962
963 func (f *Font) parseHhea(buf []byte, numGlyphs int32) (buf1 []byte, ascent, descent, lineGap, run, rise, numHMetrics int32, err error) {
964
965
966 if f.hhea.length != 36 {
967 return nil, 0, 0, 0, 0, 0, 0, errInvalidHheaTable
968 }
969 u, err := f.src.u16(buf, f.hhea, 34)
970 if err != nil {
971 return nil, 0, 0, 0, 0, 0, 0, err
972 }
973 if int32(u) > numGlyphs || u == 0 {
974 return nil, 0, 0, 0, 0, 0, 0, errInvalidHheaTable
975 }
976 a, err := f.src.u16(buf, f.hhea, 4)
977 if err != nil {
978 return nil, 0, 0, 0, 0, 0, 0, err
979 }
980 d, err := f.src.u16(buf, f.hhea, 6)
981 if err != nil {
982 return nil, 0, 0, 0, 0, 0, 0, err
983 }
984 l, err := f.src.u16(buf, f.hhea, 8)
985 if err != nil {
986 return nil, 0, 0, 0, 0, 0, 0, err
987 }
988 ru, err := f.src.u16(buf, f.hhea, 20)
989 if err != nil {
990 return nil, 0, 0, 0, 0, 0, 0, err
991 }
992 ri, err := f.src.u16(buf, f.hhea, 18)
993 if err != nil {
994 return nil, 0, 0, 0, 0, 0, 0, err
995 }
996 return buf, int32(int16(a)), int32(int16(d)), int32(int16(l)), int32(int16(ru)), int32(int16(ri)), int32(u), nil
997 }
998
999 func (f *Font) parseHmtx(buf []byte, numGlyphs, numHMetrics int32) (buf1 []byte, err error) {
1000
1001
1002
1003
1004
1005 if f.hmtx.length != uint32(4*numHMetrics) && f.hmtx.length != uint32(4*numHMetrics+2*(numGlyphs-numHMetrics)) {
1006 return nil, errInvalidHmtxTable
1007 }
1008 return buf, nil
1009 }
1010
1011 func (f *Font) parseKern(buf []byte) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
1012
1013
1014 if f.kern.length == 0 {
1015 return buf, 0, 0, nil
1016 }
1017 const headerSize = 4
1018 if f.kern.length < headerSize {
1019 return nil, 0, 0, errInvalidKernTable
1020 }
1021 buf, err = f.src.view(buf, int(f.kern.offset), headerSize)
1022 if err != nil {
1023 return nil, 0, 0, err
1024 }
1025 offset := int(f.kern.offset) + headerSize
1026 length := int(f.kern.length) - headerSize
1027
1028 switch version := u16(buf); version {
1029 case 0:
1030 if numTables := int(u16(buf[2:])); numTables == 0 {
1031 return buf, 0, 0, nil
1032 } else if numTables > 1 {
1033
1034
1035 }
1036 return f.parseKernVersion0(buf, offset, length)
1037 case 1:
1038 if buf[2] != 0 || buf[3] != 0 {
1039 return nil, 0, 0, errUnsupportedKernTable
1040 }
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051 return buf, 0, 0, nil
1052 }
1053 return nil, 0, 0, errUnsupportedKernTable
1054 }
1055
1056 func (f *Font) parseKernVersion0(buf []byte, offset, length int) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
1057 const headerSize = 6
1058 if length < headerSize {
1059 return nil, 0, 0, errInvalidKernTable
1060 }
1061 buf, err = f.src.view(buf, offset, headerSize)
1062 if err != nil {
1063 return nil, 0, 0, err
1064 }
1065 if version := u16(buf); version != 0 {
1066 return nil, 0, 0, errUnsupportedKernTable
1067 }
1068 subtableLengthU16 := u16(buf[2:])
1069 if int(subtableLengthU16) < headerSize || length < int(subtableLengthU16) {
1070 return nil, 0, 0, errInvalidKernTable
1071 }
1072 if coverageBits := buf[5]; coverageBits != 0x01 {
1073
1074 return nil, 0, 0, errUnsupportedKernTable
1075 }
1076 offset += headerSize
1077 length -= headerSize
1078 subtableLengthU16 -= headerSize
1079
1080 switch format := buf[4]; format {
1081 case 0:
1082 return f.parseKernFormat0(buf, offset, length, subtableLengthU16)
1083 case 2:
1084
1085
1086
1087 }
1088 return nil, 0, 0, errUnsupportedKernTable
1089 }
1090
1091 func (f *Font) parseKernFormat0(buf []byte, offset, length int, subtableLengthU16 uint16) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
1092 const headerSize, entrySize = 8, 6
1093 if length < headerSize {
1094 return nil, 0, 0, errInvalidKernTable
1095 }
1096 buf, err = f.src.view(buf, offset, headerSize)
1097 if err != nil {
1098 return nil, 0, 0, err
1099 }
1100 kernNumPairs = int32(u16(buf))
1101
1102
1103
1104
1105
1106 n := headerSize + entrySize*int(kernNumPairs)
1107 if (length < n) || (subtableLengthU16 != uint16(n)) {
1108 return nil, 0, 0, errInvalidKernTable
1109 }
1110 return buf, kernNumPairs, int32(offset) + headerSize, nil
1111 }
1112
1113 func (f *Font) parseMaxp(buf []byte, isPostScript bool) (buf1 []byte, numGlyphs int32, err error) {
1114
1115
1116 if isPostScript {
1117 if f.maxp.length != 6 {
1118 return nil, 0, errInvalidMaxpTable
1119 }
1120 } else {
1121 if f.maxp.length != 32 {
1122 return nil, 0, errInvalidMaxpTable
1123 }
1124 }
1125 u, err := f.src.u16(buf, f.maxp, 4)
1126 if err != nil {
1127 return nil, 0, err
1128 }
1129 return buf, int32(u), nil
1130 }
1131
1132 type glyphData struct {
1133
1134
1135
1136
1137 locations []uint32
1138
1139
1140
1141
1142
1143 gsubrs []uint32
1144 singleSubrs []uint32
1145 multiSubrs [][]uint32
1146
1147 fdSelect fdSelect
1148 }
1149
1150 func (f *Font) parseGlyphData(buf []byte, numGlyphs int32, indexToLocFormat, isPostScript bool) (buf1 []byte, ret glyphData, isColorBitmap bool, err error) {
1151 if isPostScript {
1152 p := cffParser{
1153 src: &f.src,
1154 base: int(f.cff.offset),
1155 offset: int(f.cff.offset),
1156 end: int(f.cff.offset + f.cff.length),
1157 }
1158 ret, err = p.parse(numGlyphs)
1159 if err != nil {
1160 return nil, glyphData{}, false, err
1161 }
1162 } else if f.loca.length != 0 {
1163 ret.locations, err = parseLoca(&f.src, f.loca, f.glyf.offset, indexToLocFormat, numGlyphs)
1164 if err != nil {
1165 return nil, glyphData{}, false, err
1166 }
1167 } else if f.cblc.length != 0 {
1168 isColorBitmap = true
1169
1170
1171 ret.locations = make([]uint32, numGlyphs+1)
1172 }
1173
1174 if len(ret.locations) != int(numGlyphs+1) {
1175 return nil, glyphData{}, false, errInvalidLocationData
1176 }
1177
1178 return buf, ret, isColorBitmap, nil
1179 }
1180
1181 func (f *Font) glyphTopOS2(b *Buffer, ppem fixed.Int26_6, r rune) (int32, error) {
1182 ind, err := f.GlyphIndex(b, r)
1183 if err != nil && err != ErrNotFound {
1184 return 0, err
1185 } else if ind == 0 {
1186 return 0, nil
1187 }
1188
1189 var min fixed.Int26_6
1190 seg, err := f.LoadGlyph(b, ind, ppem, nil)
1191 if err != nil {
1192 return 0, err
1193 }
1194 for _, s := range seg {
1195 for _, p := range s.Args {
1196 if p.Y < min {
1197 min = p.Y
1198 }
1199 }
1200 }
1201 return int32(min), nil
1202 }
1203
1204 func (f *Font) initOS2VersionBelow2() (xHeight, capHeight int32, err error) {
1205 ppem := fixed.Int26_6(f.UnitsPerEm())
1206 var b Buffer
1207
1208
1209
1210 xh, err := f.glyphTopOS2(&b, ppem, 'x')
1211 if err != nil {
1212 return 0, 0, err
1213 }
1214
1215
1216
1217 ch, err := f.glyphTopOS2(&b, ppem, 'H')
1218 if err != nil {
1219 return 0, 0, err
1220 }
1221
1222 return int32(xh), int32(ch), nil
1223 }
1224
1225 func (f *Font) parseOS2(buf []byte) (buf1 []byte, hasXHeightCapHeight bool, xHeight, capHeight int32, err error) {
1226
1227
1228 if f.os2.length == 0 {
1229
1230 return buf, false, 0, 0, nil
1231 } else if f.os2.length < 2 {
1232 return nil, false, 0, 0, errInvalidOS2Table
1233 }
1234 vers, err := f.src.u16(buf, f.os2, 0)
1235 if err != nil {
1236 return nil, false, 0, 0, err
1237 }
1238 if vers < 2 {
1239
1240
1241 const headerSize = 68
1242 if f.os2.length < headerSize {
1243 return nil, false, 0, 0, errInvalidOS2Table
1244 }
1245
1246 return buf, false, 0, 0, nil
1247 }
1248 const headerSize = 96
1249 if f.os2.length < headerSize {
1250 return nil, false, 0, 0, errInvalidOS2Table
1251 }
1252 xh, err := f.src.u16(buf, f.os2, 86)
1253 if err != nil {
1254 return nil, false, 0, 0, err
1255 }
1256 ch, err := f.src.u16(buf, f.os2, 88)
1257 if err != nil {
1258 return nil, false, 0, 0, err
1259 }
1260 return buf, true, int32(int16(xh)), int32(int16(ch)), nil
1261 }
1262
1263
1264 type PostTable struct {
1265
1266 Version uint32
1267
1268
1269 ItalicAngle float64
1270
1271
1272 UnderlinePosition int16
1273
1274 UnderlineThickness int16
1275
1276
1277 IsFixedPitch bool
1278 }
1279
1280
1281
1282
1283
1284 func (f *Font) PostTable() *PostTable {
1285 return f.cached.post
1286 }
1287
1288 func (f *Font) parsePost(buf []byte, numGlyphs int32) (buf1 []byte, post *PostTable, err error) {
1289
1290
1291 const headerSize = 32
1292 if f.post.length < headerSize {
1293 return nil, nil, errInvalidPostTable
1294 }
1295 u, err := f.src.u32(buf, f.post, 0)
1296 if err != nil {
1297 return nil, nil, err
1298 }
1299
1300 switch u {
1301 case 0x10000:
1302
1303 case 0x20000:
1304 if f.post.length < headerSize+2+2*uint32(numGlyphs) {
1305 return nil, nil, errInvalidPostTable
1306 }
1307 case 0x30000:
1308
1309 default:
1310 return nil, nil, errUnsupportedPostTable
1311 }
1312
1313 ang, err := f.src.u32(buf, f.post, 4)
1314 if err != nil {
1315 return nil, nil, err
1316 }
1317 up, err := f.src.u16(buf, f.post, 8)
1318 if err != nil {
1319 return nil, nil, err
1320 }
1321 ut, err := f.src.u16(buf, f.post, 10)
1322 if err != nil {
1323 return nil, nil, err
1324 }
1325 fp, err := f.src.u32(buf, f.post, 12)
1326 if err != nil {
1327 return nil, nil, err
1328 }
1329 post = &PostTable{
1330 Version: u,
1331 ItalicAngle: float64(int32(ang)) / 0x10000,
1332 UnderlinePosition: int16(up),
1333 UnderlineThickness: int16(ut),
1334 IsFixedPitch: fp != 0,
1335 }
1336 return buf, post, nil
1337 }
1338
1339
1340
1341
1342
1343 func (f *Font) Bounds(b *Buffer, ppem fixed.Int26_6, h font.Hinting) (fixed.Rectangle26_6, error) {
1344
1345
1346 r := fixed.Rectangle26_6{
1347 Min: fixed.Point26_6{
1348 X: +scale(fixed.Int26_6(f.cached.bounds[0])*ppem, f.cached.unitsPerEm),
1349 Y: -scale(fixed.Int26_6(f.cached.bounds[3])*ppem, f.cached.unitsPerEm),
1350 },
1351 Max: fixed.Point26_6{
1352 X: +scale(fixed.Int26_6(f.cached.bounds[2])*ppem, f.cached.unitsPerEm),
1353 Y: -scale(fixed.Int26_6(f.cached.bounds[1])*ppem, f.cached.unitsPerEm),
1354 },
1355 }
1356 if h == font.HintingFull {
1357
1358 r.Min.X = (r.Min.X + 0) &^ 63
1359 r.Min.Y = (r.Min.Y + 0) &^ 63
1360 r.Max.X = (r.Max.X + 63) &^ 63
1361 r.Max.Y = (r.Max.Y + 63) &^ 63
1362 }
1363 return r, nil
1364 }
1365
1366
1367
1368
1369
1370 type glyphIndexFunc func(f *Font, b *Buffer, r rune) (GlyphIndex, error)
1371
1372
1373
1374
1375
1376
1377
1378
1379 func (f *Font) GlyphIndex(b *Buffer, r rune) (GlyphIndex, error) {
1380 return f.cached.glyphIndex(f, b, r)
1381 }
1382
1383 func (f *Font) viewGlyphData(b *Buffer, x GlyphIndex) (buf []byte, offset, length uint32, err error) {
1384 xx := int(x)
1385 if f.NumGlyphs() <= xx {
1386 return nil, 0, 0, ErrNotFound
1387 }
1388 i := f.cached.glyphData.locations[xx+0]
1389 j := f.cached.glyphData.locations[xx+1]
1390 if j < i {
1391 return nil, 0, 0, errInvalidGlyphDataLength
1392 }
1393 if j-i > maxGlyphDataLength {
1394 return nil, 0, 0, errUnsupportedGlyphDataLength
1395 }
1396 buf, err = b.view(&f.src, int(i), int(j-i))
1397 return buf, i, j - i, err
1398 }
1399
1400
1401 type LoadGlyphOptions struct {
1402
1403 }
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415 func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, ppem fixed.Int26_6, opts *LoadGlyphOptions) (Segments, error) {
1416 if b == nil {
1417 b = &Buffer{}
1418 }
1419
1420 b.segments = b.segments[:0]
1421 if f.cached.isColorBitmap {
1422 return nil, ErrColoredGlyph
1423 }
1424 if f.cached.isPostScript {
1425 buf, offset, length, err := f.viewGlyphData(b, x)
1426 if err != nil {
1427 return nil, err
1428 }
1429 b.psi.type2Charstrings.initialize(f, b, x)
1430 if err := b.psi.run(psContextType2Charstring, buf, offset, length); err != nil {
1431 return nil, err
1432 }
1433 if !b.psi.type2Charstrings.ended {
1434 return nil, errInvalidCFFTable
1435 }
1436 } else if err := loadGlyf(f, b, x, 0, 0); err != nil {
1437 return nil, err
1438 }
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448 for i := range b.segments {
1449 a := &b.segments[i].Args
1450 for j := range a {
1451 a[j].X = +scale(a[j].X*ppem, f.cached.unitsPerEm)
1452 a[j].Y = -scale(a[j].Y*ppem, f.cached.unitsPerEm)
1453 }
1454 }
1455
1456
1457
1458 return b.segments, nil
1459 }
1460
1461 func (f *Font) glyphNameFormat10(x GlyphIndex) (string, error) {
1462 if x >= numBuiltInPostNames {
1463 return "", ErrNotFound
1464 }
1465
1466 i := builtInPostNamesOffsets[x+0]
1467 j := builtInPostNamesOffsets[x+1]
1468 return builtInPostNamesData[i:j], nil
1469 }
1470
1471 func (f *Font) glyphNameFormat20(b *Buffer, x GlyphIndex) (string, error) {
1472 if b == nil {
1473 b = &Buffer{}
1474 }
1475
1476
1477 const glyphNameIndexOffset = 34
1478
1479 buf, err := b.view(&f.src, int(f.post.offset)+glyphNameIndexOffset+2*int(x), 2)
1480 if err != nil {
1481 return "", err
1482 }
1483 u := u16(buf)
1484 if u < numBuiltInPostNames {
1485 i := builtInPostNamesOffsets[u+0]
1486 j := builtInPostNamesOffsets[u+1]
1487 return builtInPostNamesData[i:j], nil
1488 }
1489
1490
1491 if u > 32767 {
1492 return "", errUnsupportedPostTable
1493 }
1494 u -= numBuiltInPostNames
1495
1496
1497
1498
1499
1500
1501 offset := glyphNameIndexOffset + 2*f.NumGlyphs()
1502 buf, err = b.view(&f.src, int(f.post.offset)+offset, int(f.post.length)-offset)
1503 if err != nil {
1504 return "", err
1505 }
1506
1507 for {
1508 if len(buf) == 0 {
1509 return "", errInvalidPostTable
1510 }
1511 n := 1 + int(buf[0])
1512 if len(buf) < n {
1513 return "", errInvalidPostTable
1514 }
1515 if u == 0 {
1516 return string(buf[1:n]), nil
1517 }
1518 buf = buf[n:]
1519 u--
1520 }
1521 }
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536 func (f *Font) GlyphName(b *Buffer, x GlyphIndex) (string, error) {
1537 if int(x) >= f.NumGlyphs() {
1538 return "", ErrNotFound
1539 }
1540 if f.cached.post == nil {
1541 return "", nil
1542 }
1543 switch f.cached.post.Version {
1544 case 0x10000:
1545 return f.glyphNameFormat10(x)
1546 case 0x20000:
1547 return f.glyphNameFormat20(b, x)
1548 default:
1549 return "", nil
1550 }
1551 }
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563 func (f *Font) GlyphBounds(b *Buffer, x GlyphIndex, ppem fixed.Int26_6, h font.Hinting) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, err error) {
1564 if int(x) >= f.NumGlyphs() {
1565 return fixed.Rectangle26_6{}, 0, ErrNotFound
1566 }
1567 if b == nil {
1568 b = &Buffer{}
1569 }
1570
1571
1572
1573
1574
1575 metricIndex := x
1576 if n := GlyphIndex(f.cached.numHMetrics - 1); x > n {
1577 metricIndex = n
1578 }
1579
1580 buf, err := b.view(&f.src, int(f.hmtx.offset)+4*int(metricIndex), 2)
1581 if err != nil {
1582 return fixed.Rectangle26_6{}, 0, err
1583 }
1584 advance = fixed.Int26_6(u16(buf))
1585 advance = scale(advance*ppem, f.cached.unitsPerEm)
1586 if h == font.HintingFull {
1587
1588 advance = (advance + 32) &^ 63
1589 }
1590
1591
1592
1593
1594
1595
1596
1597 segments, err := f.LoadGlyph(b, x, ppem, &LoadGlyphOptions{
1598
1599 })
1600 if err != nil {
1601 return fixed.Rectangle26_6{}, 0, err
1602 }
1603 return segments.Bounds(), advance, nil
1604 }
1605
1606
1607
1608
1609
1610 func (f *Font) GlyphAdvance(b *Buffer, x GlyphIndex, ppem fixed.Int26_6, h font.Hinting) (fixed.Int26_6, error) {
1611 if int(x) >= f.NumGlyphs() {
1612 return 0, ErrNotFound
1613 }
1614 if b == nil {
1615 b = &Buffer{}
1616 }
1617
1618
1619
1620
1621
1622 if n := GlyphIndex(f.cached.numHMetrics - 1); x > n {
1623 x = n
1624 }
1625
1626 buf, err := b.view(&f.src, int(f.hmtx.offset)+4*int(x), 2)
1627 if err != nil {
1628 return 0, err
1629 }
1630 adv := fixed.Int26_6(u16(buf))
1631 adv = scale(adv*ppem, f.cached.unitsPerEm)
1632 if h == font.HintingFull {
1633
1634 adv = (adv + 32) &^ 63
1635 }
1636 return adv, nil
1637 }
1638
1639
1640
1641
1642
1643
1644 func (f *Font) Kern(b *Buffer, x0, x1 GlyphIndex, ppem fixed.Int26_6, h font.Hinting) (fixed.Int26_6, error) {
1645
1646
1647 if f.cached.kernFuncs != nil {
1648 for _, kf := range f.cached.kernFuncs {
1649 adv, err := kf(x0, x1)
1650 if err == ErrNotFound {
1651 continue
1652 }
1653 if err != nil {
1654 return 0, err
1655 }
1656 kern := fixed.Int26_6(adv)
1657 kern = scale(kern*ppem, f.cached.unitsPerEm)
1658 if h == font.HintingFull {
1659
1660 kern = (kern + 32) &^ 63
1661 }
1662 return kern, nil
1663 }
1664 return 0, ErrNotFound
1665 }
1666
1667
1668
1669
1670
1671
1672 if n := f.NumGlyphs(); int(x0) >= n || int(x1) >= n {
1673 return 0, ErrNotFound
1674 }
1675
1676
1677 if f.cached.kernNumPairs == 0 {
1678 return 0, nil
1679 }
1680 if b == nil {
1681 b = &Buffer{}
1682 }
1683
1684 key := uint32(x0)<<16 | uint32(x1)
1685 lo, hi := int32(0), f.cached.kernNumPairs
1686 for lo < hi {
1687 i := (lo + hi) / 2
1688
1689
1690
1691
1692
1693
1694
1695 const entrySize = 6
1696 buf, err := b.view(&f.src, int(f.cached.kernOffset+i*entrySize), entrySize)
1697 if err != nil {
1698 return 0, err
1699 }
1700
1701 k := u32(buf)
1702 if k < key {
1703 lo = i + 1
1704 } else if k > key {
1705 hi = i
1706 } else {
1707 kern := fixed.Int26_6(int16(u16(buf[4:])))
1708 kern = scale(kern*ppem, f.cached.unitsPerEm)
1709 if h == font.HintingFull {
1710
1711 kern = (kern + 32) &^ 63
1712 }
1713 return kern, nil
1714 }
1715 }
1716 return 0, nil
1717 }
1718
1719
1720 func (f *Font) Metrics(b *Buffer, ppem fixed.Int26_6, h font.Hinting) (font.Metrics, error) {
1721 m := font.Metrics{
1722 Height: scale(fixed.Int26_6(f.cached.ascent-f.cached.descent+f.cached.lineGap)*ppem, f.cached.unitsPerEm),
1723 Ascent: +scale(fixed.Int26_6(f.cached.ascent)*ppem, f.cached.unitsPerEm),
1724 Descent: -scale(fixed.Int26_6(f.cached.descent)*ppem, f.cached.unitsPerEm),
1725 XHeight: scale(fixed.Int26_6(f.cached.xHeight)*ppem, f.cached.unitsPerEm),
1726 CapHeight: scale(fixed.Int26_6(f.cached.capHeight)*ppem, f.cached.unitsPerEm),
1727 CaretSlope: image.Point{X: int(f.cached.slope[0]), Y: int(f.cached.slope[1])},
1728 }
1729 if h == font.HintingFull {
1730
1731 m.Height = (m.Height + 63) &^ 63
1732 m.Ascent = (m.Ascent + 63) &^ 63
1733 m.Descent = (m.Descent + 63) &^ 63
1734 m.XHeight = (m.XHeight + 63) &^ 63
1735 m.CapHeight = (m.CapHeight + 63) &^ 63
1736 }
1737 return m, nil
1738 }
1739
1740
1741
1742
1743
1744
1745
1746 func (f *Font) WriteSourceTo(b *Buffer, w io.Writer) (int64, error) {
1747 if f.initialOffset != 0 {
1748
1749
1750
1751
1752
1753
1754
1755 return 0, errUnsupportedCollection
1756 }
1757
1758 if f.src.b != nil {
1759 n, err := w.Write(f.src.b[:f.cached.finalTableOffset])
1760 return int64(n), err
1761 }
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773 if b == nil {
1774 b = &Buffer{}
1775 }
1776 finalTableOffset := int(f.cached.finalTableOffset)
1777 numBytesWritten := int64(0)
1778 for offset := 0; offset < finalTableOffset; {
1779 length := finalTableOffset - offset
1780 if length > 4096 {
1781 length = 4096
1782 }
1783 view, err := b.view(&f.src, offset, length)
1784 if err != nil {
1785 return numBytesWritten, err
1786 }
1787 n, err := w.Write(view)
1788 numBytesWritten += int64(n)
1789 if err != nil {
1790 return numBytesWritten, err
1791 }
1792 offset += length
1793 }
1794 return numBytesWritten, nil
1795 }
1796
1797
1798
1799
1800 func (f *Font) Name(b *Buffer, id NameID) (string, error) {
1801 if b == nil {
1802 b = &Buffer{}
1803 }
1804
1805 const headerSize, entrySize = 6, 12
1806 if f.name.length < headerSize {
1807 return "", errInvalidNameTable
1808 }
1809 buf, err := b.view(&f.src, int(f.name.offset), headerSize)
1810 if err != nil {
1811 return "", err
1812 }
1813 numSubtables := u16(buf[2:])
1814 if f.name.length < headerSize+entrySize*uint32(numSubtables) {
1815 return "", errInvalidNameTable
1816 }
1817 stringOffset := u16(buf[4:])
1818
1819 seen := false
1820 for i, n := 0, int(numSubtables); i < n; i++ {
1821 buf, err := b.view(&f.src, int(f.name.offset)+headerSize+entrySize*i, entrySize)
1822 if err != nil {
1823 return "", err
1824 }
1825 if u16(buf[6:]) != uint16(id) {
1826 continue
1827 }
1828 seen = true
1829
1830 var stringify func([]byte) (string, error)
1831 switch u32(buf) {
1832 default:
1833 continue
1834 case pidMacintosh<<16 | psidMacintoshRoman:
1835 stringify = stringifyMacintosh
1836 case pidWindows<<16 | psidWindowsUCS2:
1837 stringify = stringifyUCS2
1838 }
1839
1840 nameLength := u16(buf[8:])
1841 nameOffset := u16(buf[10:])
1842 buf, err = b.view(&f.src, int(f.name.offset)+int(nameOffset)+int(stringOffset), int(nameLength))
1843 if err != nil {
1844 return "", err
1845 }
1846 return stringify(buf)
1847 }
1848
1849 if seen {
1850 return "", errUnsupportedPlatformEncoding
1851 }
1852 return "", ErrNotFound
1853 }
1854
1855 func stringifyMacintosh(b []byte) (string, error) {
1856 for _, c := range b {
1857 if c >= 0x80 {
1858
1859 s, _ := charmap.Macintosh.NewDecoder().Bytes(b)
1860 return string(s), nil
1861 }
1862 }
1863
1864 return string(b), nil
1865 }
1866
1867 func stringifyUCS2(b []byte) (string, error) {
1868 if len(b)&1 != 0 {
1869 return "", errInvalidUCS2String
1870 }
1871 r := make([]rune, len(b)/2)
1872 for i := range r {
1873 r[i] = rune(u16(b))
1874 b = b[2:]
1875 }
1876 return string(r), nil
1877 }
1878
1879
1880
1881
1882
1883 type Buffer struct {
1884
1885 buf []byte
1886
1887 segments Segments
1888
1889 compoundStack [maxCompoundStackSize]struct {
1890 glyphIndex GlyphIndex
1891 dx, dy int16
1892 hasTransform bool
1893 transformXX int16
1894 transformXY int16
1895 transformYX int16
1896 transformYY int16
1897 }
1898
1899
1900 psi psInterpreter
1901 }
1902
1903 func (b *Buffer) view(src *source, offset, length int) ([]byte, error) {
1904 buf, err := src.view(b.buf, offset, length)
1905 if err != nil {
1906 return nil, err
1907 }
1908
1909 if src.viewBufferWritable() {
1910 b.buf = buf
1911 }
1912 return buf, nil
1913 }
1914
1915
1916 type Segment struct {
1917
1918 Op SegmentOp
1919
1920 Args [3]fixed.Point26_6
1921 }
1922
1923
1924 type SegmentOp uint32
1925
1926 const (
1927 SegmentOpMoveTo SegmentOp = iota
1928 SegmentOpLineTo
1929 SegmentOpQuadTo
1930 SegmentOpCubeTo
1931 )
1932
1933
1934 type Segments []Segment
1935
1936
1937 func (s Segments) Bounds() (bounds fixed.Rectangle26_6) {
1938 if len(s) == 0 {
1939 return fixed.Rectangle26_6{}
1940 }
1941
1942 bounds.Min.X = fixed.Int26_6(+(1 << 31) - 1)
1943 bounds.Min.Y = fixed.Int26_6(+(1 << 31) - 1)
1944 bounds.Max.X = fixed.Int26_6(-(1 << 31) + 0)
1945 bounds.Max.Y = fixed.Int26_6(-(1 << 31) + 0)
1946
1947 for _, seg := range s {
1948 n := 1
1949 switch seg.Op {
1950 case SegmentOpQuadTo:
1951 n = 2
1952 case SegmentOpCubeTo:
1953 n = 3
1954 }
1955 for i := 0; i < n; i++ {
1956 if bounds.Max.X < seg.Args[i].X {
1957 bounds.Max.X = seg.Args[i].X
1958 }
1959 if bounds.Min.X > seg.Args[i].X {
1960 bounds.Min.X = seg.Args[i].X
1961 }
1962 if bounds.Max.Y < seg.Args[i].Y {
1963 bounds.Max.Y = seg.Args[i].Y
1964 }
1965 if bounds.Min.Y > seg.Args[i].Y {
1966 bounds.Min.Y = seg.Args[i].Y
1967 }
1968 }
1969 }
1970
1971 return bounds
1972 }
1973
1974
1975 func translateArgs(args *[3]fixed.Point26_6, dx, dy fixed.Int26_6) {
1976 args[0].X += dx
1977 args[0].Y += dy
1978 args[1].X += dx
1979 args[1].Y += dy
1980 args[2].X += dx
1981 args[2].Y += dy
1982 }
1983
1984
1985
1986 func transformArgs(args *[3]fixed.Point26_6, txx, txy, tyx, tyy int16, dx, dy fixed.Int26_6) {
1987 args[0] = tform(txx, txy, tyx, tyy, dx, dy, args[0])
1988 args[1] = tform(txx, txy, tyx, tyy, dx, dy, args[1])
1989 args[2] = tform(txx, txy, tyx, tyy, dx, dy, args[2])
1990 }
1991
1992 func tform(txx, txy, tyx, tyy int16, dx, dy fixed.Int26_6, p fixed.Point26_6) fixed.Point26_6 {
1993 const half = 1 << 13
1994 return fixed.Point26_6{
1995 X: dx +
1996 fixed.Int26_6((int64(p.X)*int64(txx)+half)>>14) +
1997 fixed.Int26_6((int64(p.Y)*int64(tyx)+half)>>14),
1998 Y: dy +
1999 fixed.Int26_6((int64(p.X)*int64(txy)+half)>>14) +
2000 fixed.Int26_6((int64(p.Y)*int64(tyy)+half)>>14),
2001 }
2002 }
2003
View as plain text