stet_core/glyph_cache.rs
1// stet - A PostScript Interpreter
2// Copyright (c) 2026 Scott Bowman
3// SPDX-License-Identifier: Apache-2.0 OR MIT
4
5//! Glyph path cache: caches charstring interpretation results per font.
6//!
7//! Stores glyph outlines in charstring coordinates (pre-FontMatrix, pre-CTM).
8//! One cache entry per glyph per font, regardless of size/orientation.
9//! FontMatrix and CTM transforms are still applied per-render.
10
11use crate::display_list::DisplayElement;
12use crate::graphics_state::PathSegment;
13use crate::object::{EntityId, NameId};
14use rustc_hash::FxHashMap;
15use std::sync::Arc;
16
17/// Cached glyph outline + width in charstring coordinates.
18#[derive(Clone)]
19pub struct CachedGlyph {
20 pub segments: Arc<Vec<PathSegment>>,
21 pub width_x: f64,
22 pub width_y: f64,
23}
24
25/// Cached Type 3 glyph: display list elements + origin for translation.
26#[derive(Clone)]
27pub struct CachedType3Glyph {
28 pub elements: Vec<DisplayElement>,
29 pub origin_dev_x: f64,
30 pub origin_dev_y: f64,
31 pub width: (f64, f64),
32}
33
34/// Cache mode set by setcachedevice/setcharwidth during Type 3 BuildChar.
35#[derive(Clone, Copy, PartialEq, Eq)]
36pub enum Type3CacheMode {
37 /// setcachedevice was called — glyph is cacheable.
38 Cache,
39 /// setcharwidth was called — glyph is not cacheable (may use color ops).
40 NoCache,
41}
42
43/// Per-font glyph path cache.
44#[derive(Default)]
45pub struct GlyphCache {
46 /// Type 1 and CFF glyphs keyed by glyph name.
47 pub by_name: FxHashMap<NameId, CachedGlyph>,
48 /// CIDFont glyphs keyed by CID.
49 pub by_cid: FxHashMap<i32, CachedGlyph>,
50 /// TrueType glyphs keyed by glyph ID.
51 pub by_gid: FxHashMap<u16, CachedGlyph>,
52 /// Type 3 glyphs keyed by char code (only setcachedevice glyphs).
53 pub by_charcode: FxHashMap<u8, CachedType3Glyph>,
54 /// Type 3 glyphs keyed by glyph name (only setcachedevice glyphs).
55 ///
56 /// Separate from [`Self::by_charcode`] because `glyphshow` bypasses the
57 /// font's `Encoding` and can therefore name a glyph that no character code
58 /// maps to — such a glyph has no code to key on.
59 pub by_type3_name: FxHashMap<NameId, CachedType3Glyph>,
60}
61
62impl GlyphCache {
63 pub fn new() -> Self {
64 Self {
65 by_name: FxHashMap::default(),
66 by_cid: FxHashMap::default(),
67 by_gid: FxHashMap::default(),
68 by_charcode: FxHashMap::default(),
69 by_type3_name: FxHashMap::default(),
70 }
71 }
72}
73
74/// Get or create the glyph cache for a font entity.
75#[inline]
76pub fn get_or_create_cache(
77 caches: &mut FxHashMap<EntityId, GlyphCache>,
78 font_entity: EntityId,
79) -> &mut GlyphCache {
80 caches.entry(font_entity).or_default()
81}