skrifa/outline/autohint/
mod.rs1mod hint;
4mod instance;
5mod metrics;
6mod outline;
7mod recorder;
8mod shape;
9mod style;
10mod topo;
11
12pub use instance::GlyphStyles;
13pub(crate) use instance::Instance;
14pub use metrics::{
15 BlueZones, Scale, ScaleFlags, ScaledAxisMetrics, ScaledBlue, ScaledStyleMetrics, ScaledWidth,
16 UnscaledAxisMetrics, UnscaledBlue, UnscaledStyleMetrics, WidthMetrics,
17};
18pub use outline::Direction;
19pub use recorder::{EdgeAction, EdgeHint, HintAction, PointAction, PointHint};
20pub use style::{GlyphStyle, ScriptClass, ScriptGroup, StyleClass};
21pub use style::{SCRIPT_CLASSES, STYLE_CLASSES};
22pub use topo::{Axis, BlueProvenance, Dimension, Edge, Segment, TopoFlags};
23
24use crate::outline::{DrawError, Target};
25use crate::{FontRef, MetadataProvider};
26use alloc::vec::Vec;
27use raw::types::{F2Dot14, GlyphId};
28
29#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
31enum QuirksMode {
32 #[default]
34 Jit,
35 Aot,
37}
38
39#[derive(Clone, Debug, Default)]
41pub struct HintPlan {
42 hints: Vec<HintAction>,
43 axes: [Option<Axis>; 2],
44}
45
46impl HintPlan {
47 pub fn new(
49 font: &FontRef,
50 coords: &[F2Dot14],
51 ppem: f32,
52 target: Target,
53 glyph_id: GlyphId,
54 glyph_style: GlyphStyle,
55 ) -> Result<Self, DrawError> {
56 let style_class = glyph_style
57 .style_class()
58 .ok_or(DrawError::GlyphNotFound(glyph_id))?;
59 let outline_glyph = font
60 .outline_glyphs()
61 .get(glyph_id)
62 .ok_or(DrawError::GlyphNotFound(glyph_id))?;
63
64 let shaper_mode = if cfg!(feature = "autohint_shaping") {
65 shape::ShaperMode::BestEffort
66 } else {
67 shape::ShaperMode::Nominal
68 };
69 let shaper = shape::Shaper::new(font, shaper_mode);
70 let metrics =
71 metrics::compute_unscaled_style_metrics(&shaper, coords, style_class, QuirksMode::Aot);
72
73 let mut outline = outline::Outline::default();
74 outline.fill(&outline_glyph, coords, QuirksMode::Aot)?;
75
76 let scale = metrics::Scale::new(
77 ppem,
78 outline_glyph.units_per_em() as i32,
79 font.attributes().style,
80 target,
81 metrics.style_class().script.group,
82 );
83
84 let mut recorder = recorder::HintsRecorder::default();
85 let hinted_plan = hint::hint_outline_with_recorder(
86 &mut outline,
87 &metrics,
88 &scale,
89 Some(glyph_style),
90 &mut recorder,
91 );
92
93 Ok(Self {
94 hints: recorder.actions,
95 axes: hinted_plan.axes,
96 })
97 }
98
99 pub fn actions(&self) -> &[HintAction] {
101 &self.hints
102 }
103
104 pub fn horizontal_axis(&self) -> Option<&Axis> {
106 self.axes[Dimension::Horizontal].as_ref()
107 }
108
109 pub fn vertical_axis(&self) -> Option<&Axis> {
111 self.axes[Dimension::Vertical].as_ref()
112 }
113}
114
115fn derived_constant(units_per_em: i32, value: i32) -> i32 {
119 value * units_per_em / 2048
120}