foliojs / fontkit

An advanced font engine for Node and the browser
1.45k stars 213 forks source link

Faster, smaller `isEqual` #279

Closed toastal closed 2 years ago

toastal commented 2 years ago

The deep-equal dependency is both slower than fast-deep-equal and has a number of obsolete dependencies to polyfill browsers and Node versions that this project doesn’t target.

To visualize the chain of dependencies deep-equals adds to your project (requires JS enabled): https://npmgraph.js.org/?q=fontkit This would move from around 61 dependencies to 12 (& 11kb Gzip’d).

Moving to fast-deep-equal seems like a win-win.

toastal commented 2 years ago

Test ran on x86_64 Linux with Node.js v14 LTS

$ uname -m -o
x86_64 GNU/Linux

$ node --version
v14.18.3

$ npm run test

> fontkit@1.9.0 test /home/toastal/Incantations/fontkit
> run-s build mocha

> fontkit@1.9.0 build /home/toastal/Incantations/fontkit
> parcel build

✨ Built in 203ms

dist/main.cjs      588.09 KB    92ms
dist/module.mjs    543.13 KB    93ms

> fontkit@1.9.0 mocha /home/toastal/Incantations/fontkit
> mocha

  metadata
    ✔ decodes SFNT directory values correctly
    ✔ numTables matches table collection

  character to glyph mapping
    basic cmap handling
      ✔ should get characterSet
      ✔ should check if a character is supported
      ✔ should get a glyph for a character code
      ✔ should map a string to glyphs
      ✔ should support unicode variation selectors
      ✔ should support legacy encodings when no unicode cmap is found
    opentype features
      ✔ should list available features
      ✔ should apply opentype GSUB features
      ✔ should enable fractions when using fraction slash
      ✔ should not break if can’t enable fractions when using fraction slash
    AAT features
      ✔ should list available features
      ✔ should apply default AAT morx features
      ✔ should allow for disabling of default AAT morx features
      ✔ should apply user specified features
      ✔ should handle rtl direction
      ✔ should apply indic reordering features
    glyph id to strings
      ✔ should return strings from cmap that map to a given glyph
      ✔ should return strings from AAT morx table that map to the given glyph

  glyph positioning
    basic positioning
      ✔ should get a glyph width
    opentype positioning
      ✔ should apply opentype GPOS features
      ✔ should ignore duplicate features
    AAT features
      ✔ should apply kerning by default

  glyphs
    truetype glyphs
      ✔ should get a TTFGlyph
      ✔ should get a path for the glyph as SVG
      ✔ should get a path for the glyph as function
      ✔ should get a composite glyph
      ✔ should resolve composite glyphs recursively
      ✔ should transform points of a composite glyph
      ✔ should be able to get a scaled path at a given font size
      ✔ should get the glyph cbox
      ✔ should get the glyph bbox
      ✔ should get correct bbox for runs containing blanks (50ms)
      ✔ should get the advance width
      ✔ should get the glyph name
    CFF glyphs
      ✔ should get a CFFGlyph
      ✔ should get a path for the glyph as SVG
      ✔ should get a path for the glyph as function
      ✔ should get the glyph cbox
      ✔ should get the glyph bbox
      ✔ should get the glyph name
    CFF glyphs (CID font)
      ✔ should get a CFFGlyph
      ✔ should get a path for the glyph (41ms)
      ✔ should get the glyph cbox
      ✔ should get the glyph bbox
      ✔ should get the correct fd index
    SBIX glyphs
      ✔ should get an SBIXGlyph
      ✔ should have an empty path
      ✔ should get an image
      ✔ should get the glyph name
    COLR glyphs
      ✔ should get an SBIXGlyph
      ✔ should get layers
      ✔ should get empty path
      ✔ should get bbox
      ✔ should get the glyph name
    WOFF ttf glyphs
      ✔ should get the glyph name
      ✔ should get a TTFGlyph
      ✔ should get a quadratic path for the glyph
    WOFF otf glyphs
      ✔ should get the glyph name
      ✔ should get a CFFGlyph
      ✔ should get a cubic path for the glyph
    WOFF2 ttf glyph
      ✔ should get the glyph name
      ✔ should get a WOFF2Glyph
      ✔ should get a path for the glyph
      ✔ should get a correct quadratic path for all contours
      ✔ should get the ttf glyph cbox
      ✔ should get the ttf glyph bbox
    WOFF2 otf glyph
      ✔ should get the glyph name
      ✔ should get a CFFGlyph
      ✔ should get a path for the glyph
      ✔ should get a correct cubic path for all contours
      ✔ should get the otf glyph cbox
      ✔ should get the otf glyph bbox

  i18n
    fontkit.setDefaultLanguage
      ✔ font has "en" metadata properties
      ✔ can set global default language to "ar"
      ✔ font now has "ar" metadata properties
      ✔ can reset default language back to "en"
    font.setDefaultLanguage
      ✔ font has "en" metadata properties
      ✔ can set font's default language to "ar"
      ✔ font now has "ar" metadata properties
      ✔ the font's language should not change when the global changes
      ✔ can reset default language back to "en"
    backup languages
      ✔ if the font's default language isn't found, use the global language
      ✔ if the global language isn't found, use "en"

  fontkit
    ✔ should open a font asynchronously
    ✔ should open a font synchronously
    ✔ should open fonts of different formats
    ✔ should open fonts lacking PostScript name
    ✔ should error when opening an invalid font asynchronously
    ✔ should error when opening an invalid font synchronously
    ✔ should get collection objects for ttc fonts
    ✔ should get collection objects for dfonts

  metadata
    ✔ has metadata properties
    ✔ exposes some metrics
    ✔ exposes tables directly

  opentype
    ✔ featureParams nameID of stylistic set should be 257
    ✔ featureParams version of stylistic set should be 0
    ✔ featureParams should be null of aalt opentype feature

  shaping
    general shaping tests
      ✔ should use correct script and language when features are not specified (47ms)
      ✔ should use specified left-to-right direction
    arabic shaper
      ✔ should shape Arabic text
      ✔ should handle cursive attachment positioning (57ms)
      ✔ should shape Mongolian text
      ✔ should shape Syriac text
      ✔ should shape N'Ko text
      ✔ should shape Phags Pa text
      ✔ should attach marks to the first base of a multiple substitution (42ms)
      ✔ should adjust attached marks if base is adjusted
    hangul shaper
      ✔ should use composed versions if supported by the font
      ✔ should compose decomposed syllables if supported
      ✔ should use OT features for non-combining <L,V,T>
      ✔ should decompose <LV,T> to <L,V,T> if <LVT> is not supported
      ✔ should reorder tone marks to the beginning of <L,V> syllables
      ✔ should reorder tone marks to the beginning of <L,V,T> syllables
      ✔ should reorder tone marks to the beginning of <LV> syllables
      ✔ should reorder tone marks to the beginning of <LVT> syllables
      ✔ should insert a dotted circle for invalid tone marks
    indic shaper
      shapes Kannada text
        ✔ SHKNDA-1/1
        ✔ SHKNDA-1/2
        ✔ SHKNDA-1/3
        ✔ SHKNDA-1/4
        ✔ SHKNDA-1/5
        ✔ SHKNDA-1/6
        ✔ SHKNDA-1/7
        ✔ SHKNDA-1/8
        ✔ SHKNDA-1/9
        ✔ SHKNDA-1/10
        ✔ SHKNDA-1/11
        ✔ SHKNDA-1/12
        ✔ SHKNDA-1/13
        ✔ SHKNDA-1/14
        ✔ SHKNDA-1/15
        ✔ SHKNDA-1/16
        ✔ SHKNDA-1/17
        ✔ SHKNDA-1/18
        ✔ SHKNDA-1/19
        ✔ SHKNDA-1/20
        ✔ SHKNDA-1/21
        ✔ SHKNDA-1/22
        ✔ SHKNDA-1/23
        ✔ SHKNDA-1/24
        ✔ SHKNDA-1/25
        ✔ SHKNDA-1/26
        ✔ SHKNDA-1/27
        ✔ SHKNDA-1/28
        ✔ SHKNDA-1/29
        ✔ SHKNDA-1/30
        ✔ SHKNDA-1/31
        ✔ SHKNDA-1/32
        ✔ SHKNDA-1/33
        ✔ SHKNDA-1/34
        ✔ SHKNDA-2/1
        ✔ SHKNDA-2/2
        ✔ SHKNDA-2/3
        ✔ SHKNDA-2/4
        ✔ SHKNDA-2/5
        ✔ SHKNDA-2/6
        ✔ SHKNDA-2/7
        ✔ SHKNDA-2/8
        ✔ SHKNDA-2/9
        ✔ SHKNDA-2/10
        ✔ SHKNDA-2/11
        ✔ SHKNDA-2/12
        ✔ SHKNDA-2/13
        ✔ SHKNDA-2/14
        ✔ SHKNDA-2/15
        ✔ SHKNDA-2/16
        ✔ SHKNDA-3/1
        ✔ SHKNDA-3/2
        ✔ SHKNDA-3/3
        ✔ SHKNDA-3/4
        ✔ SHKNDA-3/5
        ✔ SHKNDA-3/6
        ✔ SHKNDA-3/7
        ✔ SHKNDA-3/8
        ✔ SHKNDA-3/9
        ✔ SHKNDA-3/10
        ✔ SHKNDA-3/11
        ✔ SHKNDA-3/12
        ✔ SHKNDA-3/13
        ✔ SHKNDA-3/14
        ✔ SHKNDA-3/15
        ✔ SHKNDA-3/16
        ✔ SHKNDA-3/17
        ✔ SHKNDA-3/18
        ✔ SHKNDA-3/19
        ✔ SHKNDA-3/20
        ✔ SHKNDA-3/21
        ✔ SHKNDA-3/22
        ✔ SHKNDA-3/23
        ✔ SHKNDA-3/24
        ✔ SHKNDA-3/25
        ✔ SHKNDA-3/26
        ✔ SHKNDA-3/27
        ✔ SHKNDA-3/28
        ✔ SHKNDA-3/29
        ✔ SHKNDA-3/30
        ✔ SHKNDA-3/31
      shapes Telugu text
        ✔ HB-TELU-1
        ✔ HB-TELU-2
        ✔ HB-TELU-3
        ✔ HB-TELU-4
        ✔ HB-TELU-5
        ✔ HB-TELU-6
        ✔ HB-TELU-7
        ✔ HB-TELU-8
        ✔ HB-TELU-9
        ✔ HB-TELU-10
        ✔ HB-TELU-11
        ✔ HB-TELU-12
      shapes Tamil text
        ✔ HB-TAML-1
        ✔ HB-TAML-2
        ✔ HB-TAML-3
        ✔ HB-TAML-4
        ✔ HB-TAML-5
        ✔ HB-TAML-6
        ✔ HB-TAML-7
        ✔ HB-TAML-8
        ✔ HB-TAML-9
        ✔ HB-TAML-10
        ✔ HB-TAML-11
        ✔ HB-TAML-12
        ✔ HB-TAML-13
        ✔ HB-TAML-14
        ✔ HB-TAML-15
        ✔ HB-TAML-16
        ✔ HB-TAML-17
        ✔ HB-TAML-18
        ✔ HB-TAML-19
        ✔ HB-TAML-20
        ✔ HB-TAML-21
        ✔ HB-TAML-22
        ✔ HB-TAML-23
        ✔ HB-TAML-24
        ✔ HB-TAML-25
        ✔ HB-TAML-26
        ✔ HB-TAML-27
        ✔ HB-TAML-28
        ✔ HB-TAML-29
        ✔ HB-TAML-30
        ✔ HB-TAML-31
        ✔ HB-TAML-32
        ✔ HB-TAML-33
        ✔ HB-TAML-34
        ✔ HB-TAML-35
        ✔ HB-TAML-36
        ✔ HB-TAML-37
        ✔ HB-TAML-38
        ✔ HB-TAML-39
        ✔ HB-TAML-40
        ✔ HB-TAML-41
        ✔ HB-TAML-42
        ✔ HB-TAML-43
      shapes Devanagari text
        joiners
          ✔ HB-DEVA-joiners-1
          ✔ HB-DEVA-joiners-2
          ✔ HB-DEVA-joiners-3
          ✔ HB-DEVA-joiners-4
          ✔ HB-DEVA-joiners-5
          ✔ HB-DEVA-joiners-6
          ✔ HB-DEVA-joiners-7
          ✔ HB-DEVA-joiners-8
          ✔ HB-DEVA-joiners-9
          ✔ HB-DEVA-joiners-10
          ✔ HB-DEVA-joiners-11
          ✔ HB-DEVA-joiners-12
          ✔ HB-DEVA-joiners-13
          ✔ HB-DEVA-joiners-14
          ✔ HB-DEVA-joiners-15
          ✔ HB-DEVA-joiners-16
          ✔ HB-DEVA-joiners-17
          ✔ HB-DEVA-joiners-18
          ✔ HB-DEVA-joiners-19
        misc
          ✔ HB-DEVA-misc-1
          ✔ HB-DEVA-misc-2
          ✔ HB-DEVA-misc-3
          ✔ HB-DEVA-misc-4
          ✔ HB-DEVA-misc-5
          ✔ HB-DEVA-misc-6
          ✔ HB-DEVA-misc-7
          ✔ HB-DEVA-misc-8
          ✔ HB-DEVA-misc-9
          ✔ HB-DEVA-misc-10
          ✔ HB-DEVA-misc-11
          ✔ HB-DEVA-misc-12
          ✔ HB-DEVA-misc-13
          ✔ HB-DEVA-misc-14
          ✔ HB-DEVA-misc-15
          ✔ HB-DEVA-misc-16
          ✔ HB-DEVA-misc-17
          ✔ HB-DEVA-misc-18
          ✔ HB-DEVA-misc-19
          ✔ HB-DEVA-misc-20
          ✔ HB-DEVA-misc-21
          ✔ HB-DEVA-misc-22
          ✔ HB-DEVA-misc-23
          ✔ HB-DEVA-misc-24
          ✔ HB-DEVA-misc-25
          ✔ HB-DEVA-misc-26
          ✔ HB-DEVA-misc-27
          ✔ HB-DEVA-misc-28
          ✔ HB-DEVA-misc-29
          ✔ HB-DEVA-misc-30
          ✔ HB-DEVA-misc-31
          ✔ HB-DEVA-misc-32
          ✔ HB-DEVA-misc-33
          ✔ HB-DEVA-misc-34
          ✔ HB-DEVA-misc-35
          ✔ HB-DEVA-misc-36
        dotted circle
          ✔ HB-DEVA-dottedcircle-1
          ✔ HB-DEVA-dottedcircle-2
          ✔ HB-DEVA-dottedcircle-3
          ✔ HB-DEVA-dottedcircle-4
          ✔ HB-DEVA-dottedcircle-5
          ✔ HB-DEVA-dottedcircle-6
          ✔ HB-DEVA-dottedcircle-7
          ✔ HB-DEVA-dottedcircle-8
        eyelash
          ✔ HB-DEVA-eyelash-1
          ✔ HB-DEVA-eyelash-2
          ✔ HB-DEVA-eyelash-3
      shapes Bengali text
        ✔ HB-BENG-1
        ✔ HB-BENG-2
        ✔ HB-BENG-3
        ✔ HB-BENG-4
        ✔ HB-BENG-5
        ✔ HB-BENG-6
        ✔ HB-BENG-7
        ✔ HB-BENG-8
        ✔ HB-BENG-9
        ✔ HB-BENG-10
        ✔ HB-BENG-11
        ✔ HB-BENG-12
        ✔ HB-BENG-13
        ✔ HB-BENG-14
        ✔ HB-BENG-15
        ✔ HB-BENG-16
        ✔ HB-BENG-17
        ✔ HB-BENG-18
        ✔ HB-BENG-19
        ✔ HB-BENG-20
        ✔ HB-BENG-21
        ✔ HB-BENG-22
        ✔ HB-BENG-23
        ✔ HB-BENG-24
        ✔ HB-BENG-25
        ✔ HB-BENG-26
        ✔ HB-BENG-27
        ✔ HB-BENG-28
        ✔ HB-BENG-29
        ✔ HB-BENG-30
        ✔ HB-BENG-31
        ✔ HB-BENG-32
        ✔ HB-BENG-33
        ✔ HB-BENG-34
        ✔ HB-BENG-35
        ✔ HB-BENG-36
        ✔ HB-BENG-37
        ✔ HB-BENG-38
        ✔ HB-BENG-39
        ✔ HB-BENG-40
        ✔ HB-BENG-41
        ✔ HB-BENG-42
        ✔ HB-BENG-43
        ✔ HB-BENG-44
        ✔ HB-BENG-45
        ✔ HB-BENG-46
        ✔ HB-BENG-47
        ✔ HB-BENG-48
        ✔ HB-BENG-49
        ✔ HB-BENG-50
        ✔ HB-BENG-51
        ✔ HB-BENG-52
        ✔ HB-BENG-53
      shapes Gurmukhi text
        ✔ HB-GURU-1
        ✔ HB-GURU-2
      shapes Gujarati text
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
      shapes Malayalam text
        ✔ HB-MLYM-1
        ✔ HB-MLYM-2
        ✔ HB-MLYM-3
        ✔ HB-MLYM-4
        ✔ HB-MLYM-5
        ✔ HB-MLYM-6
        ✔ HB-MLYM-7
        ✔ HB-MLYM-8
        ✔ HB-MLYM-9
        ✔ HB-MLYM-10
        ✔ HB-MLYM-11
        ✔ HB-MLYM-12
        ✔ HB-MLYM-13
        ✔ HB-MLYM-14
        ✔ HB-MLYM-15
        ✔ HB-MLYM-16
        ✔ HB-MLYM-17
        ✔ HB-MLYM-18
        ✔ HB-MLYM-19
        ✔ HB-MLYM-20
        ✔ HB-MLYM-21
        ✔ HB-MLYM-22
        ✔ HB-MLYM-23
        ✔ HB-MLYM-24
        ✔ HB-MLYM-25
        ✔ HB-MLYM-26
        ✔ HB-MLYM-27
        ✔ HB-MLYM-28
        ✔ HB-MLYM-29
        ✔ HB-MLYM-30
        ✔ HB-MLYM-31
        ✔ HB-MLYM-32
        ✔ HB-MLYM-33
        ✔ HB-MLYM-34
        ✔ HB-MLYM-35
        ✔ HB-MLYM-36
        ✔ HB-MLYM-37
        ✔ HB-MLYM-38
        ✔ HB-MLYM-39
        ✔ HB-MLYM-40
        ✔ HB-MLYM-41
        ✔ HB-MLYM-42
        ✔ HB-MLYM-43
        ✔ HB-MLYM-44
        ✔ HB-MLYM-45
        ✔ HB-MLYM-46
        ✔ HB-MLYM-47
        ✔ HB-MLYM-48
        ✔ HB-MLYM-49
        ✔ HB-MLYM-50
        ✔ HB-MLYM-51
        ✔ HB-MLYM-52
        ✔ HB-MLYM-53
        ✔ HB-MLYM-54
        ✔ HB-MLYM-55
        ✔ HB-MLYM-56
        ✔ HB-MLYM-57
        ✔ HB-MLYM-58
        ✔ HB-MLYM-59
        ✔ HB-MLYM-60
        ✔ HB-MLYM-61
        ✔ HB-MLYM-62
        ✔ HB-MLYM-63
        ✔ HB-MLYM-64
        ✔ HB-MLYM-65
      shapes Oriya text
        ✔ HB-ORYA-1
        ✔ HB-ORYA-2
        ✔ HB-ORYA-3
        ✔ HB-ORYA-4
        ✔ HB-ORYA-5
        ✔ HB-ORYA-6
        ✔ HB-ORYA-7
        ✔ HB-ORYA-8
      shapes Khmer text
        ✔ HB-KHMR-1
        ✔ HB-KHMR-2
        ✔ HB-KHMR-3
        ✔ HB-KHMR-4
        ✔ HB-KHMR-5
        ✔ HB-KHMR-6
        ✔ HB-KHMR-7
        ✔ HB-KHMR-8
        ✔ HB-KHMR-9
        ✔ HB-KHMR-10
        ✔ HB-KHMR-11
        ✔ HB-KHMR-12
        ✔ HB-KHMR-13
        ✔ HB-KHMR-14
        ✔ HB-KHMR-15
        ✔ HB-KHMR-16
        ✔ HB-KHMR-17
        ✔ HB-KHMR-18
        ✔ HB-KHMR-19
        ✔ HB-KHMR-20
        ✔ HB-KHMR-21
        ✔ HB-KHMR-22
        ✔ HB-KHMR-23
        ✔ decomposes split matras
    universal shaping engine
      shapes balinese text
        ✔ SHBALI-1/1
        ✔ SHBALI-1/2
        ✔ SHBALI-1/3
        ✔ SHBALI-1/4
        ✔ SHBALI-1/5
        ✔ SHBALI-1/6
        ✔ SHBALI-1/7
        ✔ SHBALI-1/8
        ✔ SHBALI-1/9
        ✔ SHBALI-1/10
        ✔ SHBALI-1/11
        ✔ SHBALI-1/12
        ✔ SHBALI-1/13
        ✔ SHBALI-1/14
        ✔ SHBALI-1/15
        ✔ SHBALI-1/16
        ✔ SHBALI-1/17
        ✔ SHBALI-1/18
        ✔ SHBALI-1/19
        ✔ SHBALI-1/20
        ✔ SHBALI-1/21
        ✔ SHBALI-1/22
        ✔ SHBALI-2/1
        ✔ SHBALI-2/2
        ✔ SHBALI-2/3
        ✔ SHBALI-2/4
        ✔ SHBALI-2/5
        ✔ SHBALI-2/6
        ✔ SHBALI-2/7
        ✔ SHBALI-2/8
        ✔ SHBALI-2/9
        ✔ SHBALI-2/10
        ✔ SHBALI-2/11
        ✔ SHBALI-2/12

  font subsetting
    truetype subsetting
      ✔ should produce a subset
      - should re-encode variation glyphs
      ✔ should handle composite glyphs
      ✔ should handle fonts with long index to location format (indexToLocFormat = 1)
    CFF subsetting
      ✔ should produce a subset
      ✔ should handle CID fonts (104ms)
      ✔ should produce a subset with asian punctuation corretly (51ms)

  variations
    Skia
      - should get available variation axes
      - should get named variation instances
      - should get a variation by name
      - should get a variation by settings
      - interpolates points without delta values
      - recomputes cbox and advance width
    truetype variations
      ✔ should support sharing all points
      ✔ should support sharing enumerated points
      ✔ should support sharing no points
      ✔ should use the HVAR table when available for variation metrics
      ✔ should fall back to the last entry in an HVAR table
      ✔ should support adjusting GPOS mark anchor points for variations
    CFF2 variations
      ✔ applies variations to CFF2 glyphs
      ✔ substitutes GSUB features depending on variations

  541 passing (1s)
  7 pending
