skrifa/outline/autohint/latin/
mod.rsmod blues;
mod edges;
mod hint;
mod metrics;
mod segments;
mod widths;
use super::{
axis::Axis,
metrics::{Scale, UnscaledStyleMetrics},
outline::Outline,
style::{GlyphStyle, ScriptGroup},
};
pub(crate) use metrics::compute_unscaled_style_metrics;
fn derived_constant(units_per_em: i32, value: i32) -> i32 {
value * units_per_em / 2048
}
#[derive(Copy, Clone, PartialEq, Default, Debug)]
pub(crate) struct EdgeMetrics {
pub left_opos: i32,
pub left_pos: i32,
pub right_opos: i32,
pub right_pos: i32,
}
#[derive(Copy, Clone, PartialEq, Default, Debug)]
pub(crate) struct HintedMetrics {
pub x_scale: i32,
pub edge_metrics: Option<EdgeMetrics>,
}
pub(crate) fn hint_outline(
outline: &mut Outline,
metrics: &UnscaledStyleMetrics,
scale: &Scale,
glyph_style: Option<GlyphStyle>,
) -> HintedMetrics {
let scaled_metrics = metrics::scale_style_metrics(metrics, *scale);
let scale = &scaled_metrics.scale;
let mut axis = Axis::default();
let hint_top_to_bottom = metrics.style_class().script.hint_top_to_bottom;
outline.scale(&scaled_metrics.scale);
let mut hinted_metrics = HintedMetrics {
x_scale: scale.x_scale,
..Default::default()
};
let group = metrics.style_class().script.group;
if group == ScriptGroup::Default && scaled_metrics.axes[1].blues.is_empty() {
return hinted_metrics;
}
for dim in 0..2 {
if (dim == Axis::HORIZONTAL && scale.flags & Scale::NO_HORIZONTAL != 0)
|| (dim == Axis::VERTICAL && scale.flags & Scale::NO_VERTICAL != 0)
{
continue;
}
axis.reset(dim, outline.orientation);
segments::compute_segments(outline, &mut axis, group);
segments::link_segments(
outline,
&mut axis,
scaled_metrics.axes[dim].scale,
group,
metrics.axes[dim].max_width(),
);
edges::compute_edges(
&mut axis,
&scaled_metrics.axes[dim],
hint_top_to_bottom,
scaled_metrics.scale.y_scale,
group,
);
if dim == Axis::VERTICAL {
if group != ScriptGroup::Default
|| glyph_style
.map(|style| !style.is_non_base())
.unwrap_or(true)
{
edges::compute_blue_edges(
&mut axis,
scale,
&metrics.axes[dim].blues,
&scaled_metrics.axes[dim].blues,
group,
);
}
} else {
hinted_metrics.x_scale = scaled_metrics.axes[0].scale;
}
hint::hint_edges(
&mut axis,
&scaled_metrics.axes[dim],
group,
scale,
hint_top_to_bottom,
);
super::hint::align_edge_points(outline, &axis, group, scale);
super::hint::align_strong_points(outline, &mut axis);
super::hint::align_weak_points(outline, dim);
if dim == 0 && axis.edges.len() > 1 {
let left = axis.edges.first().unwrap();
let right = axis.edges.last().unwrap();
hinted_metrics.edge_metrics = Some(EdgeMetrics {
left_pos: left.pos,
left_opos: left.opos,
right_pos: right.pos,
right_opos: right.opos,
});
}
}
hinted_metrics
}