1
2
3
4
5 package sfnt
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 import (
51 "fmt"
52 "math"
53 "strconv"
54
55 "golang.org/x/image/math/fixed"
56 )
57
58 const (
59
60
61
62
63 psArgStackSize = 48
64
65
66 psCallStackSize = 10
67 )
68
69 func bigEndian(b []byte) uint32 {
70 switch len(b) {
71 case 1:
72 return uint32(b[0])
73 case 2:
74 return uint32(b[0])<<8 | uint32(b[1])
75 case 3:
76 return uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2])
77 case 4:
78 return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
79 }
80 panic("unreachable")
81 }
82
83
84 type fdSelect struct {
85 format uint8
86 numRanges uint16
87 offset int32
88 }
89
90 func (t *fdSelect) lookup(f *Font, b *Buffer, x GlyphIndex) (int, error) {
91 switch t.format {
92 case 0:
93 buf, err := b.view(&f.src, int(t.offset)+int(x), 1)
94 if err != nil {
95 return 0, err
96 }
97 return int(buf[0]), nil
98 case 3:
99 lo, hi := 0, int(t.numRanges)
100 for lo < hi {
101 i := (lo + hi) / 2
102 buf, err := b.view(&f.src, int(t.offset)+3*i, 3+2)
103 if err != nil {
104 return 0, err
105 }
106
107 if xlo := GlyphIndex(u16(buf[0:])); x < xlo {
108 hi = i
109 continue
110 }
111 if xhi := GlyphIndex(u16(buf[3:])); xhi <= x {
112 lo = i + 1
113 continue
114 }
115 return int(buf[2]), nil
116 }
117 }
118 return 0, ErrNotFound
119 }
120
121
122 type cffParser struct {
123 src *source
124 base int
125 offset int
126 end int
127 err error
128
129 buf []byte
130 locBuf [2]uint32
131
132 psi psInterpreter
133 }
134
135 func (p *cffParser) parse(numGlyphs int32) (ret glyphData, err error) {
136
137 {
138 if !p.read(4) {
139 return glyphData{}, p.err
140 }
141 if p.buf[0] != 1 || p.buf[1] != 0 || p.buf[2] != 4 {
142 return glyphData{}, errUnsupportedCFFVersion
143 }
144 }
145
146
147 {
148 count, offSize, ok := p.parseIndexHeader()
149 if !ok {
150 return glyphData{}, p.err
151 }
152
153
154 if count != 1 {
155 return glyphData{}, errInvalidCFFTable
156 }
157 if !p.parseIndexLocations(p.locBuf[:2], count, offSize) {
158 return glyphData{}, p.err
159 }
160 p.offset = int(p.locBuf[1])
161 }
162
163
164 p.psi.topDict.initialize()
165 {
166 count, offSize, ok := p.parseIndexHeader()
167 if !ok {
168 return glyphData{}, p.err
169 }
170
171
172 if count != 1 {
173 return glyphData{}, errInvalidCFFTable
174 }
175 if !p.parseIndexLocations(p.locBuf[:2], count, offSize) {
176 return glyphData{}, p.err
177 }
178 if !p.read(int(p.locBuf[1] - p.locBuf[0])) {
179 return glyphData{}, p.err
180 }
181 if p.err = p.psi.run(psContextTopDict, p.buf, 0, 0); p.err != nil {
182 return glyphData{}, p.err
183 }
184 }
185
186
187 {
188 count, offSize, ok := p.parseIndexHeader()
189 if !ok {
190 return glyphData{}, p.err
191 }
192 if count != 0 {
193
194
195 if !p.skip(int(count * offSize)) {
196 return glyphData{}, p.err
197 }
198 if !p.read(int(offSize)) {
199 return glyphData{}, p.err
200 }
201 loc := bigEndian(p.buf) - 1
202
203 if uint32(p.end-p.offset) < loc {
204 return glyphData{}, errInvalidCFFTable
205 }
206
207 if !p.skip(int(loc)) {
208 return glyphData{}, p.err
209 }
210 }
211 }
212
213
214 {
215 count, offSize, ok := p.parseIndexHeader()
216 if !ok {
217 return glyphData{}, p.err
218 }
219 if count != 0 {
220 if count > maxNumSubroutines {
221 return glyphData{}, errUnsupportedNumberOfSubroutines
222 }
223 ret.gsubrs = make([]uint32, count+1)
224 if !p.parseIndexLocations(ret.gsubrs, count, offSize) {
225 return glyphData{}, p.err
226 }
227 }
228 }
229
230
231 {
232 if !p.seekFromBase(p.psi.topDict.charStringsOffset) {
233 return glyphData{}, errInvalidCFFTable
234 }
235 count, offSize, ok := p.parseIndexHeader()
236 if !ok {
237 return glyphData{}, p.err
238 }
239 if count == 0 || int32(count) != numGlyphs {
240 return glyphData{}, errInvalidCFFTable
241 }
242 ret.locations = make([]uint32, count+1)
243 if !p.parseIndexLocations(ret.locations, count, offSize) {
244 return glyphData{}, p.err
245 }
246 }
247
248 if !p.psi.topDict.isCIDFont {
249
250 ret.singleSubrs, err = p.parsePrivateDICT(
251 p.psi.topDict.privateDictOffset,
252 p.psi.topDict.privateDictLength,
253 )
254 if err != nil {
255 return glyphData{}, err
256 }
257
258 } else {
259
260
261 ret.fdSelect, err = p.parseFDSelect(p.psi.topDict.fdSelect, numGlyphs)
262 if err != nil {
263 return glyphData{}, err
264 }
265
266
267 if !p.seekFromBase(p.psi.topDict.fdArray) {
268 return glyphData{}, errInvalidCFFTable
269 }
270
271 count, offSize, ok := p.parseIndexHeader()
272 if !ok {
273 return glyphData{}, p.err
274 }
275 if count > maxNumFontDicts {
276 return glyphData{}, errUnsupportedNumberOfFontDicts
277 }
278
279 fdLocations := make([]uint32, count+1)
280 if !p.parseIndexLocations(fdLocations, count, offSize) {
281 return glyphData{}, p.err
282 }
283
284 privateDicts := make([]struct {
285 offset, length int32
286 }, count)
287
288 for i := range privateDicts {
289 length := fdLocations[i+1] - fdLocations[i]
290 if !p.read(int(length)) {
291 return glyphData{}, errInvalidCFFTable
292 }
293 p.psi.topDict.initialize()
294 if p.err = p.psi.run(psContextTopDict, p.buf, 0, 0); p.err != nil {
295 return glyphData{}, p.err
296 }
297 privateDicts[i].offset = p.psi.topDict.privateDictOffset
298 privateDicts[i].length = p.psi.topDict.privateDictLength
299 }
300
301 ret.multiSubrs = make([][]uint32, count)
302 for i, pd := range privateDicts {
303 ret.multiSubrs[i], err = p.parsePrivateDICT(pd.offset, pd.length)
304 if err != nil {
305 return glyphData{}, err
306 }
307 }
308 }
309
310 return ret, err
311 }
312
313
314
315 func (p *cffParser) parseFDSelect(offset int32, numGlyphs int32) (ret fdSelect, err error) {
316 if !p.seekFromBase(p.psi.topDict.fdSelect) {
317 return fdSelect{}, errInvalidCFFTable
318 }
319 if !p.read(1) {
320 return fdSelect{}, p.err
321 }
322 ret.format = p.buf[0]
323 switch ret.format {
324 case 0:
325 if p.end-p.offset < int(numGlyphs) {
326 return fdSelect{}, errInvalidCFFTable
327 }
328 ret.offset = int32(p.offset)
329 return ret, nil
330 case 3:
331 if !p.read(2) {
332 return fdSelect{}, p.err
333 }
334 ret.numRanges = u16(p.buf)
335 if p.end-p.offset < 3*int(ret.numRanges)+2 {
336 return fdSelect{}, errInvalidCFFTable
337 }
338 ret.offset = int32(p.offset)
339 return ret, nil
340 }
341 return fdSelect{}, errUnsupportedCFFFDSelectTable
342 }
343
344 func (p *cffParser) parsePrivateDICT(offset, length int32) (subrs []uint32, err error) {
345 p.psi.privateDict.initialize()
346 if length != 0 {
347 fullLength := int32(p.end - p.base)
348 if offset <= 0 || fullLength < offset || fullLength-offset < length || length < 0 {
349 return nil, errInvalidCFFTable
350 }
351 p.offset = p.base + int(offset)
352 if !p.read(int(length)) {
353 return nil, p.err
354 }
355 if p.err = p.psi.run(psContextPrivateDict, p.buf, 0, 0); p.err != nil {
356 return nil, p.err
357 }
358 }
359
360
361
362 if p.psi.privateDict.subrsOffset != 0 {
363 if !p.seekFromBase(offset + p.psi.privateDict.subrsOffset) {
364 return nil, errInvalidCFFTable
365 }
366 count, offSize, ok := p.parseIndexHeader()
367 if !ok {
368 return nil, p.err
369 }
370 if count != 0 {
371 if count > maxNumSubroutines {
372 return nil, errUnsupportedNumberOfSubroutines
373 }
374 subrs = make([]uint32, count+1)
375 if !p.parseIndexLocations(subrs, count, offSize) {
376 return nil, p.err
377 }
378 }
379 }
380
381 return subrs, err
382 }
383
384
385
386
387
388
389
390
391
392
393
394 func (p *cffParser) read(n int) (ok bool) {
395 if n < 0 || p.end-p.offset < n {
396 p.err = errInvalidCFFTable
397 return false
398 }
399 p.buf, p.err = p.src.view(p.buf, p.offset, n)
400
401 p.offset += n
402 return p.err == nil
403 }
404
405 func (p *cffParser) skip(n int) (ok bool) {
406 if p.end-p.offset < n {
407 p.err = errInvalidCFFTable
408 return false
409 }
410 p.offset += n
411 return true
412 }
413
414 func (p *cffParser) seekFromBase(offset int32) (ok bool) {
415 if offset < 0 || int32(p.end-p.base) < offset {
416 return false
417 }
418 p.offset = p.base + int(offset)
419 return true
420 }
421
422 func (p *cffParser) parseIndexHeader() (count, offSize int32, ok bool) {
423 if !p.read(2) {
424 return 0, 0, false
425 }
426 count = int32(u16(p.buf[:2]))
427
428
429
430 if count == 0 {
431 return count, 0, true
432 }
433 if !p.read(1) {
434 return 0, 0, false
435 }
436 offSize = int32(p.buf[0])
437 if offSize < 1 || 4 < offSize {
438 p.err = errInvalidCFFTable
439 return 0, 0, false
440 }
441 return count, offSize, true
442 }
443
444 func (p *cffParser) parseIndexLocations(dst []uint32, count, offSize int32) (ok bool) {
445 if count == 0 {
446 return true
447 }
448 if len(dst) != int(count+1) {
449 panic("unreachable")
450 }
451 if !p.read(len(dst) * int(offSize)) {
452 return false
453 }
454
455 buf, prev := p.buf, uint32(0)
456 for i := range dst {
457 loc := bigEndian(buf[:offSize])
458 buf = buf[offSize:]
459
460
461
462
463
464 if loc == 0 {
465 p.err = errInvalidCFFTable
466 return false
467 }
468 loc--
469
470
471
472 if i == 0 {
473 if loc != 0 {
474 p.err = errInvalidCFFTable
475 break
476 }
477 } else if loc <= prev {
478 p.err = errInvalidCFFTable
479 break
480 }
481
482
483 if uint32(p.end-p.offset) < loc {
484 p.err = errInvalidCFFTable
485 break
486 }
487
488 dst[i] = uint32(p.offset) + loc
489 prev = loc
490 }
491 return p.err == nil
492 }
493
494 type psCallStackEntry struct {
495 offset, length uint32
496 }
497
498 type psContext uint32
499
500 const (
501 psContextTopDict psContext = iota
502 psContextPrivateDict
503 psContextType2Charstring
504 )
505
506
507 type psTopDictData struct {
508 charStringsOffset int32
509 fdArray int32
510 fdSelect int32
511 isCIDFont bool
512 privateDictOffset int32
513 privateDictLength int32
514 }
515
516 func (d *psTopDictData) initialize() {
517 *d = psTopDictData{}
518 }
519
520
521 type psPrivateDictData struct {
522 subrsOffset int32
523 }
524
525 func (d *psPrivateDictData) initialize() {
526 *d = psPrivateDictData{}
527 }
528
529
530
531 type psType2CharstringsData struct {
532 f *Font
533 b *Buffer
534 x int32
535 y int32
536 firstX int32
537 firstY int32
538 hintBits int32
539 seenWidth bool
540 ended bool
541 glyphIndex GlyphIndex
542
543
544
545 fdSelectIndexPlusOne int32
546 }
547
548 func (d *psType2CharstringsData) initialize(f *Font, b *Buffer, glyphIndex GlyphIndex) {
549 *d = psType2CharstringsData{
550 f: f,
551 b: b,
552 glyphIndex: glyphIndex,
553 }
554 }
555
556 func (d *psType2CharstringsData) closePath() {
557 if d.x != d.firstX || d.y != d.firstY {
558 d.b.segments = append(d.b.segments, Segment{
559 Op: SegmentOpLineTo,
560 Args: [3]fixed.Point26_6{{
561 X: fixed.Int26_6(d.firstX),
562 Y: fixed.Int26_6(d.firstY),
563 }},
564 })
565 }
566 }
567
568 func (d *psType2CharstringsData) moveTo(dx, dy int32) {
569 d.closePath()
570 d.x += dx
571 d.y += dy
572 d.b.segments = append(d.b.segments, Segment{
573 Op: SegmentOpMoveTo,
574 Args: [3]fixed.Point26_6{{
575 X: fixed.Int26_6(d.x),
576 Y: fixed.Int26_6(d.y),
577 }},
578 })
579 d.firstX = d.x
580 d.firstY = d.y
581 }
582
583 func (d *psType2CharstringsData) lineTo(dx, dy int32) {
584 d.x += dx
585 d.y += dy
586 d.b.segments = append(d.b.segments, Segment{
587 Op: SegmentOpLineTo,
588 Args: [3]fixed.Point26_6{{
589 X: fixed.Int26_6(d.x),
590 Y: fixed.Int26_6(d.y),
591 }},
592 })
593 }
594
595 func (d *psType2CharstringsData) cubeTo(dxa, dya, dxb, dyb, dxc, dyc int32) {
596 d.x += dxa
597 d.y += dya
598 xa := fixed.Int26_6(d.x)
599 ya := fixed.Int26_6(d.y)
600 d.x += dxb
601 d.y += dyb
602 xb := fixed.Int26_6(d.x)
603 yb := fixed.Int26_6(d.y)
604 d.x += dxc
605 d.y += dyc
606 xc := fixed.Int26_6(d.x)
607 yc := fixed.Int26_6(d.y)
608 d.b.segments = append(d.b.segments, Segment{
609 Op: SegmentOpCubeTo,
610 Args: [3]fixed.Point26_6{{X: xa, Y: ya}, {X: xb, Y: yb}, {X: xc, Y: yc}},
611 })
612 }
613
614
615 type psInterpreter struct {
616 ctx psContext
617 instructions []byte
618 instrOffset uint32
619 instrLength uint32
620 argStack struct {
621 a [psArgStackSize]int32
622 top int32
623 }
624 callStack struct {
625 a [psCallStackSize]psCallStackEntry
626 top int32
627 }
628 parseNumberBuf [maxRealNumberStrLen]byte
629
630 topDict psTopDictData
631 privateDict psPrivateDictData
632 type2Charstrings psType2CharstringsData
633 }
634
635 func (p *psInterpreter) hasMoreInstructions() bool {
636 if len(p.instructions) != 0 {
637 return true
638 }
639 for i := int32(0); i < p.callStack.top; i++ {
640 if p.callStack.a[i].length != 0 {
641 return true
642 }
643 }
644 return false
645 }
646
647
648
649
650 func (p *psInterpreter) run(ctx psContext, instructions []byte, offset, length uint32) error {
651 p.ctx = ctx
652 p.instructions = instructions
653 p.instrOffset = offset
654 p.instrLength = length
655 p.argStack.top = 0
656 p.callStack.top = 0
657
658 loop:
659 for len(p.instructions) > 0 {
660
661 if hasResult, err := p.parseNumber(); hasResult {
662 if err != nil {
663 return err
664 }
665 continue
666 }
667
668
669 b := p.instructions[0]
670 p.instructions = p.instructions[1:]
671
672 for escaped, ops := false, psOperators[ctx][0]; ; {
673 if b == escapeByte && !escaped {
674 if len(p.instructions) <= 0 {
675 return errInvalidCFFTable
676 }
677 b = p.instructions[0]
678 p.instructions = p.instructions[1:]
679 escaped = true
680 ops = psOperators[ctx][1]
681 continue
682 }
683
684 if int(b) < len(ops) {
685 if op := ops[b]; op.name != "" {
686 if p.argStack.top < op.numPop {
687 return errInvalidCFFTable
688 }
689 if op.run != nil {
690 if err := op.run(p); err != nil {
691 return err
692 }
693 }
694 if op.numPop < 0 {
695 p.argStack.top = 0
696 } else {
697 p.argStack.top -= op.numPop
698 }
699 continue loop
700 }
701 }
702
703 if escaped {
704 return fmt.Errorf("sfnt: unrecognized CFF 2-byte operator (12 %d)", b)
705 } else {
706 return fmt.Errorf("sfnt: unrecognized CFF 1-byte operator (%d)", b)
707 }
708 }
709 }
710 return nil
711 }
712
713
714 func (p *psInterpreter) parseNumber() (hasResult bool, err error) {
715 number := int32(0)
716 switch b := p.instructions[0]; {
717 case b == 28:
718 if len(p.instructions) < 3 {
719 return true, errInvalidCFFTable
720 }
721 number, hasResult = int32(int16(u16(p.instructions[1:]))), true
722 p.instructions = p.instructions[3:]
723
724 case b == 29 && p.ctx != psContextType2Charstring:
725 if len(p.instructions) < 5 {
726 return true, errInvalidCFFTable
727 }
728 number, hasResult = int32(u32(p.instructions[1:])), true
729 p.instructions = p.instructions[5:]
730
731 case b == 30 && p.ctx != psContextType2Charstring:
732
733
734
735
736
737
738 s := p.parseNumberBuf[:0]
739 p.instructions = p.instructions[1:]
740 loop:
741 for {
742 if len(p.instructions) == 0 {
743 return true, errInvalidCFFTable
744 }
745 b := p.instructions[0]
746 p.instructions = p.instructions[1:]
747
748 for i := 0; i < 2; i++ {
749 nib := b >> 4
750 b = b << 4
751 if nib == 0x0f {
752 f, err := strconv.ParseFloat(string(s), 32)
753 if err != nil {
754 return true, errInvalidCFFTable
755 }
756 number, hasResult = int32(math.Float32bits(float32(f))), true
757 break loop
758 }
759 if nib == 0x0d {
760 return true, errInvalidCFFTable
761 }
762 if len(s)+maxNibbleDefsLength > len(p.parseNumberBuf) {
763 return true, errUnsupportedRealNumberEncoding
764 }
765 s = append(s, nibbleDefs[nib]...)
766 }
767 }
768
769 case b < 32:
770
771
772 case b < 247:
773 p.instructions = p.instructions[1:]
774 number, hasResult = int32(b)-139, true
775
776 case b < 251:
777 if len(p.instructions) < 2 {
778 return true, errInvalidCFFTable
779 }
780 b1 := p.instructions[1]
781 p.instructions = p.instructions[2:]
782 number, hasResult = +int32(b-247)*256+int32(b1)+108, true
783
784 case b < 255:
785 if len(p.instructions) < 2 {
786 return true, errInvalidCFFTable
787 }
788 b1 := p.instructions[1]
789 p.instructions = p.instructions[2:]
790 number, hasResult = -int32(b-251)*256-int32(b1)-108, true
791
792 case b == 255 && p.ctx == psContextType2Charstring:
793 if len(p.instructions) < 5 {
794 return true, errInvalidCFFTable
795 }
796 number, hasResult = int32(u32(p.instructions[1:])), true
797 p.instructions = p.instructions[5:]
798
799
800
801
802
803
804
805
806
807
808
809 number = (number >> 16) + (1 & (number >> 15))
810 }
811
812 if hasResult {
813 if p.argStack.top == psArgStackSize {
814 return true, errInvalidCFFTable
815 }
816 p.argStack.a[p.argStack.top] = number
817 p.argStack.top++
818 }
819 return hasResult, nil
820 }
821
822 const maxNibbleDefsLength = len("E-")
823
824
825 var nibbleDefs = [16]string{
826 0x00: "0",
827 0x01: "1",
828 0x02: "2",
829 0x03: "3",
830 0x04: "4",
831 0x05: "5",
832 0x06: "6",
833 0x07: "7",
834 0x08: "8",
835 0x09: "9",
836 0x0a: ".",
837 0x0b: "E",
838 0x0c: "E-",
839 0x0d: "",
840 0x0e: "-",
841 0x0f: "",
842 }
843
844 type psOperator struct {
845
846
847 numPop int32
848
849
850 name string
851
852
853 run func(*psInterpreter) error
854 }
855
856
857
858 var psOperators = [...][2][]psOperator{
859
860
861 psContextTopDict: {{
862
863 0: {+1, "version", nil},
864 1: {+1, "Notice", nil},
865 2: {+1, "FullName", nil},
866 3: {+1, "FamilyName", nil},
867 4: {+1, "Weight", nil},
868 5: {-1, "FontBBox", nil},
869 13: {+1, "UniqueID", nil},
870 14: {-1, "XUID", nil},
871 15: {+1, "charset", nil},
872 16: {+1, "Encoding", nil},
873 17: {+1, "CharStrings", func(p *psInterpreter) error {
874 p.topDict.charStringsOffset = p.argStack.a[p.argStack.top-1]
875 return nil
876 }},
877 18: {+2, "Private", func(p *psInterpreter) error {
878 p.topDict.privateDictLength = p.argStack.a[p.argStack.top-2]
879 p.topDict.privateDictOffset = p.argStack.a[p.argStack.top-1]
880 return nil
881 }},
882 }, {
883
884 0: {+1, "Copyright", nil},
885 1: {+1, "isFixedPitch", nil},
886 2: {+1, "ItalicAngle", nil},
887 3: {+1, "UnderlinePosition", nil},
888 4: {+1, "UnderlineThickness", nil},
889 5: {+1, "PaintType", nil},
890 6: {+1, "CharstringType", nil},
891 7: {-1, "FontMatrix", nil},
892 8: {+1, "StrokeWidth", nil},
893 20: {+1, "SyntheticBase", nil},
894 21: {+1, "PostScript", nil},
895 22: {+1, "BaseFontName", nil},
896 23: {-2, "BaseFontBlend", nil},
897 30: {+3, "ROS", func(p *psInterpreter) error {
898 p.topDict.isCIDFont = true
899 return nil
900 }},
901 31: {+1, "CIDFontVersion", nil},
902 32: {+1, "CIDFontRevision", nil},
903 33: {+1, "CIDFontType", nil},
904 34: {+1, "CIDCount", nil},
905 35: {+1, "UIDBase", nil},
906 36: {+1, "FDArray", func(p *psInterpreter) error {
907 p.topDict.fdArray = p.argStack.a[p.argStack.top-1]
908 return nil
909 }},
910 37: {+1, "FDSelect", func(p *psInterpreter) error {
911 p.topDict.fdSelect = p.argStack.a[p.argStack.top-1]
912 return nil
913 }},
914 38: {+1, "FontName", nil},
915 }},
916
917
918
919 psContextPrivateDict: {{
920
921 6: {-2, "BlueValues", nil},
922 7: {-2, "OtherBlues", nil},
923 8: {-2, "FamilyBlues", nil},
924 9: {-2, "FamilyOtherBlues", nil},
925 10: {+1, "StdHW", nil},
926 11: {+1, "StdVW", nil},
927 19: {+1, "Subrs", func(p *psInterpreter) error {
928 p.privateDict.subrsOffset = p.argStack.a[p.argStack.top-1]
929 return nil
930 }},
931 20: {+1, "defaultWidthX", nil},
932 21: {+1, "nominalWidthX", nil},
933 }, {
934
935 9: {+1, "BlueScale", nil},
936 10: {+1, "BlueShift", nil},
937 11: {+1, "BlueFuzz", nil},
938 12: {-2, "StemSnapH", nil},
939 13: {-2, "StemSnapV", nil},
940 14: {+1, "ForceBold", nil},
941 17: {+1, "LanguageGroup", nil},
942 18: {+1, "ExpansionFactor", nil},
943 19: {+1, "initialRandomSeed", nil},
944 }},
945
946
947
948 psContextType2Charstring: {{
949
950 0: {},
951 1: {-1, "hstem", t2CStem},
952 2: {},
953 3: {-1, "vstem", t2CStem},
954 4: {-1, "vmoveto", t2CVmoveto},
955 5: {-1, "rlineto", t2CRlineto},
956 6: {-1, "hlineto", t2CHlineto},
957 7: {-1, "vlineto", t2CVlineto},
958 8: {-1, "rrcurveto", t2CRrcurveto},
959 9: {},
960 10: {+1, "callsubr", t2CCallsubr},
961 11: {+0, "return", t2CReturn},
962 12: {},
963 13: {},
964 14: {-1, "endchar", t2CEndchar},
965 15: {},
966 16: {},
967 17: {},
968 18: {-1, "hstemhm", t2CStem},
969 19: {-1, "hintmask", t2CMask},
970 20: {-1, "cntrmask", t2CMask},
971 21: {-1, "rmoveto", t2CRmoveto},
972 22: {-1, "hmoveto", t2CHmoveto},
973 23: {-1, "vstemhm", t2CStem},
974 24: {-1, "rcurveline", t2CRcurveline},
975 25: {-1, "rlinecurve", t2CRlinecurve},
976 26: {-1, "vvcurveto", t2CVvcurveto},
977 27: {-1, "hhcurveto", t2CHhcurveto},
978 28: {},
979 29: {+1, "callgsubr", t2CCallgsubr},
980 30: {-1, "vhcurveto", t2CVhcurveto},
981 31: {-1, "hvcurveto", t2CHvcurveto},
982 }, {
983
984 34: {+7, "hflex", t2CHflex},
985 36: {+9, "hflex1", t2CHflex1},
986
987 }},
988 }
989
990
991
992 const escapeByte = 12
993
994
995
996
997
998
999
1000
1001
1002 func t2CReadWidth(p *psInterpreter, nArgs int32) {
1003 if p.type2Charstrings.seenWidth {
1004 return
1005 }
1006 p.type2Charstrings.seenWidth = true
1007 if nArgs >= 0 {
1008 if p.argStack.top != nArgs+1 {
1009 return
1010 }
1011 } else if p.argStack.top&1 == 0 {
1012 return
1013 }
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025 copy(p.argStack.a[:p.argStack.top-1], p.argStack.a[1:p.argStack.top])
1026 p.argStack.top--
1027 }
1028
1029 func t2CStem(p *psInterpreter) error {
1030 t2CReadWidth(p, -1)
1031 if p.argStack.top%2 != 0 {
1032 return errInvalidCFFTable
1033 }
1034
1035
1036
1037 p.type2Charstrings.hintBits += p.argStack.top / 2
1038 if p.type2Charstrings.hintBits > maxHintBits {
1039 return errUnsupportedNumberOfHints
1040 }
1041 return nil
1042 }
1043
1044 func t2CMask(p *psInterpreter) error {
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 if p.argStack.top != 0 {
1058 if err := t2CStem(p); err != nil {
1059 return err
1060 }
1061 } else if !p.type2Charstrings.seenWidth {
1062 p.type2Charstrings.seenWidth = true
1063 }
1064
1065 hintBytes := (p.type2Charstrings.hintBits + 7) / 8
1066 if len(p.instructions) < int(hintBytes) {
1067 return errInvalidCFFTable
1068 }
1069 p.instructions = p.instructions[hintBytes:]
1070 return nil
1071 }
1072
1073 func t2CHmoveto(p *psInterpreter) error {
1074 t2CReadWidth(p, 1)
1075 if p.argStack.top != 1 {
1076 return errInvalidCFFTable
1077 }
1078 p.type2Charstrings.moveTo(p.argStack.a[0], 0)
1079 return nil
1080 }
1081
1082 func t2CVmoveto(p *psInterpreter) error {
1083 t2CReadWidth(p, 1)
1084 if p.argStack.top != 1 {
1085 return errInvalidCFFTable
1086 }
1087 p.type2Charstrings.moveTo(0, p.argStack.a[0])
1088 return nil
1089 }
1090
1091 func t2CRmoveto(p *psInterpreter) error {
1092 t2CReadWidth(p, 2)
1093 if p.argStack.top != 2 {
1094 return errInvalidCFFTable
1095 }
1096 p.type2Charstrings.moveTo(p.argStack.a[0], p.argStack.a[1])
1097 return nil
1098 }
1099
1100 func t2CHlineto(p *psInterpreter) error { return t2CLineto(p, false) }
1101 func t2CVlineto(p *psInterpreter) error { return t2CLineto(p, true) }
1102
1103 func t2CLineto(p *psInterpreter, vertical bool) error {
1104 if !p.type2Charstrings.seenWidth || p.argStack.top < 1 {
1105 return errInvalidCFFTable
1106 }
1107 for i := int32(0); i < p.argStack.top; i, vertical = i+1, !vertical {
1108 dx, dy := p.argStack.a[i], int32(0)
1109 if vertical {
1110 dx, dy = dy, dx
1111 }
1112 p.type2Charstrings.lineTo(dx, dy)
1113 }
1114 return nil
1115 }
1116
1117 func t2CRlineto(p *psInterpreter) error {
1118 if !p.type2Charstrings.seenWidth || p.argStack.top < 2 || p.argStack.top%2 != 0 {
1119 return errInvalidCFFTable
1120 }
1121 for i := int32(0); i < p.argStack.top; i += 2 {
1122 p.type2Charstrings.lineTo(p.argStack.a[i], p.argStack.a[i+1])
1123 }
1124 return nil
1125 }
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 func t2CRcurveline(p *psInterpreter) error {
1136 if !p.type2Charstrings.seenWidth || p.argStack.top < 8 || p.argStack.top%6 != 2 {
1137 return errInvalidCFFTable
1138 }
1139 i := int32(0)
1140 for iMax := p.argStack.top - 2; i < iMax; i += 6 {
1141 p.type2Charstrings.cubeTo(
1142 p.argStack.a[i+0],
1143 p.argStack.a[i+1],
1144 p.argStack.a[i+2],
1145 p.argStack.a[i+3],
1146 p.argStack.a[i+4],
1147 p.argStack.a[i+5],
1148 )
1149 }
1150 p.type2Charstrings.lineTo(p.argStack.a[i], p.argStack.a[i+1])
1151 return nil
1152 }
1153
1154 func t2CRlinecurve(p *psInterpreter) error {
1155 if !p.type2Charstrings.seenWidth || p.argStack.top < 8 || p.argStack.top%2 != 0 {
1156 return errInvalidCFFTable
1157 }
1158 i := int32(0)
1159 for iMax := p.argStack.top - 6; i < iMax; i += 2 {
1160 p.type2Charstrings.lineTo(p.argStack.a[i], p.argStack.a[i+1])
1161 }
1162 p.type2Charstrings.cubeTo(
1163 p.argStack.a[i+0],
1164 p.argStack.a[i+1],
1165 p.argStack.a[i+2],
1166 p.argStack.a[i+3],
1167 p.argStack.a[i+4],
1168 p.argStack.a[i+5],
1169 )
1170 return nil
1171 }
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189 func t2CHhcurveto(p *psInterpreter) error { return t2CCurveto(p, false, false) }
1190 func t2CVvcurveto(p *psInterpreter) error { return t2CCurveto(p, false, true) }
1191 func t2CHvcurveto(p *psInterpreter) error { return t2CCurveto(p, true, false) }
1192 func t2CVhcurveto(p *psInterpreter) error { return t2CCurveto(p, true, true) }
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204 func t2CCurveto(p *psInterpreter, swap, vertical bool) error {
1205 if !p.type2Charstrings.seenWidth || p.argStack.top < 4 {
1206 return errInvalidCFFTable
1207 }
1208
1209 i := int32(0)
1210 switch p.argStack.top & 3 {
1211 case 0:
1212
1213 case 1:
1214 if swap {
1215 break
1216 }
1217 i = 1
1218 if vertical {
1219 p.type2Charstrings.x += p.argStack.a[0]
1220 } else {
1221 p.type2Charstrings.y += p.argStack.a[0]
1222 }
1223 default:
1224 return errInvalidCFFTable
1225 }
1226
1227 for i != p.argStack.top {
1228 i = t2CCurveto4(p, swap, vertical, i)
1229 if i < 0 {
1230 return errInvalidCFFTable
1231 }
1232 if swap {
1233 vertical = !vertical
1234 }
1235 }
1236 return nil
1237 }
1238
1239 func t2CCurveto4(p *psInterpreter, swap bool, vertical bool, i int32) (j int32) {
1240 if i+4 > p.argStack.top {
1241 return -1
1242 }
1243 dxa := p.argStack.a[i+0]
1244 dya := int32(0)
1245 dxb := p.argStack.a[i+1]
1246 dyb := p.argStack.a[i+2]
1247 dxc := p.argStack.a[i+3]
1248 dyc := int32(0)
1249 i += 4
1250
1251 if vertical {
1252 dxa, dya = dya, dxa
1253 }
1254
1255 if swap {
1256 if i+1 == p.argStack.top {
1257 dyc = p.argStack.a[i]
1258 i++
1259 }
1260 }
1261
1262 if swap != vertical {
1263 dxc, dyc = dyc, dxc
1264 }
1265
1266 p.type2Charstrings.cubeTo(dxa, dya, dxb, dyb, dxc, dyc)
1267 return i
1268 }
1269
1270 func t2CRrcurveto(p *psInterpreter) error {
1271 if !p.type2Charstrings.seenWidth || p.argStack.top < 6 || p.argStack.top%6 != 0 {
1272 return errInvalidCFFTable
1273 }
1274 for i := int32(0); i != p.argStack.top; i += 6 {
1275 p.type2Charstrings.cubeTo(
1276 p.argStack.a[i+0],
1277 p.argStack.a[i+1],
1278 p.argStack.a[i+2],
1279 p.argStack.a[i+3],
1280 p.argStack.a[i+4],
1281 p.argStack.a[i+5],
1282 )
1283 }
1284 return nil
1285 }
1286
1287
1288
1289
1290
1291
1292
1293 func t2CHflex(p *psInterpreter) error {
1294 p.type2Charstrings.cubeTo(
1295 p.argStack.a[0], 0,
1296 p.argStack.a[1], +p.argStack.a[2],
1297 p.argStack.a[3], 0,
1298 )
1299 p.type2Charstrings.cubeTo(
1300 p.argStack.a[4], 0,
1301 p.argStack.a[5], -p.argStack.a[2],
1302 p.argStack.a[6], 0,
1303 )
1304 return nil
1305 }
1306
1307 func t2CHflex1(p *psInterpreter) error {
1308 dy1 := p.argStack.a[1]
1309 dy2 := p.argStack.a[3]
1310 dy5 := p.argStack.a[7]
1311 dy6 := -dy1 - dy2 - dy5
1312 p.type2Charstrings.cubeTo(
1313 p.argStack.a[0], dy1,
1314 p.argStack.a[2], dy2,
1315 p.argStack.a[4], 0,
1316 )
1317 p.type2Charstrings.cubeTo(
1318 p.argStack.a[5], 0,
1319 p.argStack.a[6], dy5,
1320 p.argStack.a[8], dy6,
1321 )
1322 return nil
1323 }
1324
1325
1326
1327 func subrBias(numSubroutines int) int32 {
1328 if numSubroutines < 1240 {
1329 return 107
1330 }
1331 if numSubroutines < 33900 {
1332 return 1131
1333 }
1334 return 32768
1335 }
1336
1337 func t2CCallgsubr(p *psInterpreter) error {
1338 return t2CCall(p, p.type2Charstrings.f.cached.glyphData.gsubrs)
1339 }
1340
1341 func t2CCallsubr(p *psInterpreter) error {
1342 t := &p.type2Charstrings
1343 d := &t.f.cached.glyphData
1344 subrs := d.singleSubrs
1345 if d.multiSubrs != nil {
1346 if t.fdSelectIndexPlusOne == 0 {
1347 index, err := d.fdSelect.lookup(t.f, t.b, t.glyphIndex)
1348 if err != nil {
1349 return err
1350 }
1351 if index < 0 || len(d.multiSubrs) <= index {
1352 return errInvalidCFFTable
1353 }
1354 t.fdSelectIndexPlusOne = int32(index + 1)
1355 }
1356 subrs = d.multiSubrs[t.fdSelectIndexPlusOne-1]
1357 }
1358 return t2CCall(p, subrs)
1359 }
1360
1361 func t2CCall(p *psInterpreter, subrs []uint32) error {
1362 if p.callStack.top == psCallStackSize || len(subrs) == 0 {
1363 return errInvalidCFFTable
1364 }
1365 length := uint32(len(p.instructions))
1366 p.callStack.a[p.callStack.top] = psCallStackEntry{
1367 offset: p.instrOffset + p.instrLength - length,
1368 length: length,
1369 }
1370 p.callStack.top++
1371
1372 subrIndex := p.argStack.a[p.argStack.top-1] + subrBias(len(subrs)-1)
1373 if subrIndex < 0 || int32(len(subrs)-1) <= subrIndex {
1374 return errInvalidCFFTable
1375 }
1376 i := subrs[subrIndex+0]
1377 j := subrs[subrIndex+1]
1378 if j < i {
1379 return errInvalidCFFTable
1380 }
1381 if j-i > maxGlyphDataLength {
1382 return errUnsupportedGlyphDataLength
1383 }
1384 buf, err := p.type2Charstrings.b.view(&p.type2Charstrings.f.src, int(i), int(j-i))
1385 if err != nil {
1386 return err
1387 }
1388
1389 p.instructions = buf
1390 p.instrOffset = i
1391 p.instrLength = j - i
1392 return nil
1393 }
1394
1395 func t2CReturn(p *psInterpreter) error {
1396 if p.callStack.top <= 0 {
1397 return errInvalidCFFTable
1398 }
1399 p.callStack.top--
1400 o := p.callStack.a[p.callStack.top].offset
1401 n := p.callStack.a[p.callStack.top].length
1402 buf, err := p.type2Charstrings.b.view(&p.type2Charstrings.f.src, int(o), int(n))
1403 if err != nil {
1404 return err
1405 }
1406
1407 p.instructions = buf
1408 p.instrOffset = o
1409 p.instrLength = n
1410 return nil
1411 }
1412
1413 func t2CEndchar(p *psInterpreter) error {
1414 t2CReadWidth(p, 0)
1415 if p.argStack.top != 0 || p.hasMoreInstructions() {
1416 if p.argStack.top == 4 {
1417
1418
1419 return errUnsupportedType2Charstring
1420 }
1421 return errInvalidCFFTable
1422 }
1423 p.type2Charstrings.closePath()
1424 p.type2Charstrings.ended = true
1425 return nil
1426 }
1427
View as plain text