mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-28 03:37:00 -06:00
108 lines
3.4 KiB
Rust
108 lines
3.4 KiB
Rust
//! OpenType feature selection (the OpenType panel), resolved per character style.
|
|
|
|
use drawcraft_doc::CharStyle;
|
|
use harfrust::{Feature, Tag};
|
|
|
|
/// OpenType features applied during shaping. Kerning, `case` and ligature suppression are driven
|
|
/// by the character style (`kerning`, `all_caps`, `tracking`); the rest are layout-wide options.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
pub struct OtFeatures {
|
|
/// Standard ligatures (`liga`, `clig`). Suppressed automatically when tracking is non-zero.
|
|
pub ligatures: bool,
|
|
/// Contextual alternates (`calt`).
|
|
pub contextual: bool,
|
|
/// Discretionary ligatures (`dlig`).
|
|
pub discretionary_ligatures: bool,
|
|
/// Small capitals (`smcp`).
|
|
pub small_caps: bool,
|
|
/// Diagonal fractions (`frac`).
|
|
pub fractions: bool,
|
|
/// Oldstyle figures (`onum`).
|
|
pub oldstyle_figures: bool,
|
|
/// Tabular figures (`tnum`).
|
|
pub tabular_figures: bool,
|
|
/// Ordinals (`ordn`).
|
|
pub ordinals: bool,
|
|
/// Swashes (`swsh`).
|
|
pub swash: bool,
|
|
}
|
|
|
|
impl Default for OtFeatures {
|
|
fn default() -> Self {
|
|
Self {
|
|
ligatures: true,
|
|
contextual: true,
|
|
discretionary_ligatures: false,
|
|
small_caps: false,
|
|
fractions: false,
|
|
oldstyle_figures: false,
|
|
tabular_figures: false,
|
|
ordinals: false,
|
|
swash: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f(tag: &[u8; 4], on: bool) -> Feature {
|
|
Feature::new(Tag::new(tag), on as u32, ..)
|
|
}
|
|
|
|
impl OtFeatures {
|
|
/// Parse a feature list like `["dlig", "smcp", "-liga"]` (unknown tags are ignored).
|
|
pub fn from_tags<'a>(tags: impl IntoIterator<Item = &'a str>) -> Self {
|
|
let mut o = Self::default();
|
|
for t in tags {
|
|
let (on, t) = match t.strip_prefix('-') {
|
|
Some(r) => (false, r),
|
|
None => (true, t.strip_prefix('+').unwrap_or(t)),
|
|
};
|
|
match t {
|
|
"liga" => o.ligatures = on,
|
|
"calt" => o.contextual = on,
|
|
"dlig" => o.discretionary_ligatures = on,
|
|
"smcp" => o.small_caps = on,
|
|
"frac" => o.fractions = on,
|
|
"onum" => o.oldstyle_figures = on,
|
|
"tnum" => o.tabular_figures = on,
|
|
"ordn" => o.ordinals = on,
|
|
"swsh" => o.swash = on,
|
|
_ => {}
|
|
}
|
|
}
|
|
o
|
|
}
|
|
|
|
/// The harfrust features for text in style `st`.
|
|
pub(crate) fn resolve(&self, st: &CharStyle) -> Vec<Feature> {
|
|
let mut v = Vec::with_capacity(8);
|
|
if st.kerning.is_some() {
|
|
v.push(f(b"kern", false));
|
|
}
|
|
let liga = self.ligatures && st.tracking.abs() < 1e-9;
|
|
if !liga {
|
|
v.push(f(b"liga", false));
|
|
v.push(f(b"clig", false));
|
|
}
|
|
if !self.contextual {
|
|
v.push(f(b"calt", false));
|
|
}
|
|
if st.all_caps {
|
|
v.push(f(b"case", true));
|
|
}
|
|
for (on, tag) in [
|
|
(self.discretionary_ligatures, b"dlig"),
|
|
(self.small_caps, b"smcp"),
|
|
(self.fractions, b"frac"),
|
|
(self.oldstyle_figures, b"onum"),
|
|
(self.tabular_figures, b"tnum"),
|
|
(self.ordinals, b"ordn"),
|
|
(self.swash, b"swsh"),
|
|
] {
|
|
if on {
|
|
v.push(f(tag, true));
|
|
}
|
|
}
|
|
v
|
|
}
|
|
}
|