Fonts and faces#
A face represents a font file.
The Face is the following structure:
type Face struct {
FaceID int
HarfbuzzFont *harfbuzz.Font
UnitsPerEM int32
Cmap fonts.Cmap
Filename string
PostscriptName string
}
You need to register the glyphs that you put into the PDF file, since the font will be subsetted:
or
can be used.
Glyphs and code points#
There is no direct mapping between runes and glyph ids (code points) from the font. Take for example the “fi” ligature. Here the input string consists of two runes, however in most fonts this is a single code point.
To get the code point of a rune, use the Cmap from the face:
where face is a face instance. found
is true if there is a mapping from this rune to a glyph id. Similarly you can use
and
to get the code points of a rune (list).
Shaping#
In most cases you don't need to lookup the code point for a rune, as the built-in harfbuzz library takes care of the mapping from input strings to code points. This process is called shaping and can be called like this:
text := "Hello, world!"
buf := harfbuzz.NewBuffer()
buf.AddRunes([]rune(text), 0, -1)
buf.GuessSegmentProperties()
buf.Shape(f.Face.HarfbuzzFont, features)
here f is font object and features is a slice []harfbuzz.Feature
. After calling buf.Shape()
, buf.Info
is a slice in this format:
[]harfbuzz.GlyphInfo{
{Cluster:0, Glyph:0x3f, Mask:0x80000000},
{Cluster:1, Glyph:0x33, Mask:0x80000000},
{Cluster:2, Glyph:0x49, Mask:0x80000000},
{Cluster:3, Glyph:0x49, Mask:0x80000000},
{Cluster:4, Glyph:0x52, Mask:0x80000000},
{Cluster:5, Glyph:0x2e, Mask:0x80000000},
{Cluster:6, Glyph:0x68, Mask:0x80000000},
{Cluster:7, Glyph:0x73, Mask:0x80000000},
{Cluster:8, Glyph:0x52, Mask:0x80000001},
{Cluster:9, Glyph:0x61, Mask:0x80000000},
{Cluster:10, Glyph:0x49, Mask:0x80000000},
{Cluster:11, Glyph:0x30, Mask:0x80000000},
{Cluster:12, Glyph:0x36, Mask:0x80000000},
}
You can use these Glyph
entries for construction of the page content stream. To get positioning information, look at buf.Pos
:
[]harfbuzz.GlyphPosition{
{XAdvance:722, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:556, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:222, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:222, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:556, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:278, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:278, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:712, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:556, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:333, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:222, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:556, XOffset:0, YAdvance:0, YOffset:0},
{XAdvance:278, XOffset:0, YAdvance:0, YOffset:0},
}
This should be enough to position the glyphs in the PDF.
You can see an example at github.com/boxesandglue/boxesandglue-examples/tree/main/baseline/font.