|
|
|
@ -16,29 +16,31 @@ https://github.com/mbutterick/fontkit/blob/master/src/glyph/TTFGlyph.js
|
|
|
|
|
'yMax int16be)))
|
|
|
|
|
|
|
|
|
|
;; Flags for simple glyphs
|
|
|
|
|
(match-define (list ON_CURVE
|
|
|
|
|
X_SHORT_VECTOR
|
|
|
|
|
Y_SHORT_VECTOR
|
|
|
|
|
REPEAT
|
|
|
|
|
SAME_X
|
|
|
|
|
SAME_Y)
|
|
|
|
|
(map (curry expt 2) (range 6)))
|
|
|
|
|
(define-macro (define-flag-series . IDS)
|
|
|
|
|
#`(match-define (list . IDS) (map (curry expt 2) (range #,(length (syntax->list #'IDS))))))
|
|
|
|
|
|
|
|
|
|
;; Flags for simple glyphs
|
|
|
|
|
(define-flag-series ON_CURVE
|
|
|
|
|
X_SHORT_VECTOR
|
|
|
|
|
Y_SHORT_VECTOR
|
|
|
|
|
REPEAT
|
|
|
|
|
SAME_X
|
|
|
|
|
SAME_Y)
|
|
|
|
|
|
|
|
|
|
;; Flags for composite glyphs
|
|
|
|
|
(match-define (list ARG_1_AND_2_ARE_WORDS
|
|
|
|
|
ARGS_ARE_XY_VALUES
|
|
|
|
|
ROUND_XY_TO_GRID
|
|
|
|
|
WE_HAVE_A_SCALE
|
|
|
|
|
___NO-FLAG___
|
|
|
|
|
MORE_COMPONENTS
|
|
|
|
|
WE_HAVE_AN_X_AND_Y_SCALE
|
|
|
|
|
WE_HAVE_A_TWO_BY_TWO
|
|
|
|
|
WE_HAVE_INSTRUCTIONS
|
|
|
|
|
USE_MY_METRICS
|
|
|
|
|
OVERLAP_COMPOUND
|
|
|
|
|
SCALED_COMPONENT_OFFSET
|
|
|
|
|
UNSCALED_COMPONENT_OFFSET)
|
|
|
|
|
(map (curry expt 2) (range 13)))
|
|
|
|
|
(define-flag-series ARG_1_AND_2_ARE_WORDS
|
|
|
|
|
ARGS_ARE_XY_VALUES
|
|
|
|
|
ROUND_XY_TO_GRID
|
|
|
|
|
WE_HAVE_A_SCALE
|
|
|
|
|
__EMPTY-FLAG___
|
|
|
|
|
MORE_COMPONENTS
|
|
|
|
|
WE_HAVE_AN_X_AND_Y_SCALE
|
|
|
|
|
WE_HAVE_A_TWO_BY_TWO
|
|
|
|
|
WE_HAVE_INSTRUCTIONS
|
|
|
|
|
USE_MY_METRICS
|
|
|
|
|
OVERLAP_COMPOUND
|
|
|
|
|
SCALED_COMPONENT_OFFSET
|
|
|
|
|
UNSCALED_COMPONENT_OFFSET)
|
|
|
|
|
|
|
|
|
|
;; Represents a point in a simple glyph
|
|
|
|
|
(define-subclass object% (Point onCurve endContour [x 0] [y 0])
|
|
|
|
@ -52,8 +54,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/glyph/TTFGlyph.js
|
|
|
|
|
[scaleX 1]
|
|
|
|
|
[scaleY 1]
|
|
|
|
|
[scale01 0]
|
|
|
|
|
[scale10 0])
|
|
|
|
|
)
|
|
|
|
|
[scale10 0]))
|
|
|
|
|
|
|
|
|
|
;; Represents a TrueType glyph.
|
|
|
|
|
(define-subclass Glyph (TTFGlyph)
|
|
|
|
@ -65,6 +66,12 @@ https://github.com/mbutterick/fontkit/blob/master/src/glyph/TTFGlyph.js
|
|
|
|
|
|
|
|
|
|
;; Parses a single glyph coordinate
|
|
|
|
|
(define/public (_parseGlyphCoord stream prev short same)
|
|
|
|
|
(unless (DecodeStream? stream)
|
|
|
|
|
(raise-argument-error '_parseGlyphCoord "DecodeStream" stream))
|
|
|
|
|
(unless (number? prev)
|
|
|
|
|
(raise-argument-error '_parseGlyphCoord "number" prev))
|
|
|
|
|
(unless (and (boolean? short) (boolean? same))
|
|
|
|
|
(raise-argument-error '_parseGlyphCoord "booleans" (list short same)))
|
|
|
|
|
(+ prev (if short
|
|
|
|
|
((if (not same) - +) (send uint8 decode stream))
|
|
|
|
|
(if same 0 (send int16be decode stream)))))
|
|
|
|
@ -73,28 +80,20 @@ https://github.com/mbutterick/fontkit/blob/master/src/glyph/TTFGlyph.js
|
|
|
|
|
;; Decodes the glyph data into points for simple glyphs,
|
|
|
|
|
;; or components for composite glyphs
|
|
|
|
|
(define/public (_decode)
|
|
|
|
|
(define offsets (hash-ref (send _font _getTable 'loca) 'offsets))
|
|
|
|
|
(define glyfPos (list-ref offsets id))
|
|
|
|
|
(define nextPos (list-ref offsets (add1 id)))
|
|
|
|
|
(define offsets (· (send _font _getTable 'loca) offsets))
|
|
|
|
|
(match-define (list glyfPos nextPos) (take (drop offsets id) 2))
|
|
|
|
|
|
|
|
|
|
;; Nothing to do if there is no data for this glyph
|
|
|
|
|
(cond
|
|
|
|
|
[(= glyfPos nextPos) #f]
|
|
|
|
|
[else
|
|
|
|
|
(define stream (send _font _getTableStream 'glyf))
|
|
|
|
|
(send stream pos (+ (send stream pos) glyfPos))
|
|
|
|
|
(define startPos (· stream pos))
|
|
|
|
|
|
|
|
|
|
(define glyph (send GlyfHeader decode stream))
|
|
|
|
|
|
|
|
|
|
(let ([contour-count (· glyph numberOfContours)])
|
|
|
|
|
(cond
|
|
|
|
|
[(positive? contour-count)
|
|
|
|
|
(_decodeSimple glyph stream)]
|
|
|
|
|
[(negative? contour-count)
|
|
|
|
|
(_decodeComposite glyph stream startPos)]))
|
|
|
|
|
|
|
|
|
|
glyph]))
|
|
|
|
|
(and (not (= glyfPos nextPos))
|
|
|
|
|
(let ()
|
|
|
|
|
(define stream (send _font _getTableStream 'glyf))
|
|
|
|
|
(send stream pos (+ (send stream pos) glyfPos))
|
|
|
|
|
(define startPos (· stream pos))
|
|
|
|
|
(define glyph (send GlyfHeader decode stream))
|
|
|
|
|
(match (· glyph numberOfContours)
|
|
|
|
|
[(? positive?) (_decodeSimple glyph stream)]
|
|
|
|
|
[(? negative?) (_decodeComposite glyph stream startPos)])
|
|
|
|
|
glyph)))
|
|
|
|
|
|
|
|
|
|
(define/public (_decodeSimple glyph stream)
|
|
|
|
|
(unless (hash? glyph)
|
|
|
|
@ -105,49 +104,31 @@ https://github.com/mbutterick/fontkit/blob/master/src/glyph/TTFGlyph.js
|
|
|
|
|
|
|
|
|
|
;; this is a simple glyph
|
|
|
|
|
(hash-set! glyph 'points empty)
|
|
|
|
|
|
|
|
|
|
(define endPtsOfContours (send (+Array uint16be (· glyph numberOfContours)) decode stream))
|
|
|
|
|
|
|
|
|
|
(hash-set! glyph 'instructions (send (+Array uint8be uint16be) decode stream))
|
|
|
|
|
|
|
|
|
|
(define numCoords (add1 (list-ref endPtsOfContours (sub1 (length endPtsOfContours)))))
|
|
|
|
|
(define numCoords (add1 (last endPtsOfContours)))
|
|
|
|
|
|
|
|
|
|
(define flags
|
|
|
|
|
(reverse
|
|
|
|
|
(for/fold ([flags empty])
|
|
|
|
|
([i (in-naturals)]
|
|
|
|
|
#:break (= (length flags) numCoords))
|
|
|
|
|
(define flag (send uint8 decode stream))
|
|
|
|
|
|
|
|
|
|
;; check for repeat flag
|
|
|
|
|
(define repeated-flags
|
|
|
|
|
(cond
|
|
|
|
|
[(not (zero? (bitwise-and flag REPEAT)))
|
|
|
|
|
(define count (send uint8 decode stream))
|
|
|
|
|
(make-list count flag)]
|
|
|
|
|
[else empty]))
|
|
|
|
|
|
|
|
|
|
(append repeated-flags (cons flag flags)))))
|
|
|
|
|
|
|
|
|
|
(define glyph-points (mhash))
|
|
|
|
|
(for ([(flag i) (in-indexed flags)])
|
|
|
|
|
(define point (+Point (zero? (bitwise-and flag ON_CURVE)) (and (index-of endPtsOfContours i) #t) 0 0))
|
|
|
|
|
(hash-set! glyph-points i point))
|
|
|
|
|
|
|
|
|
|
(for/fold ([px 0])
|
|
|
|
|
([(flag i) (in-indexed flags)])
|
|
|
|
|
(define next-px (_parseGlyphCoord stream px (bitwise-and flag X_SHORT_VECTOR) (bitwise-and flag SAME_X)))
|
|
|
|
|
(set-field! x (hash-ref glyph-points i) next-px)
|
|
|
|
|
next-px)
|
|
|
|
|
|
|
|
|
|
(for/fold ([py 0])
|
|
|
|
|
([(flag i) (in-indexed flags)])
|
|
|
|
|
(define next-py (_parseGlyphCoord stream py (bitwise-and flag Y_SHORT_VECTOR) (bitwise-and flag SAME_Y)))
|
|
|
|
|
(set-field! y (hash-ref glyph-points i) next-py)
|
|
|
|
|
next-py)
|
|
|
|
|
|
|
|
|
|
;; skip variations shit
|
|
|
|
|
)
|
|
|
|
|
(for*/lists (flags)
|
|
|
|
|
([i (in-naturals)]
|
|
|
|
|
#:break (= (length flags) numCoords)
|
|
|
|
|
[flag (in-value (send uint8 decode stream))]
|
|
|
|
|
[count (in-range (add1 (if (not (zero? (bitwise-and flag REPEAT)))
|
|
|
|
|
(send uint8 decode stream)
|
|
|
|
|
0)))])
|
|
|
|
|
flag))
|
|
|
|
|
|
|
|
|
|
(match-define-values
|
|
|
|
|
(points _ _)
|
|
|
|
|
(for/fold ([points empty] [px 0] [py 0])
|
|
|
|
|
([(flag i) (in-indexed flags)])
|
|
|
|
|
(define point (+Point (zero? (bitwise-and flag ON_CURVE)) (and (index-of endPtsOfContours i) #t) 0 0))
|
|
|
|
|
(define next-px (_parseGlyphCoord stream px (not (zero? (bitwise-and flag X_SHORT_VECTOR))) (not (zero? (bitwise-and flag SAME_X)))))
|
|
|
|
|
(define next-py (_parseGlyphCoord stream py (not (zero? (bitwise-and flag Y_SHORT_VECTOR))) (not (zero? (bitwise-and flag SAME_Y)))))
|
|
|
|
|
(set-field! x point next-px)
|
|
|
|
|
(set-field! y point next-py)
|
|
|
|
|
(values (cons point points) next-px next-py)))
|
|
|
|
|
(hash-set! glyph 'points (reverse points)))
|
|
|
|
|
|
|
|
|
|
(define/public (_decodeComposite glyph stream [offset 0])
|
|
|
|
|
;; this is a composite glyph
|
|
|
|
@ -185,11 +166,8 @@ https://github.com/mbutterick/fontkit/blob/master/src/glyph/TTFGlyph.js
|
|
|
|
|
(set-field! scale01 component (read-fixed14 stream))
|
|
|
|
|
(set-field! scale10 component (read-fixed14 stream))
|
|
|
|
|
(set-field! scaleY component (read-fixed14 stream))])
|
|
|
|
|
|
|
|
|
|
component))
|
|
|
|
|
|
|
|
|
|
haveInstructions
|
|
|
|
|
))
|
|
|
|
|
haveInstructions))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (bytes->fixed14 b1 b2)
|
|
|
|
|