+TypeScript example
Glyphs share font and size, but retain their own letter and position. Separating those values permits style reuse without mixing one placement’s data into another.
// Put only immutable, shareable values in the style object.
class GlyphStyle {
constructor(readonly font: string, readonly size: number) { Object.freeze(this); }
}
type PlacedGlyph = Readonly<{ letter: string; x: number; style: GlyphStyle }>;
// Reuse the object for the same key instead of constructing a style per placement.
class StylePool {
private readonly fonts = new Map<string, Map<number, GlyphStyle>>();
get(font: string, size: number): GlyphStyle {
let sizes = this.fonts.get(font);
if (!sizes) { sizes = new Map(); this.fonts.set(font, sizes); }
let style = sizes.get(size);
if (!style) { style = new GlyphStyle(font, size); sizes.set(size, style); }
return style;
}
get count(): number { return [...this.fonts.values()].reduce((n, sizes) => n + sizes.size, 0); }
}
const pool = new StylePool();
const letters: PlacedGlyph[] = [
{ letter: "A", x: 0, style: pool.get("Serif", 16) },
{ letter: "B", x: 20, style: pool.get("Serif", 16) },
];
for (const glyph of letters) console.log(glyph.letter + "@" + glyph.x);
console.log("styles: " + pool.count);
A@0
B@20
styles: 1
Object.freeze keeps the shared style immutable, and the pool looks up both font and size. Retention and size limits are separate policies omitted from this example.