mirror of
https://github.com/typst/typst
synced 2025-05-16 10:05:28 +08:00
Add delim-size
parameter to mat
, vec
, and cases
Takes either a function or a relative length, just like with `lr`, `stretch`, and `accent` which was changed in the previous two commits. The short fall was changed in the first commit, so no test updates here. The default is now much clearer to the user: `x => x * 1.1 - 0.1em`.
This commit is contained in:
parent
92d06fbd9a
commit
b30a38046c
@ -1,14 +1,13 @@
|
|||||||
use typst_library::diag::SourceResult;
|
use typst_library::diag::SourceResult;
|
||||||
use typst_library::foundations::{Content, Packed, Resolve, StyleChain, SymbolElem};
|
use typst_library::foundations::{Content, Packed, Resolve, StyleChain, SymbolElem};
|
||||||
use typst_library::layout::{Em, Frame, FrameItem, Point, Size};
|
use typst_library::layout::{Em, Frame, FrameItem, Point, Size};
|
||||||
use typst_library::math::{BinomElem, FracElem};
|
use typst_library::math::{BinomElem, FracElem, DELIM_SHORT_FALL};
|
||||||
use typst_library::text::TextElem;
|
use typst_library::text::TextElem;
|
||||||
use typst_library::visualize::{FixedStroke, Geometry};
|
use typst_library::visualize::{FixedStroke, Geometry};
|
||||||
use typst_syntax::Span;
|
use typst_syntax::Span;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
style_for_denominator, style_for_numerator, FrameFragment, GlyphFragment,
|
style_for_denominator, style_for_numerator, FrameFragment, GlyphFragment, MathContext,
|
||||||
MathContext, DELIM_SHORT_FALL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const FRAC_AROUND: Em = Em::new(0.1);
|
const FRAC_AROUND: Em = Em::new(0.1);
|
||||||
@ -49,7 +48,7 @@ fn layout_frac_like(
|
|||||||
binom: bool,
|
binom: bool,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
let short_fall = DELIM_SHORT_FALL.resolve(styles);
|
let short_fall = DELIM_SHORT_FALL.abs().resolve(styles);
|
||||||
let axis = scaled!(ctx, styles, axis_height);
|
let axis = scaled!(ctx, styles, axis_height);
|
||||||
let thickness = scaled!(ctx, styles, fraction_rule_thickness);
|
let thickness = scaled!(ctx, styles, fraction_rule_thickness);
|
||||||
let shift_up = scaled!(
|
let shift_up = scaled!(
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
use typst_library::diag::{bail, warning, SourceResult};
|
use typst_library::diag::{bail, warning, SourceResult};
|
||||||
use typst_library::foundations::{Content, Packed, Resolve, StyleChain};
|
use typst_library::foundations::{Content, Packed, Resolve, StyleChain};
|
||||||
use typst_library::layout::{
|
use typst_library::layout::{
|
||||||
Abs, Axes, Em, FixedAlignment, Frame, FrameItem, Point, Ratio, Rel, Size,
|
Abs, Axes, Em, FixedAlignment, Frame, FrameItem, Point, Rel, Size,
|
||||||
|
};
|
||||||
|
use typst_library::math::{
|
||||||
|
Augment, AugmentOffsets, CasesElem, MatElem, StretchSize, VecElem,
|
||||||
};
|
};
|
||||||
use typst_library::math::{Augment, AugmentOffsets, CasesElem, MatElem, VecElem};
|
|
||||||
use typst_library::text::TextElem;
|
use typst_library::text::TextElem;
|
||||||
use typst_library::visualize::{FillRule, FixedStroke, Geometry, LineCap, Shape};
|
use typst_library::visualize::{FillRule, FixedStroke, Geometry, LineCap, Shape};
|
||||||
use typst_syntax::Span;
|
use typst_syntax::Span;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
alignments, delimiter_alignment, style_for_denominator, AlignmentResult,
|
alignments, delimiter_alignment, style_for_denominator, AlignmentResult,
|
||||||
FrameFragment, GlyphFragment, LeftRightAlternator, MathContext, DELIM_SHORT_FALL,
|
FrameFragment, GlyphFragment, LeftRightAlternator, MathContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
const VERTICAL_PADDING: Ratio = Ratio::new(0.1);
|
|
||||||
const DEFAULT_STROKE_THICKNESS: Em = Em::new(0.05);
|
const DEFAULT_STROKE_THICKNESS: Em = Em::new(0.05);
|
||||||
|
|
||||||
/// Lays out a [`VecElem`].
|
/// Lays out a [`VecElem`].
|
||||||
@ -39,7 +40,15 @@ pub fn layout_vec(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let delim = elem.delim(styles);
|
let delim = elem.delim(styles);
|
||||||
layout_delimiters(ctx, styles, frame, delim.open(), delim.close(), span)
|
layout_delimiters(
|
||||||
|
ctx,
|
||||||
|
styles,
|
||||||
|
frame,
|
||||||
|
elem.delim_size(styles),
|
||||||
|
delim.open(),
|
||||||
|
delim.close(),
|
||||||
|
span,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lays out a [`CasesElem`].
|
/// Lays out a [`CasesElem`].
|
||||||
@ -67,7 +76,7 @@ pub fn layout_cases(
|
|||||||
let delim = elem.delim(styles);
|
let delim = elem.delim(styles);
|
||||||
let (open, close) =
|
let (open, close) =
|
||||||
if elem.reverse(styles) { (None, delim.close()) } else { (delim.open(), None) };
|
if elem.reverse(styles) { (None, delim.close()) } else { (delim.open(), None) };
|
||||||
layout_delimiters(ctx, styles, frame, open, close, span)
|
layout_delimiters(ctx, styles, frame, elem.delim_size(styles), open, close, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lays out a [`MatElem`].
|
/// Lays out a [`MatElem`].
|
||||||
@ -125,7 +134,15 @@ pub fn layout_mat(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let delim = elem.delim(styles);
|
let delim = elem.delim(styles);
|
||||||
layout_delimiters(ctx, styles, frame, delim.open(), delim.close(), span)
|
layout_delimiters(
|
||||||
|
ctx,
|
||||||
|
styles,
|
||||||
|
frame,
|
||||||
|
elem.delim_size(styles),
|
||||||
|
delim.open(),
|
||||||
|
delim.close(),
|
||||||
|
span,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Layout the inner contents of a matrix, vector, or cases.
|
/// Layout the inner contents of a matrix, vector, or cases.
|
||||||
@ -302,19 +319,23 @@ fn layout_delimiters(
|
|||||||
ctx: &mut MathContext,
|
ctx: &mut MathContext,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
mut frame: Frame,
|
mut frame: Frame,
|
||||||
|
size: StretchSize,
|
||||||
left: Option<char>,
|
left: Option<char>,
|
||||||
right: Option<char>,
|
right: Option<char>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
let short_fall = DELIM_SHORT_FALL.resolve(styles);
|
|
||||||
let axis = scaled!(ctx, styles, axis_height);
|
let axis = scaled!(ctx, styles, axis_height);
|
||||||
let height = frame.height();
|
let height = frame.height();
|
||||||
let target = height + VERTICAL_PADDING.of(height);
|
|
||||||
frame.set_baseline(height / 2.0 + axis);
|
frame.set_baseline(height / 2.0 + axis);
|
||||||
|
|
||||||
|
let target = size.resolve(ctx.engine, styles, height)?;
|
||||||
|
|
||||||
if let Some(left) = left {
|
if let Some(left) = left {
|
||||||
let mut left = GlyphFragment::new(ctx, styles, left, span)
|
let mut left = GlyphFragment::new(ctx, styles, left, span).stretch_vertical(
|
||||||
.stretch_vertical(ctx, target, short_fall);
|
ctx,
|
||||||
|
target,
|
||||||
|
Abs::zero(),
|
||||||
|
);
|
||||||
left.align_on_axis(ctx, delimiter_alignment(left.c));
|
left.align_on_axis(ctx, delimiter_alignment(left.c));
|
||||||
ctx.push(left);
|
ctx.push(left);
|
||||||
}
|
}
|
||||||
@ -322,8 +343,11 @@ fn layout_delimiters(
|
|||||||
ctx.push(FrameFragment::new(styles, frame));
|
ctx.push(FrameFragment::new(styles, frame));
|
||||||
|
|
||||||
if let Some(right) = right {
|
if let Some(right) = right {
|
||||||
let mut right = GlyphFragment::new(ctx, styles, right, span)
|
let mut right = GlyphFragment::new(ctx, styles, right, span).stretch_vertical(
|
||||||
.stretch_vertical(ctx, target, short_fall);
|
ctx,
|
||||||
|
target,
|
||||||
|
Abs::zero(),
|
||||||
|
);
|
||||||
right.align_on_axis(ctx, delimiter_alignment(right.c));
|
right.align_on_axis(ctx, delimiter_alignment(right.c));
|
||||||
ctx.push(right);
|
ctx.push(right);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use ttf_parser::math::MathValue;
|
use ttf_parser::math::MathValue;
|
||||||
use typst_library::foundations::{Style, StyleChain};
|
use typst_library::foundations::{Style, StyleChain};
|
||||||
use typst_library::layout::{Abs, Em, FixedAlignment, Frame, Point, Size, VAlignment};
|
use typst_library::layout::{Abs, FixedAlignment, Frame, Point, Size, VAlignment};
|
||||||
use typst_library::math::{EquationElem, MathSize};
|
use typst_library::math::{EquationElem, MathSize};
|
||||||
use typst_utils::LazyHash;
|
use typst_utils::LazyHash;
|
||||||
|
|
||||||
@ -28,9 +28,6 @@ macro_rules! percent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How much less high scaled delimiters can be than what they wrap.
|
|
||||||
pub const DELIM_SHORT_FALL: Em = Em::new(0.1);
|
|
||||||
|
|
||||||
/// Converts some unit to an absolute length with the current font & font size.
|
/// Converts some unit to an absolute length with the current font & font size.
|
||||||
pub trait Scaled {
|
pub trait Scaled {
|
||||||
fn scaled(self, ctx: &MathContext, font_size: Abs) -> Abs;
|
fn scaled(self, ctx: &MathContext, font_size: Abs) -> Abs;
|
||||||
|
@ -2,7 +2,7 @@ use crate::foundations::{elem, func, Content, NativeElement, NativeFunc, SymbolE
|
|||||||
use crate::layout::{Em, Length, Ratio, Rel};
|
use crate::layout::{Em, Length, Ratio, Rel};
|
||||||
use crate::math::{Mathy, StretchSize};
|
use crate::math::{Mathy, StretchSize};
|
||||||
|
|
||||||
const DELIM_SHORT_FALL: Em = Em::new(-0.1);
|
pub const DELIM_SHORT_FALL: Em = Em::new(-0.1);
|
||||||
|
|
||||||
#[func(name = "x => x - 0.1em")]
|
#[func(name = "x => x - 0.1em")]
|
||||||
pub const fn default_lr_size(base: Length) -> Rel {
|
pub const fn default_lr_size(base: Length) -> Rel {
|
||||||
|
@ -5,15 +5,27 @@ use unicode_math_class::MathClass;
|
|||||||
|
|
||||||
use crate::diag::{bail, At, HintedStrResult, StrResult};
|
use crate::diag::{bail, At, HintedStrResult, StrResult};
|
||||||
use crate::foundations::{
|
use crate::foundations::{
|
||||||
array, cast, dict, elem, Array, Content, Dict, Fold, NoneValue, Resolve, Smart,
|
array, cast, dict, elem, func, Array, Content, Dict, Fold, NativeFunc, NoneValue,
|
||||||
StyleChain, Symbol, Value,
|
Resolve, Smart, StyleChain, Symbol, Value,
|
||||||
};
|
};
|
||||||
use crate::layout::{Abs, Em, HAlignment, Length, Rel};
|
use crate::layout::{Abs, Em, HAlignment, Length, Ratio, Rel};
|
||||||
use crate::math::Mathy;
|
use crate::math::{Mathy, StretchSize, DELIM_SHORT_FALL};
|
||||||
use crate::visualize::Stroke;
|
use crate::visualize::Stroke;
|
||||||
|
|
||||||
const DEFAULT_ROW_GAP: Em = Em::new(0.2);
|
const DEFAULT_ROW_GAP: Em = Em::new(0.2);
|
||||||
const DEFAULT_COL_GAP: Em = Em::new(0.5);
|
const DEFAULT_COL_GAP: Em = Em::new(0.5);
|
||||||
|
const VERTICAL_PADDING: Ratio = Ratio::new(1.1);
|
||||||
|
|
||||||
|
#[func(name = "x => x * 1.1 - 0.1em")]
|
||||||
|
const fn default_mat_size(base: Length) -> Rel {
|
||||||
|
Rel {
|
||||||
|
rel: Ratio::zero(),
|
||||||
|
abs: Length {
|
||||||
|
abs: Abs::raw(base.abs.to_raw() * VERTICAL_PADDING.get()),
|
||||||
|
em: DELIM_SHORT_FALL,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A column vector.
|
/// A column vector.
|
||||||
///
|
///
|
||||||
@ -40,6 +52,13 @@ pub struct VecElem {
|
|||||||
#[default(DelimiterPair::PAREN)]
|
#[default(DelimiterPair::PAREN)]
|
||||||
pub delim: DelimiterPair,
|
pub delim: DelimiterPair,
|
||||||
|
|
||||||
|
/// The size of the delimiters, relative to the elements' total height.
|
||||||
|
///
|
||||||
|
/// See the [stretch documentation]($math.stretch.size) for more
|
||||||
|
/// information on sizes.
|
||||||
|
#[default(<default_mat_size>::data().into())]
|
||||||
|
pub delim_size: StretchSize,
|
||||||
|
|
||||||
/// The horizontal alignment that each element should have.
|
/// The horizontal alignment that each element should have.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
@ -101,6 +120,13 @@ pub struct MatElem {
|
|||||||
#[default(DelimiterPair::PAREN)]
|
#[default(DelimiterPair::PAREN)]
|
||||||
pub delim: DelimiterPair,
|
pub delim: DelimiterPair,
|
||||||
|
|
||||||
|
/// The size of the delimiters, relative to the cells' total height.
|
||||||
|
///
|
||||||
|
/// See the [stretch documentation]($math.stretch.size) for more
|
||||||
|
/// information on sizes.
|
||||||
|
#[default(<default_mat_size>::data().into())]
|
||||||
|
pub delim_size: StretchSize,
|
||||||
|
|
||||||
/// The horizontal alignment that each cell should have.
|
/// The horizontal alignment that each cell should have.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
@ -244,6 +270,13 @@ pub struct CasesElem {
|
|||||||
#[default(DelimiterPair::BRACE)]
|
#[default(DelimiterPair::BRACE)]
|
||||||
pub delim: DelimiterPair,
|
pub delim: DelimiterPair,
|
||||||
|
|
||||||
|
/// The size of the delimiters, relative to the branches' total height.
|
||||||
|
///
|
||||||
|
/// See the [stretch documentation]($math.stretch.size) for more
|
||||||
|
/// information on sizes.
|
||||||
|
#[default(<default_mat_size>::data().into())]
|
||||||
|
pub delim_size: StretchSize,
|
||||||
|
|
||||||
/// Whether the direction of cases should be reversed.
|
/// Whether the direction of cases should be reversed.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
|
BIN
tests/ref/math-cases-delim-size.png
Normal file
BIN
tests/ref/math-cases-delim-size.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1005 B |
BIN
tests/ref/math-mat-delim-size.png
Normal file
BIN
tests/ref/math-mat-delim-size.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
tests/ref/math-vec-delim-size.png
Normal file
BIN
tests/ref/math-vec-delim-size.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
@ -16,6 +16,12 @@ $ x = cases(1, 2) $
|
|||||||
#set math.cases(delim: sym.angle.l)
|
#set math.cases(delim: sym.angle.l)
|
||||||
$ cases(a, b, c) $
|
$ cases(a, b, c) $
|
||||||
|
|
||||||
|
--- math-cases-delim-size ---
|
||||||
|
// Test setting delimiter size.
|
||||||
|
$ cases(reverse: #true, 1, 2, 3) cases(delim-size: #100%, 1, 2, 3) $
|
||||||
|
#set math.cases(delim-size: x => calc.max(x - 5pt, x * 0.901))
|
||||||
|
$ cases(1, 2) cases(1, 2, 3, 4) $
|
||||||
|
|
||||||
--- math-cases-linebreaks ---
|
--- math-cases-linebreaks ---
|
||||||
// Warning: 40-49 linebreaks are ignored in branches
|
// Warning: 40-49 linebreaks are ignored in branches
|
||||||
// Hint: 40-49 use commas instead to separate each line
|
// Hint: 40-49 use commas instead to separate each line
|
||||||
|
@ -54,6 +54,12 @@ $ a + mat(delim: #none, 1, 2; 3, 4) + b $
|
|||||||
$ mat(1, 2; 3, 4; delim: "[") $,
|
$ mat(1, 2; 3, 4; delim: "[") $,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
--- math-mat-delim-size ---
|
||||||
|
// Test setting delimiter size.
|
||||||
|
$ mat(c; c; c) mat(delim-size: #100%, c; c; c) $
|
||||||
|
#set math.mat(delim-size: x => calc.max(x - 5pt, x * 0.901))
|
||||||
|
$ mat(delim: "[", f; f; f; f) mat(delim: ||, x; x; x; x) $
|
||||||
|
|
||||||
--- math-mat-spread ---
|
--- math-mat-spread ---
|
||||||
// Test argument spreading in matrix.
|
// Test argument spreading in matrix.
|
||||||
$ mat(..#range(1, 5).chunks(2))
|
$ mat(..#range(1, 5).chunks(2))
|
||||||
@ -263,7 +269,7 @@ $ mat(a; b; c) mat(a \ b \ c) $
|
|||||||
--- math-mat-vec-cases-unity ---
|
--- math-mat-vec-cases-unity ---
|
||||||
// Test that matrices, vectors, and cases are all laid out the same.
|
// Test that matrices, vectors, and cases are all laid out the same.
|
||||||
$ mat(z_(n_p); a^2)
|
$ mat(z_(n_p); a^2)
|
||||||
vec(z_(n_p), a^2)
|
vec(z_(n_p), a^2)
|
||||||
cases(reverse: #true, delim: \(, z_(n_p), a^2)
|
cases(reverse: #true, delim: \(, z_(n_p), a^2)
|
||||||
cases(delim: \(, z_(n_p), a^2) $
|
cases(delim: \(, z_(n_p), a^2) $
|
||||||
|
|
||||||
|
@ -50,6 +50,12 @@ $ vec(1, 2) $
|
|||||||
// Error: 22-33 invalid delimiter: "%"
|
// Error: 22-33 invalid delimiter: "%"
|
||||||
#set math.vec(delim: (none, "%"))
|
#set math.vec(delim: (none, "%"))
|
||||||
|
|
||||||
|
--- math-vec-delim-size ---
|
||||||
|
// Test setting delimiter size.
|
||||||
|
$ vec(1, 2, 3) vec(delim-size: #100%, 1, 2, 3) $
|
||||||
|
#set math.vec(delim-size: x => calc.max(x - 5pt, x * 0.901))
|
||||||
|
$ vec(delim: "{", 1, 2, 3) vec(delim: "[", 1, 2, 3) $
|
||||||
|
|
||||||
--- math-vec-linebreaks ---
|
--- math-vec-linebreaks ---
|
||||||
// Warning: 20-29 linebreaks are ignored in elements
|
// Warning: 20-29 linebreaks are ignored in elements
|
||||||
// Hint: 20-29 use commas instead to separate each line
|
// Hint: 20-29 use commas instead to separate each line
|
||||||
|
Loading…
x
Reference in New Issue
Block a user