Synthetic Bold and Slant
When a font family does not include a bold or italic face, the shaper can simulate these styles synthetically. The adjustments are applied during shaping — the resulting glyph positions already include the correct advances and origins.
Quick Start
shaper, _ := ot.NewShaper(font)
// Enable synthetic bold before shaping
shaper.SetSyntheticBold(0.02, 0.02, false)
buf := ot.NewBuffer()
buf.AddString("Bold text")
buf.GuessSegmentProperties()
shaper.Shape(buf, nil)
// buf.Pos now contains bold-adjusted positions
Synthetic Bold
SetSyntheticBold
func (s *Shaper) SetSyntheticBold(x, y float32, inPlace bool)Sets the embolden strength in em-units (fractions of units-per-em). Typical values range from 0.01 (subtle) to 0.05 (heavy).
| Parameter | Type | Description |
|---|---|---|
x |
float32 |
Horizontal embolden strength |
y |
float32 |
Vertical embolden strength |
inPlace |
bool |
If true, advances and origins stay unchanged |
Internally, the em-unit values are converted to font units: xStrength = round(upem * x). For a font with 1000 upem and x = 0.02, the horizontal strength is 20 font units.
Call SetSyntheticBold before Shape().
How Bold Affects Shaping
Horizontal text (inPlace = false): Each non-zero horizontal advance is widened by xStrength.
Vertical text (inPlace = false):
- Vertical advance (with vmtx): becomes larger (more negative) by
yStrength - Vertical origin X: recomputed as
(hAdvance + xStrength) / 2 + xStrength - Vertical origin Y: shifted by
yStrength
In-place mode (inPlace = true): Advances and origins are not modified. Only glyph extents and drawing outlines are affected — useful for rendering bolder glyphs without changing text layout.
Choosing Bold Values
| Desired Effect | Suggested Value | Notes |
|---|---|---|
| Semibold | 0.01 – 0.015 | Subtle thickening |
| Bold | 0.02 – 0.03 | Standard synthetic bold |
| Extra-bold | 0.04 – 0.05 | Heavy, use with care |
The x and y values do not have to be identical. Using a smaller y than x can produce a more natural look for some fonts.
SyntheticBold (getter)
func (s *Shaper) SyntheticBold() (x, y float32, inPlace bool)Synthetic Slant
SetSyntheticSlant
func (s *Shaper) SetSyntheticSlant(slant float32)Sets the shear factor for synthetic oblique. A value of 0.2 tilts glyphs by approximately 11.3° (atan(0.2)).
| Desired Effect | Suggested Value | Approximate Angle |
|---|---|---|
| Subtle oblique | 0.1 | ~5.7° |
| Standard italic | 0.2 | ~11.3° |
| Strong italic | 0.3 | ~16.7° |
The slant value is stored on the shaper for downstream rendering code:
slant := shaper.SyntheticSlant()
// Apply shear transform: [1, slant, 0, 1, 0, 0]
SyntheticSlant (getter)
func (s *Shaper) SyntheticSlant() float32Combining Bold and Slant
shaper.SetSyntheticBold(0.02, 0.02, false)
shaper.SetSyntheticSlant(0.2)
shaper.Shape(buf, nil)Both can be reset independently:
shaper.SetSyntheticBold(0, 0, false) // Reset bold
shaper.SetSyntheticSlant(0) // Reset slant
Settings persist on the shaper between Shape() calls. You can change them between calls to shape normal, bold, italic, and bold-italic text with the same shaper.
HarfBuzz Compatibility
| textshape | HarfBuzz C |
|---|---|
SetSyntheticBold(x, y, inPlace) |
hb_font_set_synthetic_bold(font, x, y, inPlace) |
SetSyntheticSlant(slant) |
hb_font_set_synthetic_slant(font, slant) |