diff --git a/src/modules/sym.txt b/src/modules/sym.txt index 1e28454..a416cb9 100644 --- a/src/modules/sym.txt +++ b/src/modules/sym.txt @@ -1161,6 +1161,40 @@ sha ш // Uppercase Cyrillic. Sha Ш +// Arabic. +alef ا +beh ب + .dotless ٮ +jeem ج +dal د +heh ه +waw و +zain ز +hah ح +tah ط +yeh ي +kaf ك +lam ل +meem م +noon ن + .dotless ں +seen س +ain ع +feh ف + .dotless ڡ +sad ص +qaf ق + .dotless ٯ +reh ر +sheen ش +teh ت +theh ث +khah خ +thal ذ +dad ض +zah ظ +ghain غ + // Hebrew. // In math, the following symbols are replaced with corresponding characters // from Letterlike Symbols. diff --git a/src/styling.rs b/src/styling.rs index 33505ed..d461db4 100644 --- a/src/styling.rs +++ b/src/styling.rs @@ -171,13 +171,17 @@ pub enum MathStyle { } /// Base [`MathStyle`]s used in Typst. -#[non_exhaustive] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum MathVariant { Plain, Fraktur, SansSerif, Monospace, + Isolated, + Initial, + Tailed, + Stretched, + Looped, DoubleStruck, Chancery, Roundhand, @@ -230,6 +234,54 @@ impl MathStyle { ) -> MathStyle { use conversions::*; use MathVariant::*; + + if is_arabic(c) || is_arabic_dotless(c) { + let Some(variant) = variant else { + let style = if matches!(italic, Some(false)) { + MathStyle::Plain + } else if matches!(c, 'ج' | 'ه') { + MathStyle::Initial + } else { + MathStyle::Isolated + }; + return style; + }; + + return match variant { + Isolated if (is_arabic(c) & !matches!(c, 'ه')) | is_arabic_dotless(c) => { + MathStyle::Isolated + } + Initial + if is_arabic(c) & !matches!(c, 'ا' | 'د'..='ز' | 'ط' | 'ظ' | 'و') => + { + MathStyle::Initial + } + Tailed + if (is_arabic(c) + & !matches!( + c, + 'ا' | 'ب' | 'ت' | 'ث' | 'د' + ..='ز' | 'ط' | 'ظ' | 'ف' | 'ك' | 'م' | 'ه' | 'و' + )) + | (is_arabic_dotless(c) & !matches!(c, 'ٮ' | 'ڡ')) => + { + MathStyle::Tailed + } + Stretched + if (is_arabic(c) & !matches!(c, 'ا' | 'د'..='ز' | 'ل' | 'و')) + | (is_arabic_dotless(c) & !matches!(c, 'ٯ' | 'ں')) => + { + MathStyle::Stretched + } + Looped if is_arabic(c) & !matches!(c, 'ك') => MathStyle::Looped, + DoubleStruck if is_arabic(c) & !matches!(c, 'ا' | 'ك' | 'ه') => { + MathStyle::DoubleStruck + } + _ if matches!(c, 'ج' | 'ه') => MathStyle::Initial, + _ => MathStyle::Isolated, + }; + } + match (variant.unwrap_or(Plain), bold, italic) { (SansSerif, false, Some(false)) if is_latin(c) => MathStyle::SansSerif, (SansSerif, false, _) if is_latin(c) => MathStyle::SansSerifItalic, @@ -446,6 +498,16 @@ mod conversions { matches!(c, 'א'..='ד') } + #[inline] + pub fn is_arabic(c: char) -> bool { + matches!(c, 'ا' | 'ب' | 'ت'..='غ' | 'ف'..='و' | 'ي') + } + + #[inline] + pub fn is_arabic_dotless(c: char) -> bool { + matches!(c, 'ٮ' | 'ٯ' | 'ڡ' | 'ں') + } + /// The character given by adding `delta` to the codepoint of `c`. #[inline] fn apply_delta(c: char, delta: u32) -> char {