Skip to content
unidocPublic
forked from tdewolff/font

About

Go library for SFNT-based fonts (TTF, OTF, WOFF, WOFF2, EOT). UniDoc's fork of tdewolff/font.

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Latest commit

 

History

217 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Font API reference

UniDoc's fork of tdewolff/font by Taco de Wolff (MIT, license unchanged), maintained for our own use, mainly WOFF/WOFF2 decoding. Differences from upstream:

  • WOFF2 fonts with bit 11 of head.flags clear are accepted instead of rejected.
  • Requires Go 1.25; the examples/glyphs example is removed.
  • Upstream's AI-agent instruction files are removed.

See NOTICE for details.

This fork is maintained for UniDoc's own needs, with no support or stability guarantees, and may be changed, archived or removed at any time. For general use, we recommend upstream.

Parsers for SFNT-based fonts (TTF, OTF, WOFF, WOFF2, EOT) that can extract glyph paths, advancement and kerning data, Unicode mapping and glyph lookups. It also supports merging two fonts as well as subsetting fonts using a list of glyphs. It can write out TTF/OTF as well as WOFF2 fonts. The WOFF and WOFF2 converters have been testing using the validation tests from the W3C (https://github.com/w3c/woff/tree/master/woff1/tests and https://github.com/w3c/woff2-tests).

fontcmd: font toolkit that can select a subset of glyphs from a font, merge fonts, or show font information and display glyphs in the command line or as a raster image.

Usage

Parse font

import "github.com/unidoc/font"

// Can be any of TTF, OTF, TTC, WOFF, WOFF2, or EOT
fontBytes, err := os.ReadFile("DejaVuSerif.otf")
if err != nil {
    panic(err)
}

sfnt, err := font.ParseSFNT(fontBytes, 0) // 0 is the first index for TTC fonts
if err != nil {
    panic(err)
}

// font information
sfnt.NumGlyphs() uint16
sfnt.UnitsPerEm() uint16
sfnt.VerticalMetrics() (uint16, uint16, uint16)

// glyph mappings
sfnt.GlyphIndex(r rune) uint16
sfnt.GlyphToUnicode(glyphID uint16) []rune
sfnt.GlyphName(glyphID uint16) string
sfnt.FindGlyphName(name string) uint16

// glyph shapes
sfnt.GlyphPath(p Pather, glyphID, ppem uint16, x, y, scale float64, hinting Hinting) error
sfnt.GlyphBounds(glyphID uint16) (int16, int16, int16, int16)
sfnt.GlyphAdvance(glyphID uint16) uint16
sfnt.GlyphVerticalAdvance(glyphID uint16) uint16
sfnt.Kerning(left, right uint16) int16

// editting
sfnt.SetGlyphNames(names []string) error
sfnt.Merge(sfnt *SFNT, options MergeOptions) error
sfnt.Subset(glyphIDs []uint16, options SubsetOptions) (*SFNT, error)
sfnt.Write() []byte
sfnt.WriteWOFF2() ([]byte, error)
import "github.com/unidoc/font"

// Load two fonts
fontBytes, err := os.ReadFile("DejaVuSerif.otf")
if err != nil {
    panic(err)
}
font2Bytes, err := os.ReadFile("DejaVuSerif-Extended.otf")
if err != nil {
    panic(err)
}

sfnt, err := font.ParseSFNT(fontBytes, 0)
if err != nil {
    panic(err)
}
sfnt2, err := font.ParseSFNT(font2Bytes, 0)
if err != nil {
    panic(err)
}

// Add all glyphs of the second font to the first
options := font.MergeOptions{
    RearrangeCmap: false, // don't rewrite unicode mapping to sequential order
}
if err := sfnt.Merge(sfnt2, options); err != nil {
    panic(err)
}

if err := os.WriteFile("DejaVuSerif-Merged.otf", sfnt.Write(), 0644); err != nil{
    panic(err)
}
import "github.com/unidoc/font"

fontBytes, err := os.ReadFile("DejaVuSerif.otf")
if err != nil {
    panic(err)
}

sfnt, err := font.ParseSFNT(fontBytes, 0)
if err != nil {
    panic(err)
}

var glyphIDs []uint16
for c := 'A'; c <= 'Z'; c++ {
    if glyphID := sfnt.GlyphIndex(c); glyphID != 0 {
        glyphIDs = append(glyphIDs, glyphID)
    }
}

// Create subset
options := font.SubsetOptions{
    Tables: font.KeepMinTables, // keep only required tables
}
sfntSubset, err := sfnt.Subset(glyphIDs, options)
if err != nil {
    panic(err)
}

if err := os.WriteFile("DejaVuSerif-Subset.otf", sfntSubset.Write(), 0644); err != nil{
    panic(err)
}

380132 bytes => 6700 bytes (1.7%)

Convert to TTF/OTF

import "github.com/unidoc/font"

// Can be any of TTF, OTF, TTC, WOFF, WOFF2, or EOT
fontBytes, err := os.ReadFile("DejaVuSerif.woff")
if err != nil {
    panic(err)
}

// []byte to []byte
sfnt, err := font.ToSFNT(fontBytes)
if err != nil {
    panic(err)
}

ext := font.Extension(sfnt) // .ttf or .otf
if err := os.WriteFile("DejaVuSerif"+ext, sfnt, 0644); err != nil{
    panic(err)
}

License

Released under the MIT license.

About

Go library for SFNT-based fonts (TTF, OTF, WOFF, WOFF2, EOT). UniDoc's fork of tdewolff/font.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages