theme/font/registry.go
Functions
func FaceCount
func (r *Registry) FaceCount(familyName string) int {
r.mu.RLock()
defer r.mu.RUnlock()
entry, ok := r.families[familyName]
if !ok {
return 0
}
return len(entry.faces)
}
func FamilyNames
FamilyNames returns a sorted list of all registered family names.
func (r *Registry) FamilyNames() []string {
r.mu.RLock()
defer r.mu.RUnlock()
names := make([]string, 0, len(r.families))
for name := range r.families {
names = append(names, name)
}
sort.Strings(names)
return names
}
func HasFamily
HasFamily reports whether the given family name is registered.
func (r *Registry) HasFamily(familyName string) bool {
r.mu.RLock()
defer r.mu.RUnlock()
_, ok := r.families[familyName]
return ok
}
func NewRegistry
NewRegistry creates an empty font registry.
func NewRegistry() *Registry {
return &Registry{
families: make(map[string]*familyEntry),
}
}
func RegisterFamily
RegisterFamily registers all faces of a font family.
If the family already exists, new faces are appended. If a face with the
same weight and style already exists, it is replaced.
func (r *Registry) RegisterFamily(family Family) {
r.mu.Lock()
defer r.mu.Unlock()
entry, ok := r.families[family.Name]
if !ok {
entry = &familyEntry{name: family.Name}
r.families[family.Name] = entry
}
for _, face := range family.Faces {
r.addFaceLocked(entry, face)
}
}
func Resolve
Resolve finds the best matching font data for the given family, weight, and style.
Resolution follows the CSS font-matching algorithm
(https://www.w3.org/TR/css-fonts-4/#font-style-matching):
1. Look for an exact weight+style match.
2. If the requested style is Italic and no italic face exists, fall back to Normal style.
3. Apply CSS weight resolution: for weights <= 500, try lighter first then heavier;
for weights > 500, try heavier first then lighter.
Returns the font data and true if a match was found, or nil and false if the
family does not exist or has no faces.
func (r *Registry) Resolve(familyName string, weight Weight, style Style) ([]byte, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
entry, ok := r.families[familyName]
if !ok || len(entry.faces) == 0 {
return nil, false
}
// Try exact match first.
if data := findExact(entry.faces, weight, style); data != nil {
return data, true
}
// If italic requested but not available, fall back to normal style.
searchStyle := style
if style == Italic {
if !hasStyle(entry.faces, Italic) {
searchStyle = Normal
}
}
// Try exact weight with resolved style.
if searchStyle != style {
if data := findExact(entry.faces, weight, searchStyle); data != nil {
return data, true
}
}
// CSS weight resolution with the resolved style.
if data := resolveWeight(entry.faces, weight, searchStyle); data != nil {
return data, true
}
// Last resort: any face in the family.
return entry.faces[0].Data, true
}
Structs
type Registry struct
Registry manages font families and resolves font face requests to font data.
The registry maps family+weight+style combinations to raw font data. When an
exact match is not available, it uses the CSS font-matching algorithm to find
the closest available weight within the requested style.
Registry is safe for concurrent use. It uses a read-write mutex optimized
for read-heavy workloads (font resolution is far more frequent than
registration).
type Registry struct {
mu sync.RWMutex
families map[string]*familyEntry
}
FaceCount returns the number of registered faces for the given family,
or 0 if the family is not registered.