diff options
| author | Malo <57839069+MDLC01@users.noreply.github.com> | 2025-01-31 11:05:03 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-31 10:05:03 +0000 |
| commit | f239b0a6a1e68a016cacf19eeef2df52e4affeb9 (patch) | |
| tree | 101b8aeba40b8c9925d273894cfc27de2a4b5756 | |
| parent | 46727878da083eb8186373434997f5f7403cbb66 (diff) | |
Change the default math class of U+22A5 ⊥ UP TACK to Normal (#5714)
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | crates/typst-layout/src/math/fragment.rs | 9 | ||||
| -rw-r--r-- | crates/typst-library/src/math/matrix.rs | 6 | ||||
| -rw-r--r-- | crates/typst-syntax/src/parser.rs | 3 | ||||
| -rw-r--r-- | crates/typst-utils/Cargo.toml | 1 | ||||
| -rw-r--r-- | crates/typst-utils/src/lib.rs | 26 | ||||
| -rw-r--r-- | tests/ref/issue-4985-up-tack-is-normal-perp-is-relation.png | bin | 0 -> 360 bytes | |||
| -rw-r--r-- | tests/suite/math/class.typ | 5 |
8 files changed, 41 insertions, 10 deletions
@@ -3106,6 +3106,7 @@ dependencies = [ "rayon", "siphasher 1.0.1", "thin-vec", + "unicode-math-class", ] [[package]] diff --git a/crates/typst-layout/src/math/fragment.rs b/crates/typst-layout/src/math/fragment.rs index 81b726ba..1b508a34 100644 --- a/crates/typst-layout/src/math/fragment.rs +++ b/crates/typst-layout/src/math/fragment.rs @@ -13,6 +13,7 @@ use typst_library::math::{EquationElem, MathSize}; use typst_library::text::{Font, Glyph, Lang, Region, TextElem, TextItem}; use typst_library::visualize::Paint; use typst_syntax::Span; +use typst_utils::default_math_class; use unicode_math_class::MathClass; use super::{stretch_glyph, MathContext, Scaled}; @@ -275,11 +276,7 @@ impl GlyphFragment { span: Span, ) -> Self { let class = EquationElem::class_in(styles) - .or_else(|| match c { - ':' => Some(MathClass::Relation), - '.' | '/' | '⋯' | '⋱' | '⋰' | '⋮' => Some(MathClass::Normal), - _ => unicode_math_class::class(c), - }) + .or_else(|| default_math_class(c)) .unwrap_or(MathClass::Normal); let mut fragment = Self { @@ -629,7 +626,7 @@ pub enum Limits { impl Limits { /// The default limit configuration if the given character is the base. pub fn for_char(c: char) -> Self { - match unicode_math_class::class(c) { + match default_math_class(c) { Some(MathClass::Large) => { if is_integral_char(c) { Limits::Never diff --git a/crates/typst-library/src/math/matrix.rs b/crates/typst-library/src/math/matrix.rs index c74eb8fa..b6c4654e 100644 --- a/crates/typst-library/src/math/matrix.rs +++ b/crates/typst-library/src/math/matrix.rs @@ -1,6 +1,6 @@ use smallvec::{smallvec, SmallVec}; use typst_syntax::Spanned; -use typst_utils::Numeric; +use typst_utils::{default_math_class, Numeric}; use unicode_math_class::MathClass; use crate::diag::{bail, At, HintedStrResult, StrResult}; @@ -292,7 +292,7 @@ impl Delimiter { pub fn char(c: char) -> StrResult<Self> { if !matches!( - unicode_math_class::class(c), + default_math_class(c), Some(MathClass::Opening | MathClass::Closing | MathClass::Fence), ) { bail!("invalid delimiter: \"{}\"", c) @@ -311,7 +311,7 @@ impl Delimiter { Some(']') => Self(Some('[')), Some('{') => Self(Some('}')), Some('}') => Self(Some('{')), - Some(c) => match unicode_math_class::class(c) { + Some(c) => match default_math_class(c) { Some(MathClass::Opening) => Self(char::from_u32(c as u32 + 1)), Some(MathClass::Closing) => Self(char::from_u32(c as u32 - 1)), _ => Self(Some(c)), diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs index 55d5550b..e187212d 100644 --- a/crates/typst-syntax/src/parser.rs +++ b/crates/typst-syntax/src/parser.rs @@ -3,6 +3,7 @@ use std::mem; use std::ops::{Index, IndexMut, Range}; use ecow::{eco_format, EcoString}; +use typst_utils::default_math_class; use unicode_math_class::MathClass; use crate::set::{syntax_set, SyntaxSet}; @@ -468,7 +469,7 @@ fn math_class(text: &str) -> Option<MathClass> { chars .next() .filter(|_| chars.next().is_none()) - .and_then(unicode_math_class::class) + .and_then(default_math_class) } /// Parse an argument list in math: `(a, b; c, d; size: #50%)`. diff --git a/crates/typst-utils/Cargo.toml b/crates/typst-utils/Cargo.toml index 5f828cff..360e07d8 100644 --- a/crates/typst-utils/Cargo.toml +++ b/crates/typst-utils/Cargo.toml @@ -18,6 +18,7 @@ portable-atomic = { workspace = true } rayon = { workspace = true } siphasher = { workspace = true } thin-vec = { workspace = true } +unicode-math-class = { workspace = true } [lints] workspace = true diff --git a/crates/typst-utils/src/lib.rs b/crates/typst-utils/src/lib.rs index b59fe2f7..34d6a943 100644 --- a/crates/typst-utils/src/lib.rs +++ b/crates/typst-utils/src/lib.rs @@ -31,6 +31,7 @@ use std::ops::{Add, Deref, Div, Mul, Neg, Sub}; use std::sync::Arc; use siphasher::sip128::{Hasher128, SipHasher13}; +use unicode_math_class::MathClass; /// Turn a closure into a struct implementing [`Debug`]. pub fn debug<F>(f: F) -> impl Debug @@ -337,3 +338,28 @@ pub trait Numeric: /// Whether `self` consists only of finite parts. fn is_finite(self) -> bool; } + +/// Returns the default math class of a character in Typst, if it has one. +/// +/// This is determined by the Unicode math class, with some manual overrides. +pub fn default_math_class(c: char) -> Option<MathClass> { + match c { + // Better spacing. + // https://github.com/typst/typst/commit/2e039cb052fcb768027053cbf02ce396f6d7a6be + ':' => Some(MathClass::Relation), + + // Better spacing when used alongside + PLUS SIGN. + // https://github.com/typst/typst/pull/1726 + '⋯' | '⋱' | '⋰' | '⋮' => Some(MathClass::Normal), + + // Better spacing. + // https://github.com/typst/typst/pull/1855 + '.' | '/' => Some(MathClass::Normal), + + // ⊥ UP TACK should not be a relation, contrary to ⟂ PERPENDICULAR. + // https://github.com/typst/typst/pull/5714 + '\u{22A5}' => Some(MathClass::Normal), + + c => unicode_math_class::class(c), + } +} diff --git a/tests/ref/issue-4985-up-tack-is-normal-perp-is-relation.png b/tests/ref/issue-4985-up-tack-is-normal-perp-is-relation.png Binary files differnew file mode 100644 index 00000000..acadc3be --- /dev/null +++ b/tests/ref/issue-4985-up-tack-is-normal-perp-is-relation.png diff --git a/tests/suite/math/class.typ b/tests/suite/math/class.typ index d25071db..9f014810 100644 --- a/tests/suite/math/class.typ +++ b/tests/suite/math/class.typ @@ -45,3 +45,8 @@ $class("large", ->)_a$ $limits(class("normal", ->))_a$ $ scripts(class("relation", x))_a $ + +--- issue-4985-up-tack-is-normal-perp-is-relation --- +$ top = 1 \ + bot = 2 \ + a perp b $ |
