next: GPOS & GSUB tables

main
Matthew Butterick 7 years ago
parent 3fd8cefdde
commit 7b5a04ba10

@ -44,11 +44,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js
(define/public (_getTableStream tag)
(define table (hash-ref (· this directory tables) tag))
(cond
[table
(send stream pos (· table offset))
stream]
[else #f]))
(and table (send stream pos (· table offset)) stream))
(define/public (_decodeTable table-tag)
(define table-decoder (hash-ref table-codecs table-tag
@ -233,7 +229,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js
;; Returns a GlyphRun object, which includes an array of Glyphs and GlyphPositions for the given string.
(define/contract (layout this string [userFeatures #f] [script #f] [language #f])
((string?) ((or/c (listof symbol?) #f) (or/c symbol? #f) (or/c symbol? #f)) . ->*m . GlyphRun?)
((string?) ((option/c (listof symbol?)) (option/c symbol?) (option/c symbol?)) . ->*m . GlyphRun?)
(unless (· this _layoutEngine)
(set-field! _layoutEngine this (make-object LayoutEngine this)))
(report 'in-layout)
@ -257,7 +253,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js
;; Maps a single unicode code point to a Glyph object.
;; Does not perform any advanced substitutions (there is no context to do so).
(define/contract (glyphForCodePoint this codePoint)
(index? . ->m . (is-a?/c Glyph))
(index? . ->m . Glyph?)
(define glyph-idx (FT_Get_Char_Index (· this ft-face) codePoint))
(send this getGlyph glyph-idx (list codePoint)))
@ -287,14 +283,14 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js
(define/contract (openSync filename [postscriptName #f])
((string?) ((or/c string? #f)) . ->* . TTFFont?)
((string?) ((option/c string?)) . ->* . TTFFont?)
(define buffer (file->bytes filename))
(create buffer filename postscriptName))
(define/contract (create buffer [filename #f] [postscriptName #f])
((bytes?) ((or/c path-string? #f) (or/c string? #f)) . ->* . TTFFont?)
((bytes?) ((option/c path-string?) (option/c string?)) . ->* . TTFFont?)
(or
(for*/first ([format (in-list formats)]
;; rather than use a `probe` function,

@ -1,6 +1,6 @@
#lang fontkit/racket
(require "freetype-ffi.rkt")
(provide Glyph CFFGlyph)
(provide (all-defined-out))
(module+ test (require rackunit))
#|

@ -1,5 +1,5 @@
#lang fontkit/racket
(require "bbox.rkt" "script.rkt")
(require "bbox.rkt" (prefix-in Script- "script.rkt"))
(provide (all-defined-out))
;; Represents a run of Glyph and GlyphPosition objects.
@ -15,7 +15,7 @@
(field [positions #f])
;; The directionality of the requested script (either ltr or rtl).
(field [direction (script-direction script)])
(field [direction (Script-direction script)])
;; The features requested during shaping. This is a combination of user
;; specified features and features chosen by the shaper.

@ -0,0 +1,11 @@
#lang fontkit/racket
(require "ot-processor.rkt")
(provide (all-defined-out))
#|
https://github.com/mbutterick/fontkit/blob/master/src/opentype/GPOSProcessor.js
|#
(define-subclass OTProcessor (GPOSProcessor)
)

@ -0,0 +1,11 @@
#lang fontkit/racket
(require "ot-processor.rkt")
(provide (all-defined-out))
#|
https://github.com/mbutterick/fontkit/blob/master/src/opentype/GSUBProcessor.js
|#
(define-subclass OTProcessor (GSUBProcessor)
)

@ -1,6 +1,6 @@
#lang fontkit/racket
(require "script.rkt" "glyph.rkt" "glyphrun.rkt" "glyph-position.rkt")
(provide LayoutEngine)
(require (prefix-in Script- "script.rkt") "glyph.rkt" "glyphrun.rkt" "glyph-position.rkt" "ot-layout-engine.rkt")
(provide (all-defined-out))
#|
approximates
@ -18,7 +18,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/layout/LayoutEngine.js
(cond
[(· this font has-morx-table?) (error 'morx-layout-unimplemented)]
[(or (· this font has-gsub-table?) (· this font has-gpos-table?))
(displayln 'warning:ot-layout-unimplemented) #f]
(+OTLayoutEngine (· this font))]
[else #f])])
(as-methods
@ -30,11 +30,11 @@ https://github.com/mbutterick/fontkit/blob/master/src/layout/LayoutEngine.js
(define/contract (layout this str-or-glyphs [features #f]
;; Attempt to detect the script if not provided.
[script (if (string? str-or-glyphs)
(script-for-string str-or-glyphs)
(script-for-codepoints (append-map (λ (g) (· g codePoints)) str-or-glyphs)))]
[script (report (if (string? str-or-glyphs)
(Script-forString str-or-glyphs)
(Script-forCodePoints (append-map (λ (g) (· g codePoints)) str-or-glyphs))))]
[language #f])
(((or/c string? (listof (is-a?/c Glyph)))) ((or/c list? #f) (or/c symbol? #f) (or/c symbol? #f)) . ->*m . (is-a?/c GlyphRun))
(((or/c string? (listof Glyph?))) ((option/c list?) (option/c symbol?) (option/c symbol?)) . ->*m . GlyphRun?)
(define glyphs
(if (string? str-or-glyphs)

@ -0,0 +1,24 @@
#lang fontkit/racket
(require "gsub-processor.rkt" "gpos-processor.rkt")
(provide (all-defined-out))
#|
https://github.com/mbutterick/fontkit/blob/master/src/opentype/OTLayoutEngine.js
|#
(define-subclass object% (OTLayoutEngine font)
(field [glyphInfos #f]
[plan #f]
[GSUBProcessor #f]
[GPOSProcessor #f])
(report 'dingdong)
(when (· font has-gsub-table?)
(set-field! GSUBProcessor this (+GSUBProcessor font (· font GSUB))))
(when (· font has-gpos-table?)
(set-field! GPOSProcessor this (+GPOSProcessor font (· font GPOS))))
)

@ -0,0 +1,79 @@
#lang fontkit/racket
(require (prefix-in Script- "script.rkt"))
(provide (all-defined-out))
#|
https://github.com/mbutterick/fontkit/blob/master/src/opentype/OTProcessor.js
|#
(define DEFAULT_SCRIPTS '(DFLT dflt latn))
(define-subclass object% (OTProcessor font table)
(field [script #f]
[scriptTag #f]
[language #f]
[languageTag #f]
[features (mhash)]
[lookups (mhash)])
;; initialize to default script + language
(selectScript)
;; current context (set by applyFeatures)
(field [glyphs empty]
[positions empty] ; only used by GPOS
[ligatureID 1])
(define/public (findScript script)
(unless (script? script)
(raise-argument-error 'findScript "script" script))
(and (· this table scriptList)
(let ([script (if (not (list? script)) (list script) script)])
(for*/first ([entry (in-list (· this table scriptList))]
[s (in-list script)]
#:when (equal? (· entry tag) s))
entry))))
(define/public (selectScript script language)
(let/ec return!
(define changed #f)
(define entry #f)
(when (or (not (· this script)) (not (equal? script (· this scriptTag))))
(set! entry (findScript script))
(when script
(set! entry (findScript script))) ; ? why double dip
(when (not entry)
(set! entry (findScript DEFAULT_SCRIPTS)))
(when (not entry)
(return! (void)))
(set-field! scriptTag this (· entry tag))
(set-field! script this (· entry script))
(set-field! direction this (Script-direction script))
(set-field! language this #f)
(set! changed #t))
(when (and (not language) (not (equal? language (· this languageTag))))
(for/first ([lang (in-list (· this script langSysRecords))]
#:when (equal? (· lang tag) language))
(set-field! language this (· lang langSys))
(set-field! languageTag this (· lang tag))
(set! changed #t)))
(when (not (· this language))
(set-field! language this (· this script defaultLangSys)))
;; Build a feature lookup table
(when changed
(set-field! features this (mhash))
(when (· this language)
(for ([featureIndex (in-list (· this language featureIndexes))])
(define record (hash-ref (· this table featureList) featureIndex))
(hash-set! (· this features) (· record tag)) (· record feature))))))
)

@ -1,7 +1,7 @@
#lang racket/base
(require (for-syntax racket/base br/syntax))
(provide (for-syntax (all-from-out racket/base br/syntax)))
(provide (all-from-out racket/base) r+p)
(provide (all-from-out racket/base) r+p (all-defined-out))
(define-syntax-rule (r+p id ...) (begin (require id ...) (provide (all-from-out id ...))))
@ -21,7 +21,10 @@
sugar/js
sugar/dict
sugar/stub
sugar/port)
sugar/port
sugar/contract)
(define script? symbol?)
(module reader syntax/module-reader
#:language 'fontkit/racket

@ -1,23 +1,182 @@
#lang fontkit/racket
(provide (all-defined-out))
;; approximates
;; https://github.com/devongovett/fontkit/blob/master/src/layout/Script.js
#|
https://github.com/mbutterick/fontkit/blob/master/src/layout/Script.js
|#
(define/contract (script-for-string str)
(string? . -> . symbol?)
;; infers unicode script from string.
;; todo: everything
'latn)
;; This maps the Unicode Script property to an OpenType script tag
;; Data from http://www.microsoft.com/typography/otspec/scripttags.htm
;; and http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt.
(define UNICODE_SCRIPTS
(apply mhash
'(Caucasian_Albanian aghb
Arabic arab
Imperial_Aramaic armi
Armenian armn
Avestan avst
Balinese bali
Bamum bamu
Bassa_Vah bass
Batak batk
Bengali '(bng2 beng)
Bopomofo bopo
Brahmi brah
Braille brai
Buginese bugi
Buhid buhd
Chakma cakm
Canadian_Aboriginal cans
Carian cari
Cham cham
Cherokee cher
Coptic copt
Cypriot cprt
Cyrillic cyrl
Devanagari '(dev2 deva)
Deseret dsrt
Duployan dupl
Egyptian_Hieroglyphs egyp
Elbasan elba
Ethiopic ethi
Georgian geor
Glagolitic glag
Gothic goth
Grantha gran
Greek grek
Gujarati '(gjr2 gujr)
Gurmukhi '(gur2 guru)
Hangul hang
Han hani
Hanunoo hano
Hebrew hebr
Hiragana hira
Pahawh_Hmong hmng
Katakana_Or_Hiragana hrkt
Old_Italic ital
Javanese java
Kayah_Li kali
Katakana kana
Kharoshthi khar
Khmer khmr
Khojki khoj
Kannada '(knd2 knda)
Kaithi kthi
Tai_Tham lana
Lao lao
Latin latn
Lepcha lepc
Limbu limb
Linear_A lina
Linear_B linb
Lisu lisu
Lycian lyci
Lydian lydi
Mahajani mahj
Mandaic mand
Manichaean mani
Mende_Kikakui mend
Meroitic_Cursive merc
Meroitic_Hieroglyphs mero
Malayalam '(mlm2 mlym)
Modi modi
Mongolian mong
Mro mroo
Meetei_Mayek mtei
Myanmar '(mym2 mymr)
Old_North_Arabian narb
Nabataean nbat
Nko nko
Ogham ogam
Ol_Chiki olck
Old_Turkic orkh
Oriya orya
Osmanya osma
Palmyrene palm
Pau_Cin_Hau pauc
Old_Permic perm
Phags_Pa phag
Inscriptional_Pahlavi phli
Psalter_Pahlavi phlp
Phoenician phnx
Miao plrd
Inscriptional_Parthian prti
Rejang rjng
Runic runr
Samaritan samr
Old_South_Arabian sarb
Saurashtra saur
Shavian shaw
Sharada shrd
Siddham sidd
Khudawadi sind
Sinhala sinh
Sora_Sompeng sora
Sundanese sund
Syloti_Nagri sylo
Syriac syrc
Tagbanwa tagb
Takri takr
Tai_Le tale
New_Tai_Lue talu
Tamil taml
Tai_Viet tavt
Telugu '(tel2 telu)
Tifinagh tfng
Tagalog tglg
Thaana thaa
Thai thai
Tibetan tibt
Tirhuta tirh
Ugaritic ugar
Vai vai
Warang_Citi wara
Old_Persian xpeo
Cuneiform xsux
Yi yi
Inherited zinh
Common zyyy
Unknown zzzz)))
(define/contract (script-for-codepoints codepoints)
((listof integer?) . -> . symbol?)
;; infers unicode script from string.
;; todo: everything
(error 'script-for-codepoints-unimplemented))
(define/contract (fromUnicode script)
((option/c script?) . -> . script?)
(hash-ref UNICODE_SCRIPTS script #f))
(define/contract (script-direction script)
((or/c symbol? #f) . -> . symbol?)
'ltr) ; todo everything
(define-stub-stop forString)
(define-stub-stop forCodePoints)
(define RTL '( arab ;; Arabic
hebr ;; Hebrew
syrc ;; Syriac
thaa ;; Thaana
cprt ;; Cypriot Syllabary
khar ;; Kharosthi
phnx ;; Phoenician
|nko | ;; N'Ko
lydi ;; Lydian
avst ;; Avestan
armi ;; Imperial Aramaic
phli ;; Inscriptional Pahlavi
prti ;; Inscriptional Parthian
sarb ;; Old South Arabian
orkh ;; Old Turkic, Orkhon Runic
samr ;; Samaritan
mand ;; Mandaic, Mandaean
merc ;; Meroitic Cursive
mero ;; Meroitic Hieroglyphs
;; Unicode 7.0 (not listed on http://www.microsoft.com/typography/otspec/scripttags.htm)
mani ;; Manichaean
mend ;; Mende Kikakui
nbat ;; Nabataean
narb ;; Old North Arabian
palm ;; Palmyrene
phlp ;; Psalter Pahlavi
))
(define/contract (direction script)
((option/c script?) . -> . (or/c 'rtl 'ltr))
(if (memq script RTL) 'rtl 'ltr))

@ -32,7 +32,7 @@ https://github.com/mbutterick/pdfkit/blob/master/lib/font/embedded.coffee
((string? number?) ((option/c list?)) . ->*m . number?)
(cond
[features
(define run (send (· this font) layout string features)) ; todo: features would be passed here
(define run (send (· this font) layout string features))
(define width (· run advanceWidth))
(define scale (/ size (· this font unitsPerEm)))
(* width scale)]

@ -16,5 +16,5 @@
(define-runtime-path this "test15rkt.pdf")
(make-doc this #f proc #:test #f)
#;(define-runtime-path that "test14crkt.pdf")
#;(define-runtime-path that "test15crkt.pdf")
#;(make-doc that #t proc #:pdfkit #f)
Loading…
Cancel
Save