toastal commented 2 years ago

Sorry, it looks like this project was using a newer npm version so I force pushed. New test results

$ uname -m -o
x86_64 GNU/Linux

$ node --version
v16.13.2

$ npm run test

> fontkit@1.9.0 test
> run-s build mocha

> fontkit@1.9.0 build
> parcel build

✨ Built in 179ms

dist/main.cjs      588.09 KB    180ms
dist/module.mjs    543.13 KB    148ms

> fontkit@1.9.0 mocha
> mocha

  metadata
    ✔ decodes SFNT directory values correctly
    ✔ numTables matches table collection

  character to glyph mapping
    basic cmap handling
      ✔ should get characterSet
      ✔ should check if a character is supported
      ✔ should get a glyph for a character code
      ✔ should map a string to glyphs
      ✔ should support unicode variation selectors
      ✔ should support legacy encodings when no unicode cmap is found
    opentype features
      ✔ should list available features
      ✔ should apply opentype GSUB features
      ✔ should enable fractions when using fraction slash
      ✔ should not break if can’t enable fractions when using fraction slash
    AAT features
      ✔ should list available features
      ✔ should apply default AAT morx features
      ✔ should allow for disabling of default AAT morx features
      ✔ should apply user specified features
      ✔ should handle rtl direction
      ✔ should apply indic reordering features
    glyph id to strings
      ✔ should return strings from cmap that map to a given glyph
      ✔ should return strings from AAT morx table that map to the given glyph

  glyph positioning
    basic positioning
      ✔ should get a glyph width
    opentype positioning
      ✔ should apply opentype GPOS features
      ✔ should ignore duplicate features
    AAT features
      ✔ should apply kerning by default

  glyphs
    truetype glyphs
      ✔ should get a TTFGlyph
      ✔ should get a path for the glyph as SVG
      ✔ should get a path for the glyph as function
      ✔ should get a composite glyph
      ✔ should resolve composite glyphs recursively
      ✔ should transform points of a composite glyph
      ✔ should be able to get a scaled path at a given font size
      ✔ should get the glyph cbox
      ✔ should get the glyph bbox
      ✔ should get correct bbox for runs containing blanks (52ms)
      ✔ should get the advance width
      ✔ should get the glyph name
    CFF glyphs
      ✔ should get a CFFGlyph
      ✔ should get a path for the glyph as SVG
      ✔ should get a path for the glyph as function
      ✔ should get the glyph cbox
      ✔ should get the glyph bbox
      ✔ should get the glyph name
    CFF glyphs (CID font)
      ✔ should get a CFFGlyph
      ✔ should get a path for the glyph
      ✔ should get the glyph cbox
      ✔ should get the glyph bbox
      ✔ should get the correct fd index
    SBIX glyphs
      ✔ should get an SBIXGlyph
      ✔ should have an empty path
      ✔ should get an image
      ✔ should get the glyph name
    COLR glyphs
      ✔ should get an SBIXGlyph
      ✔ should get layers
      ✔ should get empty path
      ✔ should get bbox
      ✔ should get the glyph name
    WOFF ttf glyphs
      ✔ should get the glyph name
      ✔ should get a TTFGlyph
      ✔ should get a quadratic path for the glyph
    WOFF otf glyphs
      ✔ should get the glyph name
      ✔ should get a CFFGlyph
      ✔ should get a cubic path for the glyph
    WOFF2 ttf glyph
      ✔ should get the glyph name
      ✔ should get a WOFF2Glyph
      ✔ should get a path for the glyph
      ✔ should get a correct quadratic path for all contours
      ✔ should get the ttf glyph cbox
      ✔ should get the ttf glyph bbox
    WOFF2 otf glyph
      ✔ should get the glyph name
      ✔ should get a CFFGlyph
      ✔ should get a path for the glyph
      ✔ should get a correct cubic path for all contours
      ✔ should get the otf glyph cbox
      ✔ should get the otf glyph bbox

  i18n
    fontkit.setDefaultLanguage
      ✔ font has "en" metadata properties
      ✔ can set global default language to "ar"
      ✔ font now has "ar" metadata properties
      ✔ can reset default language back to "en"
    font.setDefaultLanguage
      ✔ font has "en" metadata properties
      ✔ can set font's default language to "ar"
      ✔ font now has "ar" metadata properties
      ✔ the font's language should not change when the global changes
      ✔ can reset default language back to "en"
    backup languages
      ✔ if the font's default language isn't found, use the global language
      ✔ if the global language isn't found, use "en"

  fontkit
    ✔ should open a font asynchronously
    ✔ should open a font synchronously
    ✔ should open fonts of different formats
    ✔ should open fonts lacking PostScript name
    ✔ should error when opening an invalid font asynchronously
    ✔ should error when opening an invalid font synchronously
    ✔ should get collection objects for ttc fonts
    ✔ should get collection objects for dfonts

  metadata
    ✔ has metadata properties
    ✔ exposes some metrics
    ✔ exposes tables directly

  opentype
    ✔ featureParams nameID of stylistic set should be 257
    ✔ featureParams version of stylistic set should be 0
    ✔ featureParams should be null of aalt opentype feature

  shaping
    general shaping tests
      ✔ should use correct script and language when features are not specified (46ms)
      ✔ should use specified left-to-right direction
    arabic shaper
      ✔ should shape Arabic text
      ✔ should handle cursive attachment positioning (67ms)
      ✔ should shape Mongolian text
      ✔ should shape Syriac text (38ms)
      ✔ should shape N'Ko text
      ✔ should shape Phags Pa text
      ✔ should attach marks to the first base of a multiple substitution (49ms)
      ✔ should adjust attached marks if base is adjusted
    hangul shaper
      ✔ should use composed versions if supported by the font
      ✔ should compose decomposed syllables if supported
      ✔ should use OT features for non-combining <L,V,T>
      ✔ should decompose <LV,T> to <L,V,T> if <LVT> is not supported
      ✔ should reorder tone marks to the beginning of <L,V> syllables
      ✔ should reorder tone marks to the beginning of <L,V,T> syllables
      ✔ should reorder tone marks to the beginning of <LV> syllables
      ✔ should reorder tone marks to the beginning of <LVT> syllables
      ✔ should insert a dotted circle for invalid tone marks
    indic shaper
      shapes Kannada text
        ✔ SHKNDA-1/1
        ✔ SHKNDA-1/2
        ✔ SHKNDA-1/3
        ✔ SHKNDA-1/4
        ✔ SHKNDA-1/5
        ✔ SHKNDA-1/6
        ✔ SHKNDA-1/7
        ✔ SHKNDA-1/8
        ✔ SHKNDA-1/9
        ✔ SHKNDA-1/10
        ✔ SHKNDA-1/11
        ✔ SHKNDA-1/12
        ✔ SHKNDA-1/13
        ✔ SHKNDA-1/14
        ✔ SHKNDA-1/15
        ✔ SHKNDA-1/16
        ✔ SHKNDA-1/17
        ✔ SHKNDA-1/18
        ✔ SHKNDA-1/19
        ✔ SHKNDA-1/20
        ✔ SHKNDA-1/21
        ✔ SHKNDA-1/22
        ✔ SHKNDA-1/23
        ✔ SHKNDA-1/24
        ✔ SHKNDA-1/25
        ✔ SHKNDA-1/26
        ✔ SHKNDA-1/27
        ✔ SHKNDA-1/28
        ✔ SHKNDA-1/29
        ✔ SHKNDA-1/30
        ✔ SHKNDA-1/31
        ✔ SHKNDA-1/32
        ✔ SHKNDA-1/33
        ✔ SHKNDA-1/34
        ✔ SHKNDA-2/1
        ✔ SHKNDA-2/2
        ✔ SHKNDA-2/3
        ✔ SHKNDA-2/4
        ✔ SHKNDA-2/5
        ✔ SHKNDA-2/6
        ✔ SHKNDA-2/7
        ✔ SHKNDA-2/8
        ✔ SHKNDA-2/9
        ✔ SHKNDA-2/10
        ✔ SHKNDA-2/11
        ✔ SHKNDA-2/12
        ✔ SHKNDA-2/13
        ✔ SHKNDA-2/14
        ✔ SHKNDA-2/15
        ✔ SHKNDA-2/16
        ✔ SHKNDA-3/1
        ✔ SHKNDA-3/2
        ✔ SHKNDA-3/3
        ✔ SHKNDA-3/4
        ✔ SHKNDA-3/5
        ✔ SHKNDA-3/6
        ✔ SHKNDA-3/7
        ✔ SHKNDA-3/8
        ✔ SHKNDA-3/9
        ✔ SHKNDA-3/10
        ✔ SHKNDA-3/11
        ✔ SHKNDA-3/12
        ✔ SHKNDA-3/13
        ✔ SHKNDA-3/14
        ✔ SHKNDA-3/15
        ✔ SHKNDA-3/16
        ✔ SHKNDA-3/17
        ✔ SHKNDA-3/18
        ✔ SHKNDA-3/19
        ✔ SHKNDA-3/20
        ✔ SHKNDA-3/21
        ✔ SHKNDA-3/22
        ✔ SHKNDA-3/23
        ✔ SHKNDA-3/24
        ✔ SHKNDA-3/25
        ✔ SHKNDA-3/26
        ✔ SHKNDA-3/27
        ✔ SHKNDA-3/28
        ✔ SHKNDA-3/29
        ✔ SHKNDA-3/30
        ✔ SHKNDA-3/31
      shapes Telugu text
        ✔ HB-TELU-1
        ✔ HB-TELU-2
        ✔ HB-TELU-3
        ✔ HB-TELU-4
        ✔ HB-TELU-5
        ✔ HB-TELU-6
        ✔ HB-TELU-7
        ✔ HB-TELU-8
        ✔ HB-TELU-9
        ✔ HB-TELU-10
        ✔ HB-TELU-11
        ✔ HB-TELU-12
      shapes Tamil text
        ✔ HB-TAML-1
        ✔ HB-TAML-2
        ✔ HB-TAML-3
        ✔ HB-TAML-4
        ✔ HB-TAML-5
        ✔ HB-TAML-6
        ✔ HB-TAML-7
        ✔ HB-TAML-8
        ✔ HB-TAML-9
        ✔ HB-TAML-10
        ✔ HB-TAML-11
        ✔ HB-TAML-12
        ✔ HB-TAML-13
        ✔ HB-TAML-14
        ✔ HB-TAML-15
        ✔ HB-TAML-16
        ✔ HB-TAML-17
        ✔ HB-TAML-18
        ✔ HB-TAML-19
        ✔ HB-TAML-20
        ✔ HB-TAML-21
        ✔ HB-TAML-22
        ✔ HB-TAML-23
        ✔ HB-TAML-24
        ✔ HB-TAML-25
        ✔ HB-TAML-26
        ✔ HB-TAML-27
        ✔ HB-TAML-28
        ✔ HB-TAML-29
        ✔ HB-TAML-30
        ✔ HB-TAML-31
        ✔ HB-TAML-32
        ✔ HB-TAML-33
        ✔ HB-TAML-34
        ✔ HB-TAML-35
        ✔ HB-TAML-36
        ✔ HB-TAML-37
        ✔ HB-TAML-38
        ✔ HB-TAML-39
        ✔ HB-TAML-40
        ✔ HB-TAML-41
        ✔ HB-TAML-42
        ✔ HB-TAML-43
      shapes Devanagari text
        joiners
          ✔ HB-DEVA-joiners-1
          ✔ HB-DEVA-joiners-2
          ✔ HB-DEVA-joiners-3
          ✔ HB-DEVA-joiners-4
          ✔ HB-DEVA-joiners-5
          ✔ HB-DEVA-joiners-6
          ✔ HB-DEVA-joiners-7
          ✔ HB-DEVA-joiners-8
          ✔ HB-DEVA-joiners-9
          ✔ HB-DEVA-joiners-10
          ✔ HB-DEVA-joiners-11
          ✔ HB-DEVA-joiners-12
          ✔ HB-DEVA-joiners-13
          ✔ HB-DEVA-joiners-14
          ✔ HB-DEVA-joiners-15
          ✔ HB-DEVA-joiners-16
          ✔ HB-DEVA-joiners-17
          ✔ HB-DEVA-joiners-18
          ✔ HB-DEVA-joiners-19
        misc
          ✔ HB-DEVA-misc-1
          ✔ HB-DEVA-misc-2
          ✔ HB-DEVA-misc-3
          ✔ HB-DEVA-misc-4
          ✔ HB-DEVA-misc-5
          ✔ HB-DEVA-misc-6
          ✔ HB-DEVA-misc-7
          ✔ HB-DEVA-misc-8
          ✔ HB-DEVA-misc-9
          ✔ HB-DEVA-misc-10
          ✔ HB-DEVA-misc-11
          ✔ HB-DEVA-misc-12
          ✔ HB-DEVA-misc-13
          ✔ HB-DEVA-misc-14
          ✔ HB-DEVA-misc-15
          ✔ HB-DEVA-misc-16
          ✔ HB-DEVA-misc-17
          ✔ HB-DEVA-misc-18
          ✔ HB-DEVA-misc-19
          ✔ HB-DEVA-misc-20
          ✔ HB-DEVA-misc-21
          ✔ HB-DEVA-misc-22
          ✔ HB-DEVA-misc-23
          ✔ HB-DEVA-misc-24
          ✔ HB-DEVA-misc-25
          ✔ HB-DEVA-misc-26
          ✔ HB-DEVA-misc-27
          ✔ HB-DEVA-misc-28
          ✔ HB-DEVA-misc-29
          ✔ HB-DEVA-misc-30
          ✔ HB-DEVA-misc-31
          ✔ HB-DEVA-misc-32
          ✔ HB-DEVA-misc-33
          ✔ HB-DEVA-misc-34
          ✔ HB-DEVA-misc-35
          ✔ HB-DEVA-misc-36
        dotted circle
          ✔ HB-DEVA-dottedcircle-1
          ✔ HB-DEVA-dottedcircle-2
          ✔ HB-DEVA-dottedcircle-3
          ✔ HB-DEVA-dottedcircle-4
          ✔ HB-DEVA-dottedcircle-5
          ✔ HB-DEVA-dottedcircle-6
          ✔ HB-DEVA-dottedcircle-7
          ✔ HB-DEVA-dottedcircle-8
        eyelash
          ✔ HB-DEVA-eyelash-1
          ✔ HB-DEVA-eyelash-2
          ✔ HB-DEVA-eyelash-3
      shapes Bengali text
        ✔ HB-BENG-1
        ✔ HB-BENG-2
        ✔ HB-BENG-3
        ✔ HB-BENG-4
        ✔ HB-BENG-5
        ✔ HB-BENG-6
        ✔ HB-BENG-7
        ✔ HB-BENG-8
        ✔ HB-BENG-9
        ✔ HB-BENG-10
        ✔ HB-BENG-11
        ✔ HB-BENG-12
        ✔ HB-BENG-13
        ✔ HB-BENG-14
        ✔ HB-BENG-15
        ✔ HB-BENG-16
        ✔ HB-BENG-17
        ✔ HB-BENG-18
        ✔ HB-BENG-19
        ✔ HB-BENG-20
        ✔ HB-BENG-21
        ✔ HB-BENG-22
        ✔ HB-BENG-23
        ✔ HB-BENG-24
        ✔ HB-BENG-25
        ✔ HB-BENG-26
        ✔ HB-BENG-27
        ✔ HB-BENG-28
        ✔ HB-BENG-29
        ✔ HB-BENG-30
        ✔ HB-BENG-31
        ✔ HB-BENG-32
        ✔ HB-BENG-33
        ✔ HB-BENG-34
        ✔ HB-BENG-35
        ✔ HB-BENG-36
        ✔ HB-BENG-37
        ✔ HB-BENG-38
        ✔ HB-BENG-39
        ✔ HB-BENG-40
        ✔ HB-BENG-41
        ✔ HB-BENG-42
        ✔ HB-BENG-43
        ✔ HB-BENG-44
        ✔ HB-BENG-45
        ✔ HB-BENG-46
        ✔ HB-BENG-47
        ✔ HB-BENG-48
        ✔ HB-BENG-49
        ✔ HB-BENG-50
        ✔ HB-BENG-51
        ✔ HB-BENG-52
        ✔ HB-BENG-53
      shapes Gurmukhi text
        ✔ HB-GURU-1
        ✔ HB-GURU-2
      shapes Gujarati text
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
        ✔ HB-GURU-1
      shapes Malayalam text
        ✔ HB-MLYM-1
        ✔ HB-MLYM-2
        ✔ HB-MLYM-3
        ✔ HB-MLYM-4
        ✔ HB-MLYM-5
        ✔ HB-MLYM-6
        ✔ HB-MLYM-7
        ✔ HB-MLYM-8
        ✔ HB-MLYM-9
        ✔ HB-MLYM-10
        ✔ HB-MLYM-11
        ✔ HB-MLYM-12
        ✔ HB-MLYM-13
        ✔ HB-MLYM-14
        ✔ HB-MLYM-15
        ✔ HB-MLYM-16
        ✔ HB-MLYM-17
        ✔ HB-MLYM-18
        ✔ HB-MLYM-19
        ✔ HB-MLYM-20
        ✔ HB-MLYM-21
        ✔ HB-MLYM-22
        ✔ HB-MLYM-23
        ✔ HB-MLYM-24
        ✔ HB-MLYM-25
        ✔ HB-MLYM-26
        ✔ HB-MLYM-27
        ✔ HB-MLYM-28
        ✔ HB-MLYM-29
        ✔ HB-MLYM-30
        ✔ HB-MLYM-31
        ✔ HB-MLYM-32
        ✔ HB-MLYM-33
        ✔ HB-MLYM-34
        ✔ HB-MLYM-35
        ✔ HB-MLYM-36
        ✔ HB-MLYM-37
        ✔ HB-MLYM-38
        ✔ HB-MLYM-39
        ✔ HB-MLYM-40
        ✔ HB-MLYM-41
        ✔ HB-MLYM-42
        ✔ HB-MLYM-43
        ✔ HB-MLYM-44
        ✔ HB-MLYM-45
        ✔ HB-MLYM-46
        ✔ HB-MLYM-47
        ✔ HB-MLYM-48
        ✔ HB-MLYM-49
        ✔ HB-MLYM-50
        ✔ HB-MLYM-51
        ✔ HB-MLYM-52
        ✔ HB-MLYM-53
        ✔ HB-MLYM-54
        ✔ HB-MLYM-55
        ✔ HB-MLYM-56
        ✔ HB-MLYM-57
        ✔ HB-MLYM-58
        ✔ HB-MLYM-59
        ✔ HB-MLYM-60
        ✔ HB-MLYM-61
        ✔ HB-MLYM-62
        ✔ HB-MLYM-63
        ✔ HB-MLYM-64
        ✔ HB-MLYM-65
      shapes Oriya text
        ✔ HB-ORYA-1
        ✔ HB-ORYA-2
        ✔ HB-ORYA-3
        ✔ HB-ORYA-4
        ✔ HB-ORYA-5
        ✔ HB-ORYA-6
        ✔ HB-ORYA-7
        ✔ HB-ORYA-8
      shapes Khmer text
        ✔ HB-KHMR-1
        ✔ HB-KHMR-2
        ✔ HB-KHMR-3
        ✔ HB-KHMR-4
        ✔ HB-KHMR-5
        ✔ HB-KHMR-6
        ✔ HB-KHMR-7
        ✔ HB-KHMR-8
        ✔ HB-KHMR-9
        ✔ HB-KHMR-10
        ✔ HB-KHMR-11
        ✔ HB-KHMR-12
        ✔ HB-KHMR-13
        ✔ HB-KHMR-14
        ✔ HB-KHMR-15
        ✔ HB-KHMR-16
        ✔ HB-KHMR-17
        ✔ HB-KHMR-18
        ✔ HB-KHMR-19
        ✔ HB-KHMR-20
        ✔ HB-KHMR-21
        ✔ HB-KHMR-22
        ✔ HB-KHMR-23
        ✔ decomposes split matras
    universal shaping engine
      shapes balinese text
        ✔ SHBALI-1/1
        ✔ SHBALI-1/2
        ✔ SHBALI-1/3
        ✔ SHBALI-1/4
        ✔ SHBALI-1/5
        ✔ SHBALI-1/6
        ✔ SHBALI-1/7
        ✔ SHBALI-1/8
        ✔ SHBALI-1/9
        ✔ SHBALI-1/10
        ✔ SHBALI-1/11
        ✔ SHBALI-1/12
        ✔ SHBALI-1/13
        ✔ SHBALI-1/14
        ✔ SHBALI-1/15
        ✔ SHBALI-1/16
        ✔ SHBALI-1/17
        ✔ SHBALI-1/18
        ✔ SHBALI-1/19
        ✔ SHBALI-1/20
        ✔ SHBALI-1/21
        ✔ SHBALI-1/22
        ✔ SHBALI-2/1
        ✔ SHBALI-2/2
        ✔ SHBALI-2/3
        ✔ SHBALI-2/4
        ✔ SHBALI-2/5
        ✔ SHBALI-2/6
        ✔ SHBALI-2/7
        ✔ SHBALI-2/8
        ✔ SHBALI-2/9
        ✔ SHBALI-2/10
        ✔ SHBALI-2/11
        ✔ SHBALI-2/12

  font subsetting
    truetype subsetting
      ✔ should produce a subset
      - should re-encode variation glyphs
      ✔ should handle composite glyphs
      ✔ should handle fonts with long index to location format (indexToLocFormat = 1)
    CFF subsetting
      ✔ should produce a subset
      ✔ should handle CID fonts (136ms)
      ✔ should produce a subset with asian punctuation corretly (54ms)

  variations
    Skia
      - should get available variation axes
      - should get named variation instances
      - should get a variation by name
      - should get a variation by settings
      - interpolates points without delta values
      - recomputes cbox and advance width
    truetype variations
      ✔ should support sharing all points
      ✔ should support sharing enumerated points
      ✔ should support sharing no points
      ✔ should use the HVAR table when available for variation metrics
      ✔ should fall back to the last entry in an HVAR table
      ✔ should support adjusting GPOS mark anchor points for variations
    CFF2 variations
      ✔ applies variations to CFF2 glyphs
      ✔ substitutes GSUB features depending on variations

  541 passing (1s)
  7 pending