fontfind

package module
v0.0.0-...-c8481c4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 12, 2026 License: BSD-3-Clause Imports: 11 Imported by: 0

README

fontfind

fontfind is a Go package for discovering and loading scalable fonts from multiple sources.

The package is built around one practical goal: given a font request (family pattern, style, weight), return a usable font resource that can be loaded as bytes. Resolution is provider-based and can combine:

  • embedded fallback fonts
  • local/system fonts
  • Google Fonts (with local caching)

Clients may bring their own font-search providers, which must be of function type locate.FontLocator.

The resolver pipeline is cache-backed (see sub-package fontregistry) and designed so callers can still receive a fallback font object even when the requested font cannot be found.

Installation

go get github.com/npillmayer/fontfind

API Overview

Core types (package fontfind)
  • Descriptor: describes a requested font (Pattern, Style, Weight)
  • ScalableFont: describes a resolved font variant and where to load it from
  • NullFont: zero-value marker used for unresolved results
  • FallbackFont(): returns packaged default fallback (Go-Regular.otf)

ScalableFont is a container for the location of the font's binary data. It is not to be used as a font directly, but rather holds the information how the binary font data may be obtained. ScalableFont properties/methods are:

  • Name
  • ReadFontData() ([]byte, error) // clients use this to load font data
  • Path() string
  • SetFS(fs fs.FS, path string) // used by the resolver pipeline
Resolution API (package locate)
  • ResolveFontLoc(desc, resolvers...) FontPromise
  • ResolveFontLocWithContext(ctx, desc, resolvers...) FontPromise

FontPromise:

  • Font() (fontfind.ScalableFont, error)
  • FontWithContext(ctx) (fontfind.ScalableFont, error)

Custom pipeline API:

  • type locate.FontRegistry
  • type locate.ResolverPipeline
  • locate.NewResolverPipeline(reg, resolvers...)
  • (ResolverPipeline).Resolve(ctx, desc)

Resolution behavior:

  1. Normalize descriptor to registry key.
  2. Try registry cache (fontregistry.GlobalRegistry().GetFont).
  3. Run resolvers in provided order on cache miss.
  4. Cache successful hits.
  5. Return registry fallback font with an error if all resolvers fail.

By default, ResolveFontLoc* uses the global registry singleton. If you need per-client cache isolation, build a pipeline with your own registry.

Resolver providers
  • locate/fallbackfont: embedded packaged fonts (Find, Default)
  • locate/systemfont: local/system lookup (Find, FindLocalFont)
  • locate/googlefont: Google Fonts lookup + cache (Find, FindGoogleFont)

See the documentation in the sub-packages for more details.

Examples

1. General app font resolution

This example will search for: system fonts -> embedded fallback fonts, i.e. Go fonts.

desc := fontfind.Descriptor{
	Pattern: "Noto Sans",
	Style:   font.StyleNormal,
	Weight:  font.WeightNormal,
}

system := systemfont.Find("myapp", USE_SYSTEM_IO)
fallback := fallbackfont.Find()

promise := locate.ResolveFontLoc(desc, system, fallback)
// …
font, err := promise.Font()
if err != nil {
	// err may be non-nil while font is still a usable fallback font
	log.Printf("font lookup degraded: %v", err)
}

data, err := font.ReadFontData()
if err != nil {
	log.Fatal(err)
}
fmt.Printf("resolved %s (%s), %d bytes\n", sf.Name, sf.Path(), len(data))
2. Timeout-aware async resolution

Use a context-aware resolver and wait with cancellation/deadline control.

desc := fontfind.Descriptor{
	Pattern: "Any",
	Style:   font.StyleNormal,
	Weight:  font.WeightNormal,
}

myLongRunningResolver := …   // client-provided resolver

ctx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond)
defer cancel()

promise := locate.ResolveFontLocWithContext(ctx, desc, myLongRunningResolver)
_, err := promise.FontWithContext(ctx)
fmt.Println("result:", err) // context deadline exceeded
3. Client-owned registry (cache isolation)
type myRegistry struct { /* implement locate.FontRegistry */ }

reg := &myRegistry{}
pipeline := locate.NewResolverPipeline(reg, systemResolver, fallbackResolver)
sf, err := pipeline.Resolve(context.Background(), desc).Font()
4. Embedded-only/offline deployments

For fully offline systems, use only the fallback resolver:

desc := fontfind.Descriptor{
	Pattern: "Go",
	Style: font.StyleNormal,
	Weight: font.WeightNormal
}
promise := locate.ResolveFontLoc(desc, fallbackfont.Find())
font, err := promise.Font()

This will return a packaged Go font.

Notes

  • Google Fonts access requires a valid Google API key (GOOGLE_FONTS_API_KEY) for live directory fetches.
  • TTC (*.ttc) handling is not yet implemented.

License

BSD 3-Clause. See LICENSE file in the top-level directory.

Documentation

Overview

