Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/modules/sym.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
64 changes: 63 additions & 1 deletion src/styling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down