mirror of
https://github.com/typst/typst
synced 2025-08-19 09:28:33 +08:00
Add math.scr
This commit is contained in:
parent
b37f57bdec
commit
4b13abc728
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -413,7 +413,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "codex"
|
name = "codex"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "git+https://github.com/mkorje/codex?rev=f02fa4a#f02fa4a04f2a9937f043892ee865dd06628264ba"
|
source = "git+https://github.com/typst/codex?rev=9ac86f9#9ac86f96af5b89fce555e6bba8b6d1ac7b44ef00"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color-print"
|
name = "color-print"
|
||||||
|
@ -47,7 +47,7 @@ clap = { version = "4.4", features = ["derive", "env", "wrap_help"] }
|
|||||||
clap_complete = "4.2.1"
|
clap_complete = "4.2.1"
|
||||||
clap_mangen = "0.2.10"
|
clap_mangen = "0.2.10"
|
||||||
codespan-reporting = "0.11"
|
codespan-reporting = "0.11"
|
||||||
codex = { git = "https://github.com/mkorje/codex", rev = "f02fa4a" }
|
codex = { git = "https://github.com/typst/codex", rev = "9ac86f9" }
|
||||||
color-print = "0.3.6"
|
color-print = "0.3.6"
|
||||||
comemo = "0.4"
|
comemo = "0.4"
|
||||||
csv = "1"
|
csv = "1"
|
||||||
|
@ -65,12 +65,21 @@ fn layout_inline_text(
|
|||||||
ctx: &mut MathContext,
|
ctx: &mut MathContext,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> SourceResult<FrameFragment> {
|
) -> SourceResult<FrameFragment> {
|
||||||
|
let variant = EquationElem::variant_in(styles);
|
||||||
|
let bold = EquationElem::bold_in(styles);
|
||||||
|
// Disable auto-italic.
|
||||||
|
let italic = EquationElem::italic_in(styles).or(Some(false));
|
||||||
|
|
||||||
if text.chars().all(|c| c.is_ascii_digit() || c == '.') {
|
if text.chars().all(|c| c.is_ascii_digit() || c == '.') {
|
||||||
// Small optimization for numbers. Note that this lays out slightly
|
// Small optimization for numbers. Note that this lays out slightly
|
||||||
// differently to normal text and is worth re-evaluating in the future.
|
// differently to normal text and is worth re-evaluating in the future.
|
||||||
let mut fragments = vec![];
|
let mut fragments = vec![];
|
||||||
for unstyled_c in text.chars() {
|
for unstyled_c in text.chars() {
|
||||||
let c = styled_char(styles, unstyled_c, false);
|
// This is fine as ascii digits and '.' can never end up as more
|
||||||
|
// than a single char after styling.
|
||||||
|
let style = MathStyle::select(unstyled_c, variant, bold, italic);
|
||||||
|
let c = to_style(unstyled_c, style).next().unwrap();
|
||||||
|
|
||||||
let glyph = GlyphFragment::new_char(ctx.font, styles, c, span)?;
|
let glyph = GlyphFragment::new_char(ctx.font, styles, c, span)?;
|
||||||
fragments.push(glyph.into());
|
fragments.push(glyph.into());
|
||||||
}
|
}
|
||||||
@ -84,8 +93,10 @@ fn layout_inline_text(
|
|||||||
.map(|p| p.wrap());
|
.map(|p| p.wrap());
|
||||||
|
|
||||||
let styles = styles.chain(&local);
|
let styles = styles.chain(&local);
|
||||||
let styled_text: EcoString =
|
let styled_text: EcoString = text
|
||||||
text.chars().map(|c| styled_char(styles, c, false)).collect();
|
.chars()
|
||||||
|
.flat_map(|c| to_style(c, MathStyle::select(c, variant, bold, italic)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let spaced = styled_text.graphemes(true).nth(1).is_some();
|
let spaced = styled_text.graphemes(true).nth(1).is_some();
|
||||||
let elem = TextElem::packed(styled_text).spanned(span);
|
let elem = TextElem::packed(styled_text).spanned(span);
|
||||||
@ -125,9 +136,16 @@ pub fn layout_symbol(
|
|||||||
Some(c) if has_dtls_feat(ctx.font) => (c, styles.chain(&dtls)),
|
Some(c) if has_dtls_feat(ctx.font) => (c, styles.chain(&dtls)),
|
||||||
_ => (elem.text, styles),
|
_ => (elem.text, styles),
|
||||||
};
|
};
|
||||||
let c = styled_char(styles, unstyled_c, true);
|
|
||||||
|
let variant = EquationElem::variant_in(styles);
|
||||||
|
let bold = EquationElem::bold_in(styles);
|
||||||
|
let italic = EquationElem::italic_in(styles);
|
||||||
|
|
||||||
|
let style = MathStyle::select(unstyled_c, variant, bold, italic);
|
||||||
|
let text: EcoString = to_style(unstyled_c, style).collect();
|
||||||
|
|
||||||
let fragment: MathFragment =
|
let fragment: MathFragment =
|
||||||
match GlyphFragment::new_char(ctx.font, symbol_styles, c, elem.span()) {
|
match GlyphFragment::new(ctx.font, symbol_styles, &text, elem.span()) {
|
||||||
Ok(mut glyph) => {
|
Ok(mut glyph) => {
|
||||||
adjust_glyph_layout(&mut glyph, ctx, styles);
|
adjust_glyph_layout(&mut glyph, ctx, styles);
|
||||||
glyph.into()
|
glyph.into()
|
||||||
@ -135,8 +153,7 @@ pub fn layout_symbol(
|
|||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Not in the math font, fallback to normal inline text layout.
|
// Not in the math font, fallback to normal inline text layout.
|
||||||
// TODO: Should replace this with proper fallback in [`GlyphFragment::new`].
|
// TODO: Should replace this with proper fallback in [`GlyphFragment::new`].
|
||||||
layout_inline_text(c.encode_utf8(&mut [0; 4]), elem.span(), ctx, styles)?
|
layout_inline_text(&text, elem.span(), ctx, styles)?.into()
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ctx.push(fragment);
|
ctx.push(fragment);
|
||||||
@ -162,38 +179,6 @@ fn adjust_glyph_layout(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Style the character by selecting the Unicode codepoint for italic, bold,
|
|
||||||
/// caligraphic, etc.
|
|
||||||
fn styled_char(styles: StyleChain, c: char, auto_italic: bool) -> char {
|
|
||||||
if let Some(c) = basic_exception(c) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
let variant = EquationElem::variant_in(styles);
|
|
||||||
let bold = EquationElem::bold_in(styles);
|
|
||||||
let italic =
|
|
||||||
EquationElem::italic_in(styles).or_else(|| (!auto_italic).then_some(false));
|
|
||||||
let style = MathStyle::select(c, variant, bold, italic);
|
|
||||||
|
|
||||||
// At the moment we are only using styles that output a single character,
|
|
||||||
// so we just grab the first character in the ToStyle iterator.
|
|
||||||
to_style(c, style).next().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn basic_exception(c: char) -> Option<char> {
|
|
||||||
Some(match c {
|
|
||||||
'〈' => '⟨',
|
|
||||||
'〉' => '⟩',
|
|
||||||
'《' => '⟪',
|
|
||||||
'》' => '⟫',
|
|
||||||
'א' => 'ℵ',
|
|
||||||
'ב' => 'ℶ',
|
|
||||||
'ג' => 'ℷ',
|
|
||||||
'ד' => 'ℸ',
|
|
||||||
_ => return None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The non-dotless version of a dotless character that can be used with the
|
/// The non-dotless version of a dotless character that can be used with the
|
||||||
/// `dtls` OpenType feature.
|
/// `dtls` OpenType feature.
|
||||||
pub fn try_dotless(c: char) -> Option<char> {
|
pub fn try_dotless(c: char) -> Option<char> {
|
||||||
|
@ -80,6 +80,7 @@ pub fn module() -> Module {
|
|||||||
math.define_func::<italic>();
|
math.define_func::<italic>();
|
||||||
math.define_func::<serif>();
|
math.define_func::<serif>();
|
||||||
math.define_func::<sans>();
|
math.define_func::<sans>();
|
||||||
|
math.define_func::<scr>();
|
||||||
math.define_func::<cal>();
|
math.define_func::<cal>();
|
||||||
math.define_func::<frak>();
|
math.define_func::<frak>();
|
||||||
math.define_func::<mono>();
|
math.define_func::<mono>();
|
||||||
|
@ -64,20 +64,34 @@ pub fn sans(
|
|||||||
body.styled(EquationElem::set_variant(Some(MathVariant::SansSerif)))
|
body.styled(EquationElem::set_variant(Some(MathVariant::SansSerif)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calligraphic font style in math.
|
/// Calligraphic (chancery) font style in math.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
/// Let $cal(P)$ be the set of ...
|
/// Let $cal(P)$ be the set of ...
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// This corresponds both to LaTeX's `\mathcal` and `\mathscr` as both of these
|
/// This is the default calligraphic/script style for most math fonts. See
|
||||||
/// styles share the same Unicode codepoints. Switching between the styles is
|
/// [`scr`]($math.scr) for more on how to get the other style (roundhand).
|
||||||
/// thus only possible if supported by the font via
|
#[func(title = "Calligraphic", keywords = ["mathcal", "chancery"])]
|
||||||
|
pub fn cal(
|
||||||
|
/// The content to style.
|
||||||
|
body: Content,
|
||||||
|
) -> Content {
|
||||||
|
body.styled(EquationElem::set_variant(Some(MathVariant::Chancery)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Script (roundhand) font style in math.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// $ scr(S) $
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Very few math fonts currently support differentiating `cal` and `scr`. Some
|
||||||
|
/// fonts support switching between the styles via
|
||||||
/// [font features]($text.features).
|
/// [font features]($text.features).
|
||||||
///
|
///
|
||||||
/// For the default math font, the roundhand style is available through the
|
/// Say, for example, the roundhand style is available through the `ss01`
|
||||||
/// `ss01` feature. Therefore, you could define your own version of `\mathscr`
|
/// feature. Then, you could define your own version of `\mathscr` like this:
|
||||||
/// like this:
|
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
/// #let scr(it) = text(
|
/// #let scr(it) = text(
|
||||||
@ -90,12 +104,12 @@ pub fn sans(
|
|||||||
///
|
///
|
||||||
/// (The box is not conceptually necessary, but unfortunately currently needed
|
/// (The box is not conceptually necessary, but unfortunately currently needed
|
||||||
/// due to limitations in Typst's text style handling in math.)
|
/// due to limitations in Typst's text style handling in math.)
|
||||||
#[func(title = "Calligraphic", keywords = ["mathcal", "mathscr"])]
|
#[func(title = "Script", keywords = ["mathscr", "roundhand"])]
|
||||||
pub fn cal(
|
pub fn scr(
|
||||||
/// The content to style.
|
/// The content to style.
|
||||||
body: Content,
|
body: Content,
|
||||||
) -> Content {
|
) -> Content {
|
||||||
body.styled(EquationElem::set_variant(Some(MathVariant::Script)))
|
body.styled(EquationElem::set_variant(Some(MathVariant::Roundhand)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fraktur font style in math.
|
/// Fraktur font style in math.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
title: Variants
|
title: Variants
|
||||||
category: math
|
category: math
|
||||||
path: ["math"]
|
path: ["math"]
|
||||||
filter: ["serif", "sans", "frak", "mono", "bb", "cal"]
|
filter: ["serif", "sans", "frak", "mono", "bb", "cal", "scr"]
|
||||||
details: |
|
details: |
|
||||||
Alternate typefaces within formulas.
|
Alternate typefaces within formulas.
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 296 B After Width: | Height: | Size: 489 B |
@ -47,7 +47,8 @@ $bb(Gamma) , bb(gamma), bb(Pi), bb(pi), bb(sum)$
|
|||||||
|
|
||||||
--- math-style-hebrew-exceptions ---
|
--- math-style-hebrew-exceptions ---
|
||||||
// Test hebrew exceptions.
|
// Test hebrew exceptions.
|
||||||
$aleph, beth, gimel, daleth$
|
$aleph, beth, gimel, daleth$ \
|
||||||
|
$upright(aleph), upright(beth), upright(gimel), upright(daleth)$
|
||||||
|
|
||||||
--- issue-3650-italic-equation ---
|
--- issue-3650-italic-equation ---
|
||||||
_abc $sin(x) "abc"$_ \
|
_abc $sin(x) "abc"$_ \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user