Package fontfind is for typeface and font finding and loading.

There is a certain confusion with the nomenclature of typesetting. We will stick to the following definitions:

▪︎ A "typeface" is a family of fonts. An example is "Helvetica". This corresponds to a TrueType "collection" (*.ttc).

▪︎ A "scalable font" is a font, i.e. a variant of a typeface with a certain weight, slant, etc. An example is "Helvetica regular".

▪︎ A "typecase" is a scaled font, i.e. a font in a certain size for a certain script and language. The name is reminiscend on the wooden boxes of typesetters in the era of metal type. An example is "Helvetica regular 11pt, Latin, en_US".

Please note that Go (Golang) does use the terms "font" and "face" differently–actually more or less in an opposite manner.

Status

Does not yet contain methods for font collections (*.ttc), e.g., /System/Library/Fonts/Helvetica.ttc on Mac OS.

License

Governed by a 3-Clause BSD license. License file may be found in the root folder of this module.

Copyright © Norbert Pillmayer <norbert@pillmayer.com>

Index

Constants

View Source
const (
	StyleNormal = font.StyleNormal
	StyleItalic = font.StyleItalic
)
View Source
const (
	WeightLight    = font.WeightLight
	WeightNormal   = font.WeightNormal
	WeightSemiBold = font.WeightSemiBold
	WeightBold     = font.WeightBold
)

Variables

View Source
var NullFont = ScalableFont{}

NullFont is the zero-value marker used when no scalable font could be resolved.

View Source
var PtIn fixed.Int26_6 = fixed.I(72) + fixed.I(27)/100

PtIn is 72.27, i.e. printer's points per inch.

Functions

func ClosestMatch

func ClosestMatch(fdescs []FontVariantsLocation, pattern string, style font.Style,
	weight font.Weight) (match FontVariantsLocation, variant string, confidence MatchConfidence)

ClosestMatch scans a list of font descriptors and returns the closest match for a given set of parameters.

If no variant matches, returns `NoConfidence`.

func GuessStyleAndWeight

func GuessStyleAndWeight(fontfilename string) (font.Style, font.Weight)

GuessStyleAndWeight tries to guess a font's style and weight from the font's file name.

func Matches

func Matches(fontfilename, pattern string, style font.Style, weight font.Weight) bool

Matches returns true if a font's filename contains pattern and indicators for a given style and weight.

func PpEm

func PpEm(ptSize fixed.Int26_6, dpi float32) fixed.Int26_6

PpEm calculates a ppem value for a given font point-size and an output resolution (dpi).

func RasterCoords

func RasterCoords(u sfnt.Units, sfont *sfnt.Font, ptSize fixed.Int26_6, dpi float32) fixed.Int26_6

RasterCoords transforms `u`, a value in font-units, into pixel coordinates. Calculation is done for a font `sfont` at a given point-size `ptSize`.

Types

type Descriptor

type Descriptor struct {
	Pattern string
	Style   font.Style
	Weight  font.Weight
}

Descriptor describes a requested scalable font by family pattern, style, and weight.

type FontVariantsLocation

type FontVariantsLocation struct {
	Family   string   `json:"family"`
	Variants []string `json:"variants"`
	Path     string   // used for local font sources
}

FontVariantsLocation describes known variants and location info for a font family.

type MatchConfidence

type MatchConfidence int

MatchConfidence is a type for expressing the confidence level of font matching.

const (
	NoConfidence      MatchConfidence = 0
	LowConfidence     MatchConfidence = 2
	HighConfidence    MatchConfidence = 3
	PerfectConfidence MatchConfidence = 4
)

func MatchStyle

func MatchStyle(variantName string, style font.Style) MatchConfidence

MatchStyle tries to match a font-variant to a given style.

func MatchWeight

func MatchWeight(variantName string, weight font.Weight) MatchConfidence

MatchWeight tries to match a font-variant to a given weight.

type ScalableFont

type ScalableFont struct {
	Name   string
	Style  font.Style
	Weight font.Weight
	// contains filtered or unexported fields
}

ScalableFont describes a concrete font variant and where to load it from.

func FallbackFont

func FallbackFont() ScalableFont

FallbackFont returns the default packaged fallback font.

func (*ScalableFont) Path

func (f *ScalableFont) Path() string

Path returns the path of the font file inside the configured file-system.

func (*ScalableFont) ReadFontData

func (f *ScalableFont) ReadFontData() ([]byte, error)

ReadFontData reads the raw bytes of this scalable font from its configured file-system.

func (*ScalableFont) SetFS

func (f *ScalableFont) SetFS(fs fs.FS, path string)

SetFS sets file-system and path for loading font bytes.

Directories

Path Synopsis
Package fontregistry manages a registry for loaded fonts.
Package fontregistry manages a registry for loaded fonts.
Package locate defines resolver function types and async font resolution helpers.
Package locate defines resolver function types and async font resolution helpers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL