mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Change the default math class of U+22A5 ⊥ UP TACK to Normal (#5714)
This commit is contained in:
parent
46727878da
commit
f239b0a6a1
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3106,6 +3106,7 @@ dependencies = [
|
|||||||
"rayon",
|
"rayon",
|
||||||
"siphasher 1.0.1",
|
"siphasher 1.0.1",
|
||||||
"thin-vec",
|
"thin-vec",
|
||||||
|
"unicode-math-class",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -13,6 +13,7 @@ use typst_library::math::{EquationElem, MathSize};
|
|||||||
use typst_library::text::{Font, Glyph, Lang, Region, TextElem, TextItem};
|
use typst_library::text::{Font, Glyph, Lang, Region, TextElem, TextItem};
|
||||||
use typst_library::visualize::Paint;
|
use typst_library::visualize::Paint;
|
||||||
use typst_syntax::Span;
|
use typst_syntax::Span;
|
||||||
|
use typst_utils::default_math_class;
|
||||||
use unicode_math_class::MathClass;
|
use unicode_math_class::MathClass;
|
||||||
|
|
||||||
use super::{stretch_glyph, MathContext, Scaled};
|
use super::{stretch_glyph, MathContext, Scaled};
|
||||||
@ -275,11 +276,7 @@ impl GlyphFragment {
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let class = EquationElem::class_in(styles)
|
let class = EquationElem::class_in(styles)
|
||||||
.or_else(|| match c {
|
.or_else(|| default_math_class(c))
|
||||||
':' => Some(MathClass::Relation),
|
|
||||||
'.' | '/' | '⋯' | '⋱' | '⋰' | '⋮' => Some(MathClass::Normal),
|
|
||||||
_ => unicode_math_class::class(c),
|
|
||||||
})
|
|
||||||
.unwrap_or(MathClass::Normal);
|
.unwrap_or(MathClass::Normal);
|
||||||
|
|
||||||
let mut fragment = Self {
|
let mut fragment = Self {
|
||||||
@ -629,7 +626,7 @@ pub enum Limits {
|
|||||||
impl Limits {
|
impl Limits {
|
||||||
/// The default limit configuration if the given character is the base.
|
/// The default limit configuration if the given character is the base.
|
||||||
pub fn for_char(c: char) -> Self {
|
pub fn for_char(c: char) -> Self {
|
||||||
match unicode_math_class::class(c) {
|
match default_math_class(c) {
|
||||||
Some(MathClass::Large) => {
|
Some(MathClass::Large) => {
|
||||||
if is_integral_char(c) {
|
if is_integral_char(c) {
|
||||||
Limits::Never
|
Limits::Never
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use typst_syntax::Spanned;
|
use typst_syntax::Spanned;
|
||||||
use typst_utils::Numeric;
|
use typst_utils::{default_math_class, Numeric};
|
||||||
use unicode_math_class::MathClass;
|
use unicode_math_class::MathClass;
|
||||||
|
|
||||||
use crate::diag::{bail, At, HintedStrResult, StrResult};
|
use crate::diag::{bail, At, HintedStrResult, StrResult};
|
||||||
@ -292,7 +292,7 @@ impl Delimiter {
|
|||||||
|
|
||||||
pub fn char(c: char) -> StrResult<Self> {
|
pub fn char(c: char) -> StrResult<Self> {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
unicode_math_class::class(c),
|
default_math_class(c),
|
||||||
Some(MathClass::Opening | MathClass::Closing | MathClass::Fence),
|
Some(MathClass::Opening | MathClass::Closing | MathClass::Fence),
|
||||||
) {
|
) {
|
||||||
bail!("invalid delimiter: \"{}\"", c)
|
bail!("invalid delimiter: \"{}\"", c)
|
||||||
@ -311,7 +311,7 @@ impl Delimiter {
|
|||||||
Some(']') => Self(Some('[')),
|
Some(']') => Self(Some('[')),
|
||||||
Some('{') => Self(Some('}')),
|
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::Opening) => Self(char::from_u32(c as u32 + 1)),
|
||||||
Some(MathClass::Closing) => Self(char::from_u32(c as u32 - 1)),
|
Some(MathClass::Closing) => Self(char::from_u32(c as u32 - 1)),
|
||||||
_ => Self(Some(c)),
|
_ => Self(Some(c)),
|
||||||
|
@ -3,6 +3,7 @@ use std::mem;
|
|||||||
use std::ops::{Index, IndexMut, Range};
|
use std::ops::{Index, IndexMut, Range};
|
||||||
|
|
||||||
use ecow::{eco_format, EcoString};
|
use ecow::{eco_format, EcoString};
|
||||||
|
use typst_utils::default_math_class;
|
||||||
use unicode_math_class::MathClass;
|
use unicode_math_class::MathClass;
|
||||||
|
|
||||||
use crate::set::{syntax_set, SyntaxSet};
|
use crate::set::{syntax_set, SyntaxSet};
|
||||||
@ -468,7 +469,7 @@ fn math_class(text: &str) -> Option<MathClass> {
|
|||||||
chars
|
chars
|
||||||
.next()
|
.next()
|
||||||
.filter(|_| chars.next().is_none())
|
.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%)`.
|
/// Parse an argument list in math: `(a, b; c, d; size: #50%)`.
|
||||||
|
@ -18,6 +18,7 @@ portable-atomic = { workspace = true }
|
|||||||
rayon = { workspace = true }
|
rayon = { workspace = true }
|
||||||
siphasher = { workspace = true }
|
siphasher = { workspace = true }
|
||||||
thin-vec = { workspace = true }
|
thin-vec = { workspace = true }
|
||||||
|
unicode-math-class = { workspace = true }
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
@ -31,6 +31,7 @@ use std::ops::{Add, Deref, Div, Mul, Neg, Sub};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use siphasher::sip128::{Hasher128, SipHasher13};
|
use siphasher::sip128::{Hasher128, SipHasher13};
|
||||||
|
use unicode_math_class::MathClass;
|
||||||
|
|
||||||
/// Turn a closure into a struct implementing [`Debug`].
|
/// Turn a closure into a struct implementing [`Debug`].
|
||||||
pub fn debug<F>(f: F) -> impl Debug
|
pub fn debug<F>(f: F) -> impl Debug
|
||||||
@ -337,3 +338,28 @@ pub trait Numeric:
|
|||||||
/// Whether `self` consists only of finite parts.
|
/// Whether `self` consists only of finite parts.
|
||||||
fn is_finite(self) -> bool;
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BIN
tests/ref/issue-4985-up-tack-is-normal-perp-is-relation.png
Normal file
BIN
tests/ref/issue-4985-up-tack-is-normal-perp-is-relation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 360 B |
@ -45,3 +45,8 @@ $class("large", ->)_a$
|
|||||||
|
|
||||||
$limits(class("normal", ->))_a$
|
$limits(class("normal", ->))_a$
|
||||||
$ scripts(class("relation", x))_a $
|
$ scripts(class("relation", x))_a $
|
||||||
|
|
||||||
|
--- issue-4985-up-tack-is-normal-perp-is-relation ---
|
||||||
|
$ top = 1 \
|
||||||
|
bot = 2 \
|
||||||
|
a perp b $
|
||||||
|
Loading…
x
Reference in New Issue
Block a user