theme/font/registry.go

Functions Structs

Functions

func FaceCount

FaceCount returns the number of registered faces for the given family,

or 0 if the family is not registered.

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
}