The only place allowed to call doc.text() directly (a facade pattern, per decision) —
every block must draw text through this instead, so normalizeText is always guaranteed
regardless of whether the caller remembered to normalize beforehand (defense-in-depth at
the boundary) + fails fast if Thai text is about to be drawn with a built-in font that has no Thai glyphs
The only place allowed to call doc.text() directly (a facade pattern, per decision) — every block must draw text through this instead, so normalizeText is always guaranteed regardless of whether the caller remembered to normalize beforehand (defense-in-depth at the boundary) + fails fast if Thai text is about to be drawn with a built-in font that has no Thai glyphs