1
2
3
4
5 package sfnt
6
7 import (
8 "golang.org/x/image/math/fixed"
9 )
10
11
12
13
14 const (
15 flagOnCurve = 1 << 0
16 flagXShortVector = 1 << 1
17 flagYShortVector = 1 << 2
18 flagRepeat = 1 << 3
19
20
21
22 flagPositiveXShortVector = 1 << 4
23 flagThisXIsSame = 1 << 4
24 flagPositiveYShortVector = 1 << 5
25 flagThisYIsSame = 1 << 5
26 )
27
28
29
30
31 const (
32 flagArg1And2AreWords = 1 << 0
33 flagArgsAreXYValues = 1 << 1
34 flagRoundXYToGrid = 1 << 2
35 flagWeHaveAScale = 1 << 3
36 flagReserved4 = 1 << 4
37 flagMoreComponents = 1 << 5
38 flagWeHaveAnXAndYScale = 1 << 6
39 flagWeHaveATwoByTwo = 1 << 7
40 flagWeHaveInstructions = 1 << 8
41 flagUseMyMetrics = 1 << 9
42 flagOverlapCompound = 1 << 10
43 flagScaledComponentOffset = 1 << 11
44 flagUnscaledComponentOffset = 1 << 12
45 )
46
47 func midPoint(p, q fixed.Point26_6) fixed.Point26_6 {
48 return fixed.Point26_6{
49 X: (p.X + q.X) / 2,
50 Y: (p.Y + q.Y) / 2,
51 }
52 }
53
54 func parseLoca(src *source, loca table, glyfOffset uint32, indexToLocFormat bool, numGlyphs int32) (locations []uint32, err error) {
55 if indexToLocFormat {
56 if loca.length != 4*uint32(numGlyphs+1) {
57 return nil, errInvalidLocaTable
58 }
59 } else {
60 if loca.length != 2*uint32(numGlyphs+1) {
61 return nil, errInvalidLocaTable
62 }
63 }
64
65 locations = make([]uint32, numGlyphs+1)
66 buf, err := src.view(nil, int(loca.offset), int(loca.length))
67 if err != nil {
68 return nil, err
69 }
70
71 if indexToLocFormat {
72 for i := range locations {
73 locations[i] = 1*uint32(u32(buf[4*i:])) + glyfOffset
74 }
75 } else {
76 for i := range locations {
77 locations[i] = 2*uint32(u16(buf[2*i:])) + glyfOffset
78 }
79 }
80 return locations, err
81 }
82
83
84
85 const glyfHeaderLen = 10
86
87 func loadGlyf(f *Font, b *Buffer, x GlyphIndex, stackBottom, recursionDepth uint32) error {
88 data, _, _, err := f.viewGlyphData(b, x)
89 if err != nil {
90 return err
91 }
92 if len(data) == 0 {
93 return nil
94 }
95 if len(data) < glyfHeaderLen {
96 return errInvalidGlyphData
97 }
98 index := glyfHeaderLen
99
100 numContours, numPoints := int16(u16(data)), 0
101 switch {
102 case numContours == -1:
103
104 case numContours == 0:
105 return nil
106 case numContours > 0:
107
108 index += 2 * int(numContours)
109 if index > len(data) {
110 return errInvalidGlyphData
111 }
112
113
114 numPoints = 1 + int(u16(data[index-2:]))
115 default:
116 return errInvalidGlyphData
117 }
118
119 if numContours < 0 {
120 return loadCompoundGlyf(f, b, data[glyfHeaderLen:], stackBottom, recursionDepth)
121 }
122
123
124 index += 2
125 if index > len(data) {
126 return errInvalidGlyphData
127 }
128 hintsLength := int(u16(data[index-2:]))
129 index += hintsLength
130 if index > len(data) {
131 return errInvalidGlyphData
132 }
133
134
135
136
137
138
139
140
141
142 flagIndex := int32(index)
143 xIndex, yIndex, ok := findXYIndexes(data, index, numPoints)
144 if !ok {
145 return errInvalidGlyphData
146 }
147
148
149 g := glyfIter{
150 data: data,
151 flagIndex: flagIndex,
152 xIndex: xIndex,
153 yIndex: yIndex,
154 endIndex: glyfHeaderLen,
155
156
157 prevEnd: -1,
158 finalEnd: int32(numPoints - 1),
159 numContours: int32(numContours),
160 }
161 for g.nextContour() {
162 for g.nextSegment() {
163 b.segments = append(b.segments, g.seg)
164 }
165 }
166 return g.err
167 }
168
169 func findXYIndexes(data []byte, index, numPoints int) (xIndex, yIndex int32, ok bool) {
170 xDataLen := 0
171 yDataLen := 0
172 for i := 0; ; {
173 if i > numPoints {
174 return 0, 0, false
175 }
176 if i == numPoints {
177 break
178 }
179
180 repeatCount := 1
181 if index >= len(data) {
182 return 0, 0, false
183 }
184 flag := data[index]
185 index++
186 if flag&flagRepeat != 0 {
187 if index >= len(data) {
188 return 0, 0, false
189 }
190 repeatCount += int(data[index])
191 index++
192 }
193
194 xSize := 0
195 if flag&flagXShortVector != 0 {
196 xSize = 1
197 } else if flag&flagThisXIsSame == 0 {
198 xSize = 2
199 }
200 xDataLen += xSize * repeatCount
201
202 ySize := 0
203 if flag&flagYShortVector != 0 {
204 ySize = 1
205 } else if flag&flagThisYIsSame == 0 {
206 ySize = 2
207 }
208 yDataLen += ySize * repeatCount
209
210 i += repeatCount
211 }
212 if index+xDataLen+yDataLen > len(data) {
213 return 0, 0, false
214 }
215 return int32(index), int32(index + xDataLen), true
216 }
217
218 func loadCompoundGlyf(f *Font, b *Buffer, data []byte, stackBottom, recursionDepth uint32) error {
219 if recursionDepth++; recursionDepth == maxCompoundRecursionDepth {
220 return errUnsupportedCompoundGlyph
221 }
222
223
224
225
226
227 stackTop := stackBottom
228 for {
229 if stackTop >= maxCompoundStackSize {
230 return errUnsupportedCompoundGlyph
231 }
232 elem := &b.compoundStack[stackTop]
233 stackTop++
234
235 if len(data) < 4 {
236 return errInvalidGlyphData
237 }
238 flags := u16(data)
239 elem.glyphIndex = GlyphIndex(u16(data[2:]))
240 if flags&flagArg1And2AreWords == 0 {
241 if len(data) < 6 {
242 return errInvalidGlyphData
243 }
244 elem.dx = int16(int8(data[4]))
245 elem.dy = int16(int8(data[5]))
246 data = data[6:]
247 } else {
248 if len(data) < 8 {
249 return errInvalidGlyphData
250 }
251 elem.dx = int16(u16(data[4:]))
252 elem.dy = int16(u16(data[6:]))
253 data = data[8:]
254 }
255
256 if flags&flagArgsAreXYValues == 0 {
257 return errUnsupportedCompoundGlyph
258 }
259 elem.hasTransform = flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0
260 if elem.hasTransform {
261 switch {
262 case flags&flagWeHaveAScale != 0:
263 if len(data) < 2 {
264 return errInvalidGlyphData
265 }
266 elem.transformXX = int16(u16(data))
267 elem.transformXY = 0
268 elem.transformYX = 0
269 elem.transformYY = elem.transformXX
270 data = data[2:]
271 case flags&flagWeHaveAnXAndYScale != 0:
272 if len(data) < 4 {
273 return errInvalidGlyphData
274 }
275 elem.transformXX = int16(u16(data[0:]))
276 elem.transformXY = 0
277 elem.transformYX = 0
278 elem.transformYY = int16(u16(data[2:]))
279 data = data[4:]
280 case flags&flagWeHaveATwoByTwo != 0:
281 if len(data) < 8 {
282 return errInvalidGlyphData
283 }
284 elem.transformXX = int16(u16(data[0:]))
285 elem.transformXY = int16(u16(data[2:]))
286 elem.transformYX = int16(u16(data[4:]))
287 elem.transformYY = int16(u16(data[6:]))
288 data = data[8:]
289 }
290 }
291
292 if flags&flagMoreComponents == 0 {
293 break
294 }
295 }
296
297
298
299
300
301 for i := stackBottom; i < stackTop; i++ {
302 elem := &b.compoundStack[i]
303 base := len(b.segments)
304 if err := loadGlyf(f, b, elem.glyphIndex, stackTop, recursionDepth); err != nil {
305 return err
306 }
307 dx, dy := fixed.Int26_6(elem.dx), fixed.Int26_6(elem.dy)
308 segments := b.segments[base:]
309 if elem.hasTransform {
310 txx := elem.transformXX
311 txy := elem.transformXY
312 tyx := elem.transformYX
313 tyy := elem.transformYY
314 for j := range segments {
315 transformArgs(&segments[j].Args, txx, txy, tyx, tyy, dx, dy)
316 }
317 } else {
318 for j := range segments {
319 translateArgs(&segments[j].Args, dx, dy)
320 }
321 }
322 }
323
324 return nil
325 }
326
327 type glyfIter struct {
328 data []byte
329 err error
330
331
332
333 flagIndex int32
334 xIndex int32
335 yIndex int32
336
337
338
339
340 endIndex int32
341 prevEnd int32
342 finalEnd int32
343
344
345
346 c, numContours int32
347 p, nPoints int32
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373 x, y int16
374 on bool
375 flag uint8
376 repeats uint8
377
378
379 closing bool
380 closed bool
381 firstOnCurveValid bool
382 firstOffCurveValid bool
383 lastOffCurveValid bool
384 firstOnCurve fixed.Point26_6
385 firstOffCurve fixed.Point26_6
386 lastOffCurve fixed.Point26_6
387 seg Segment
388 }
389
390 func (g *glyfIter) nextContour() (ok bool) {
391 if g.c == g.numContours {
392 if g.prevEnd != g.finalEnd {
393 g.err = errInvalidGlyphData
394 }
395 return false
396 }
397 g.c++
398
399 end := int32(u16(g.data[g.endIndex:]))
400 g.endIndex += 2
401 if (end <= g.prevEnd) || (g.finalEnd < end) {
402 g.err = errInvalidGlyphData
403 return false
404 }
405 g.nPoints = end - g.prevEnd
406 g.p = 0
407 g.prevEnd = end
408
409 g.closing = false
410 g.closed = false
411 g.firstOnCurveValid = false
412 g.firstOffCurveValid = false
413 g.lastOffCurveValid = false
414
415 return true
416 }
417
418 func (g *glyfIter) close() {
419 switch {
420 case !g.firstOffCurveValid && !g.lastOffCurveValid:
421 g.closed = true
422 g.seg = Segment{
423 Op: SegmentOpLineTo,
424 Args: [3]fixed.Point26_6{g.firstOnCurve},
425 }
426 case !g.firstOffCurveValid && g.lastOffCurveValid:
427 g.closed = true
428 g.seg = Segment{
429 Op: SegmentOpQuadTo,
430 Args: [3]fixed.Point26_6{g.lastOffCurve, g.firstOnCurve},
431 }
432 case g.firstOffCurveValid && !g.lastOffCurveValid:
433 g.closed = true
434 g.seg = Segment{
435 Op: SegmentOpQuadTo,
436 Args: [3]fixed.Point26_6{g.firstOffCurve, g.firstOnCurve},
437 }
438 case g.firstOffCurveValid && g.lastOffCurveValid:
439 g.lastOffCurveValid = false
440 g.seg = Segment{
441 Op: SegmentOpQuadTo,
442 Args: [3]fixed.Point26_6{
443 g.lastOffCurve,
444 midPoint(g.lastOffCurve, g.firstOffCurve),
445 },
446 }
447 }
448 }
449
450 func (g *glyfIter) nextSegment() (ok bool) {
451 for !g.closed {
452 if g.closing || !g.nextPoint() {
453 g.closing = true
454 g.close()
455 return true
456 }
457
458
459
460
461
462
463
464
465
466
467 p := fixed.Point26_6{
468 X: fixed.Int26_6(g.x),
469 Y: fixed.Int26_6(g.y),
470 }
471
472 if !g.firstOnCurveValid {
473 if g.on {
474 g.firstOnCurve = p
475 g.firstOnCurveValid = true
476 g.seg = Segment{
477 Op: SegmentOpMoveTo,
478 Args: [3]fixed.Point26_6{p},
479 }
480 return true
481 } else if !g.firstOffCurveValid {
482 g.firstOffCurve = p
483 g.firstOffCurveValid = true
484 continue
485 } else {
486 g.firstOnCurve = midPoint(g.firstOffCurve, p)
487 g.firstOnCurveValid = true
488 g.lastOffCurve = p
489 g.lastOffCurveValid = true
490 g.seg = Segment{
491 Op: SegmentOpMoveTo,
492 Args: [3]fixed.Point26_6{g.firstOnCurve},
493 }
494 return true
495 }
496
497 } else if !g.lastOffCurveValid {
498 if !g.on {
499 g.lastOffCurve = p
500 g.lastOffCurveValid = true
501 continue
502 } else {
503 g.seg = Segment{
504 Op: SegmentOpLineTo,
505 Args: [3]fixed.Point26_6{p},
506 }
507 return true
508 }
509
510 } else {
511 if !g.on {
512 g.seg = Segment{
513 Op: SegmentOpQuadTo,
514 Args: [3]fixed.Point26_6{
515 g.lastOffCurve,
516 midPoint(g.lastOffCurve, p),
517 },
518 }
519 g.lastOffCurve = p
520 g.lastOffCurveValid = true
521 return true
522 } else {
523 g.seg = Segment{
524 Op: SegmentOpQuadTo,
525 Args: [3]fixed.Point26_6{g.lastOffCurve, p},
526 }
527 g.lastOffCurveValid = false
528 return true
529 }
530 }
531 }
532 return false
533 }
534
535 func (g *glyfIter) nextPoint() (ok bool) {
536 if g.p == g.nPoints {
537 return false
538 }
539 g.p++
540
541 if g.repeats > 0 {
542 g.repeats--
543 } else {
544 g.flag = g.data[g.flagIndex]
545 g.flagIndex++
546 if g.flag&flagRepeat != 0 {
547 g.repeats = g.data[g.flagIndex]
548 g.flagIndex++
549 }
550 }
551
552 if g.flag&flagXShortVector != 0 {
553 if g.flag&flagPositiveXShortVector != 0 {
554 g.x += int16(g.data[g.xIndex])
555 } else {
556 g.x -= int16(g.data[g.xIndex])
557 }
558 g.xIndex += 1
559 } else if g.flag&flagThisXIsSame == 0 {
560 g.x += int16(u16(g.data[g.xIndex:]))
561 g.xIndex += 2
562 }
563
564 if g.flag&flagYShortVector != 0 {
565 if g.flag&flagPositiveYShortVector != 0 {
566 g.y += int16(g.data[g.yIndex])
567 } else {
568 g.y -= int16(g.data[g.yIndex])
569 }
570 g.yIndex += 1
571 } else if g.flag&flagThisYIsSame == 0 {
572 g.y += int16(u16(g.data[g.yIndex:]))
573 g.yIndex += 2
574 }
575
576 g.on = g.flag&flagOnCurve != 0
577 return true
578 }
579
View as plain text