From 3dd7c8121c679719073b8f760accac3d176c7c15 Mon Sep 17 00:00:00 2001 From: Greg Pomerantz Date: Wed, 18 Dec 2019 13:00:38 -0500 Subject: [PATCH] font/opentype: add Collection type and methods The Collection type wraps sfnt.Collection and allows lazy-loading of fonts from SFNT collections. Signed-off-by: Greg Pomerantz --- font/opentype/opentype.go | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/font/opentype/opentype.go b/font/opentype/opentype.go index b1ba669d..58dd4366 100644 --- a/font/opentype/opentype.go +++ b/font/opentype/opentype.go @@ -5,6 +5,8 @@ package opentype import ( + "io" + "unicode" "unicode/utf8" @@ -23,6 +25,11 @@ type Font struct { buf sfnt.Buffer } +// Collection is a collection of one or more fonts. +type Collection struct { + coll *sfnt.Collection +} + type opentype struct { Font *sfnt.Font Hinting font.Hinting @@ -38,6 +45,46 @@ func Parse(src []byte) (*Font, error) { return &Font{font: fnt}, nil } +// ParseCollection parses an SFNT font collection, such as TTC or OTC data, +// from a []byte data source. +// +// If passed data for a single font, a TTF or OTF instead of a TTC or OTC, +// it will return a collection containing 1 font. +func ParseCollection(src []byte) (*Collection, error) { + c, err := sfnt.ParseCollection(src) + if err != nil { + return nil, err + } + return &Collection{c}, nil +} + +// ParseCollectionReaderAt parses an SFNT collection, such as TTC or OTC data, +// from an io.ReaderAt data source. +// +// If passed data for a single font, a TTF or OTF instead of a TTC or OTC, it +// will return a collection containing 1 font. +func ParseCollectionReaderAt(src io.ReaderAt) (*Collection, error) { + c, err := sfnt.ParseCollectionReaderAt(src) + if err != nil { + return nil, err + } + return &Collection{c}, nil +} + +// NumFonts returns the number of fonts in the collection. +func (c *Collection) NumFonts() int { + return c.coll.NumFonts() +} + +// Font returns the i'th font in the collection. +func (c *Collection) Font(i int) (*Font, error) { + fnt, err := c.coll.Font(i) + if err != nil { + return nil, err + } + return &Font{font: fnt}, nil +} + func (f *Font) Layout(ppem fixed.Int26_6, str string, opts text.LayoutOptions) *text.Layout { return layoutText(&f.buf, ppem, str, &opentype{Font: f.font, Hinting: font.HintingFull}, opts) }