/src/fontations/skrifa/src/outline/autohint/mod.rs
Line | Count | Source |
1 | | //! Runtime autohinting support. |
2 | | |
3 | | mod hint; |
4 | | mod instance; |
5 | | mod metrics; |
6 | | mod outline; |
7 | | mod recorder; |
8 | | mod shape; |
9 | | mod style; |
10 | | mod topo; |
11 | | |
12 | | pub use instance::GlyphStyles; |
13 | | pub(crate) use instance::Instance; |
14 | | pub use metrics::{ |
15 | | BlueZones, Scale, ScaleFlags, ScaledAxisMetrics, ScaledBlue, ScaledStyleMetrics, ScaledWidth, |
16 | | UnscaledAxisMetrics, UnscaledBlue, UnscaledStyleMetrics, WidthMetrics, |
17 | | }; |
18 | | pub use outline::Direction; |
19 | | pub use recorder::{EdgeAction, EdgeHint, HintAction, PointAction, PointHint}; |
20 | | pub use style::{GlyphStyle, ScriptClass, ScriptGroup, StyleClass}; |
21 | | pub use style::{SCRIPT_CLASSES, STYLE_CLASSES}; |
22 | | pub use topo::{Axis, BlueProvenance, Dimension, Edge, Segment, TopoFlags}; |
23 | | |
24 | | use crate::outline::{DrawError, Target}; |
25 | | use crate::{FontRef, MetadataProvider}; |
26 | | use alloc::vec::Vec; |
27 | | use raw::types::{F2Dot14, GlyphId}; |
28 | | |
29 | | /// Controls quirks for the different autohinters. |
30 | | #[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] |
31 | | enum QuirksMode { |
32 | | /// Just in time hinter; matches FreeType. |
33 | | #[default] |
34 | | Jit, |
35 | | /// Ahead of time hinter; matches ttfautohint. |
36 | | Aot, |
37 | | } |
38 | | |
39 | | /// Plan for hinting an outline. |
40 | | #[derive(Clone, Debug, Default)] |
41 | | pub struct HintPlan { |
42 | | hints: Vec<HintAction>, |
43 | | axes: [Option<Axis>; 2], |
44 | | } |
45 | | |
46 | | impl HintPlan { |
47 | | /// Creates a new hint plan. |
48 | 0 | pub fn new( |
49 | 0 | font: &FontRef, |
50 | 0 | coords: &[F2Dot14], |
51 | 0 | ppem: f32, |
52 | 0 | target: Target, |
53 | 0 | glyph_id: GlyphId, |
54 | 0 | glyph_style: GlyphStyle, |
55 | 0 | ) -> Result<Self, DrawError> { |
56 | 0 | let style_class = glyph_style |
57 | 0 | .style_class() |
58 | 0 | .ok_or(DrawError::GlyphNotFound(glyph_id))?; |
59 | 0 | let outline_glyph = font |
60 | 0 | .outline_glyphs() |
61 | 0 | .get(glyph_id) |
62 | 0 | .ok_or(DrawError::GlyphNotFound(glyph_id))?; |
63 | | |
64 | 0 | let shaper_mode = if cfg!(feature = "autohint_shaping") { |
65 | 0 | shape::ShaperMode::BestEffort |
66 | | } else { |
67 | 0 | shape::ShaperMode::Nominal |
68 | | }; |
69 | 0 | let shaper = shape::Shaper::new(font, shaper_mode); |
70 | 0 | let metrics = |
71 | 0 | metrics::compute_unscaled_style_metrics(&shaper, coords, style_class, QuirksMode::Aot); |
72 | | |
73 | 0 | let mut outline = outline::Outline::default(); |
74 | 0 | outline.fill(&outline_glyph, coords, QuirksMode::Aot)?; |
75 | | |
76 | 0 | let scale = metrics::Scale::new( |
77 | 0 | ppem, |
78 | 0 | outline_glyph.units_per_em() as i32, |
79 | 0 | font.attributes().style, |
80 | 0 | target, |
81 | 0 | metrics.style_class().script.group, |
82 | | ); |
83 | | |
84 | 0 | let mut recorder = recorder::HintsRecorder::default(); |
85 | 0 | let hinted_plan = hint::hint_outline_with_recorder( |
86 | 0 | &mut outline, |
87 | 0 | &metrics, |
88 | 0 | &scale, |
89 | 0 | Some(glyph_style), |
90 | 0 | &mut recorder, |
91 | | ); |
92 | | |
93 | 0 | Ok(Self { |
94 | 0 | hints: recorder.actions, |
95 | 0 | axes: hinted_plan.axes, |
96 | 0 | }) |
97 | 0 | } |
98 | | |
99 | | /// Returns the collection of hinting actions. |
100 | 0 | pub fn actions(&self) -> &[HintAction] { |
101 | 0 | &self.hints |
102 | 0 | } |
103 | | |
104 | | /// Returns the topological analysis of the horizontal axis. |
105 | 0 | pub fn horizontal_axis(&self) -> Option<&Axis> { |
106 | 0 | self.axes[Dimension::Horizontal].as_ref() |
107 | 0 | } |
108 | | |
109 | | /// Returns the topological analysis of the vertical axis. |
110 | 0 | pub fn vertical_axis(&self) -> Option<&Axis> { |
111 | 0 | self.axes[Dimension::Vertical].as_ref() |
112 | 0 | } |
113 | | } |
114 | | |
115 | | /// All constants are defined based on a UPEM of 2048. |
116 | | /// |
117 | | /// See <https://gitlab.freedesktop.org/freetype/freetype/-/blob/57617782464411201ce7bbc93b086c1b4d7d84a5/src/autofit/aflatin.h#L34> |
118 | 0 | fn derived_constant(units_per_em: i32, value: i32) -> i32 { |
119 | 0 | value * units_per_em / 2048 |
120 | 0 | } |