Fonts and font families

Fonts and font families

Font families

A font family is a collection of faces that appear in different font weight and styles:

type FontFamily struct {
	Name string
	ID   int
}

You can add faces to the font family:

func (ff *FontFamily) AddMember(fontsource *FontSource, weight FontWeight, style FontStyle) error

where the font source is:

type FontSource struct {
	VariationSettings map[string]float64 // axis tag -> value (e.g., "wght" -> 700)
	Name         string
	Location     string
	FontFeatures []string
	Data         []byte
	SizeAdjust   float64 // 1 - SizeAdjust is the relative adjustment.
	// The sub font index within the font file.
	Index int
	// Metrics, when set, replaces the face's own vertical metrics, as CSS's
	// ascent-override, descent-override and line-gap-override do.
	Metrics *MetricsOverride
	// Slant shears the face into an oblique, as the tangent of the angle
	// (see font.Font.Slant). GetFontSource sets it to SyntheticSlant on the
	// copy of an upright it makes for a missing italic.
	Slant float64
}

and the weight is a number between 100 and 900 or a predefined name FontWeight100, FontWeight200, …, FontWeight900 and the style is FontStyleNormal, FontStyleItalic or FontStyleOblique.

You can retrieve a font source with

func (ff *FontFamily) GetFontSource(weight FontWeight, style FontStyle) (*FontSource, error)

which will give you the closest match.

Missing italics

A family without an italic or oblique face uses its upright face for them. With style synthesis on, the upright face is slanted by SyntheticSlant (tan 12°) instead, as browsers do with font-synthesis-style: auto. It is off by default:

func (ff *FontFamily) SetSynthesizeStyle(on bool)

A text overrides the family’s default with SettingSynthesizeStyle. The slant ends up in the font source’s Slant and is written to the PDF as a shear of the text matrix, so the glyphs keep their widths.

Vertical metrics

A face’s ascent, descent and line gap come from its hhea table. The font source’s Metrics replaces them, as CSS’s ascent-override, descent-override and line-gap-override do. The values are fractions of the em, and a negative one keeps the face’s own value:

type MetricsOverride struct {
	Ascent, Descent, LineGap float64
}
ff.AddMember(&frontend.FontSource{
	Location: "fonts/CrimsonPro-Regular.ttf",
	Metrics:  &frontend.MetricsOverride{Ascent: 0.9, Descent: 0.25, LineGap: -1},
}, frontend.FontWeight400, frontend.FontStyleNormal)

The line breaker’s own line spacing does not read these metrics. They are there for a LineModel (see Linebreaking), which finds each glyph’s font, with its metrics, on the line.

Converting font weight and style from string

To get a font weight or a font style from a string you can use these two functions:

func ResolveFontWeight(fw string, inheritedValue FontWeight) FontWeight
func ResolveFontStyle(fs string) FontStyle

The inherited value for the font weight is used when the string is “bolder”.