use crate::font::FontKey;
use crate::graphics::Color;
use crate::length::Length;
use crate::math::{default_math_class_map, MathCharClass, MathKind};
use std::collections::BTreeMap;
use std::sync::Arc;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct MathCmdId(pub usize);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Script {
HanIdeographic = 0,
Kana = 1,
Latin = 2,
OtherScript = 3,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Language {
Japanese,
English,
NoLanguageSystem,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum HyphenLang {
EnglishUS,
EnglishGB,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MathScriptLevel {
Base,
Script,
ScriptScript,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ScriptFont {
pub font: FontKey,
pub ratio: f64,
pub rising: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Context {
pub font: FontKey,
pub math_font: FontKey,
pub font_size: Length,
pub leading: Length,
pub paragraph_width: Length,
pub paragraph_top: Length,
pub paragraph_bottom: Length,
pub manual_rising: Length,
pub dominant_wide_script: Script,
pub dominant_narrow_script: Script,
pub langsys_scheme: [Language; 4],
pub font_scheme: [ScriptFont; 4],
pub script_space_map: [[f64; 4]; 4],
pub text_color: Color,
pub hyphen_badness: i64,
pub hyphen_dictionary: Option<HyphenLang>,
pub left_hyphen_min: i64,
pub right_hyphen_min: i64,
pub space_natural: f64,
pub space_shrink: f64,
pub space_stretch: f64,
pub adjacent_stretch: f64,
pub math_command: Option<MathCmdId>,
pub code_text_command: Option<MathCmdId>,
pub math_char_class: MathCharClass,
pub math_class_map: Arc<BTreeMap<String, (String, MathKind)>>,
pub math_variant_char_map: Arc<BTreeMap<(char, MathCharClass), char>>,
pub math_script_level: MathScriptLevel,
pub math_cramped: bool,
}
pub fn default_script_space_map() -> [[f64; 4]; 4] {
const LATIN_CJK_NATURAL: f64 = 0.24;
let mut m = [[0.0; 4]; 4];
for cjk in [Script::HanIdeographic, Script::Kana] {
m[Script::Latin as usize][cjk as usize] = LATIN_CJK_NATURAL;
m[cjk as usize][Script::Latin as usize] = LATIN_CJK_NATURAL;
}
m
}
impl Context {
pub fn initial(paragraph_width: Length) -> Context {
Context {
font: FontKey(0),
math_font: FontKey(0),
font_size: Length::pt(12.0),
leading: Length::pt(18.0),
paragraph_width,
paragraph_top: Length::pt(18.0),
paragraph_bottom: Length::pt(18.0),
manual_rising: Length::ZERO,
dominant_wide_script: Script::OtherScript,
dominant_narrow_script: Script::OtherScript,
langsys_scheme: [Language::NoLanguageSystem; 4],
font_scheme: [ScriptFont {
font: FontKey(0),
ratio: 1.0,
rising: 0.0,
}; 4],
script_space_map: default_script_space_map(),
text_color: Color::Gray(0.0),
hyphen_badness: 100,
hyphen_dictionary: Some(HyphenLang::EnglishUS),
left_hyphen_min: 3,
right_hyphen_min: 2,
space_natural: 0.33,
space_shrink: 0.08,
space_stretch: 0.16,
adjacent_stretch: 0.025,
math_command: None,
code_text_command: None,
math_char_class: MathCharClass::Italic,
math_class_map: Arc::new(default_math_class_map()),
math_variant_char_map: Arc::new(BTreeMap::new()),
math_script_level: MathScriptLevel::Base,
math_cramped: false,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct PageGeometry {
pub paper_width: Length,
pub paper_height: Length,
pub text_origin: (Length, Length),
pub text_width: Length,
pub text_height: Length,
}
impl Default for PageGeometry {
fn default() -> Self {
let paper_width = Length::from_unit(210.0, "mm").unwrap();
let paper_height = Length::from_unit(297.0, "mm").unwrap();
let margin = Length::from_unit(25.0, "mm").unwrap();
PageGeometry {
paper_width,
paper_height,
text_origin: (margin, margin),
text_width: paper_width - margin - margin,
text_height: paper_height - margin - margin,
}
}
}
impl PageGeometry {
pub fn for_paper(paper_width: Length, paper_height: Length) -> PageGeometry {
PageGeometry {
paper_width,
paper_height,
text_origin: (Length::ZERO, Length::ZERO),
text_width: paper_width,
text_height: paper_height,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PaperSize {
A0,
A1,
A2,
A3,
A4,
A5,
USLetter,
USLegal,
UserDefined(Length, Length),
}
impl PaperSize {
pub fn dims(&self) -> (Length, Length) {
fn mm(w: f64, h: f64) -> (Length, Length) {
(
Length::from_unit(w, "mm").unwrap(),
Length::from_unit(h, "mm").unwrap(),
)
}
fn inch(w: f64, h: f64) -> (Length, Length) {
(
Length::from_unit(w, "inch").unwrap(),
Length::from_unit(h, "inch").unwrap(),
)
}
match *self {
PaperSize::A0 => mm(841.0, 1189.0),
PaperSize::A1 => mm(594.0, 841.0),
PaperSize::A2 => mm(420.0, 594.0),
PaperSize::A3 => mm(297.0, 420.0),
PaperSize::A4 => mm(210.0, 297.0),
PaperSize::A5 => mm(148.0, 210.0),
PaperSize::USLetter => inch(8.5, 11.0),
PaperSize::USLegal => inch(8.5, 14.0),
PaperSize::UserDefined(w, h) => (w, h),
}
}
}