use crate::context::Script;
use crate::length::Length;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct FontKey(pub u16);
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct MathConstants {
pub axis_height: f64,
pub superscript_bottom_min: f64,
pub superscript_shift_up: f64,
pub superscript_shift_up_cramped: f64,
pub superscript_baseline_drop_max: f64,
pub subscript_top_max: f64,
pub subscript_shift_down: f64,
pub subscript_baseline_drop_min: f64,
pub script_scale_down: f64,
pub script_script_scale_down: f64,
pub space_after_script: f64,
pub sub_superscript_gap_min: f64,
pub fraction_rule_thickness: f64,
pub fraction_numer_shift_up: f64,
pub fraction_numer_gap_min: f64,
pub fraction_denom_shift_down: f64,
pub fraction_denom_gap_min: f64,
pub radical_extra_ascender: f64,
pub radical_rule_thickness: f64,
pub radical_vertical_gap: f64,
pub upper_limit_gap_min: f64,
pub upper_limit_baseline_rise_min: f64,
pub lower_limit_gap_min: f64,
pub lower_limit_baseline_drop_min: f64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MathCorner {
TopRight,
TopLeft,
BottomRight,
BottomLeft,
}
pub fn char_script(c: char) -> Script {
match c as u32 {
0x3040..=0x30FF | 0x31F0..=0x31FF => Script::Kana,
0x3400..=0x4DBF
| 0x4E00..=0x9FFF
| 0xF900..=0xFAFF
| 0x3000..=0x303F
| 0xFF00..=0xFFEF
| 0x20000..=0x2FA1F => Script::HanIdeographic,
0x0000..=0x024F => Script::Latin,
_ => Script::OtherScript,
}
}
pub trait FontMetrics {
fn advance(&self, font: FontKey, c: char, size: Length) -> Option<Length>;
fn ascender(&self, font: FontKey, size: Length) -> Length;
fn descender(&self, font: FontKey, size: Length) -> Length;
fn glyph_vextent(&self, _font: FontKey, _c: char, _size: Length) -> Option<(Length, Length)> {
None
}
fn run_vextent(&self, font: FontKey, text: &str, size: Length) -> (Length, Length) {
let mut hgt = Length::ZERO;
let mut dpt = Length::ZERO;
let mut any = false;
for c in text.chars() {
if let Some((h, d)) = self.glyph_vextent(font, c, size) {
hgt = hgt.max(h);
dpt = dpt.max(d);
any = true;
}
}
if any {
(hgt, dpt)
} else {
(self.ascender(font, size), self.descender(font, size))
}
}
fn text_width(&self, font: FontKey, text: &str, size: Length) -> Option<Length> {
let mut w = Length::ZERO;
for c in text.chars() {
w += self.advance(font, c, size)?;
}
Some(w)
}
fn math_constants(&self, _font: FontKey) -> Option<MathConstants> {
None
}
fn italic_correction(&self, _font: FontKey, _c: char, _size: Length) -> Option<Length> {
None
}
fn math_kern(
&self,
_font: FontKey,
_c: char,
_size: Length,
_corner: MathCorner,
_corr: Length,
) -> Option<Length> {
None
}
fn math_vertical_variant(
&self,
_font: FontKey,
_c: char,
_size: Length,
_policy: VertVariantPolicy,
) -> Option<MathVariantGlyph> {
None
}
fn math_script_variant(
&self,
_font: FontKey,
_c: char,
_size: Length,
) -> Option<MathVariantGlyph> {
None
}
fn math_vertical_assembly(
&self,
_font: FontKey,
_c: char,
_size: Length,
_target: Length,
) -> Option<Vec<(u16, Length, Length)>> {
None
}
fn resolve_font_abbrev(&self, _abbrev: &str) -> Option<FontKey> {
None
}
fn font_abbrev(&self, _key: FontKey) -> Option<String> {
None
}
fn default_script_font(&self, _script: Script) -> Option<(FontKey, f64, f64)> {
None
}
fn default_math_font(&self) -> Option<FontKey> {
None
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum VertVariantPolicy {
BigOp,
AtLeast(Length),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct MathVariantGlyph {
pub gid: u16,
pub advance: Length,
pub height: Length,
pub depth: Length,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn char_script_classifies_the_stdja_corpus() {
assert_eq!(char_script('あ'), Script::Kana); assert_eq!(char_script('ア'), Script::Kana); assert_eq!(char_script('漢'), Script::HanIdeographic);
assert_eq!(char_script('A'), Script::Latin);
assert_eq!(char_script('z'), Script::Latin);
assert_eq!(char_script('é'), Script::Latin); assert_eq!(char_script('→'), Script::OtherScript); assert_eq!(char_script('。'), Script::HanIdeographic); assert_eq!(char_script('「'), Script::HanIdeographic);
assert_eq!(char_script('、'), Script::HanIdeographic);
}
}