mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Equation numbering
This commit is contained in:
parent
a69b587455
commit
c7f4d6b12e
@ -39,6 +39,9 @@ use self::fragment::*;
|
|||||||
use self::row::*;
|
use self::row::*;
|
||||||
use self::spacing::*;
|
use self::spacing::*;
|
||||||
use crate::layout::{HNode, ParNode, Spacing};
|
use crate::layout::{HNode, ParNode, Spacing};
|
||||||
|
use crate::meta::{
|
||||||
|
Count, Counter, CounterAction, CounterNode, CounterUpdate, LocalName, Numbering,
|
||||||
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::text::{
|
use crate::text::{
|
||||||
families, variant, FontFamily, FontList, LinebreakNode, SpaceNode, TextNode, TextSize,
|
families, variant, FontFamily, FontList, LinebreakNode, SpaceNode, TextNode, TextSize,
|
||||||
@ -132,17 +135,37 @@ pub fn module() -> Module {
|
|||||||
///
|
///
|
||||||
/// Display: Equation
|
/// Display: Equation
|
||||||
/// Category: math
|
/// Category: math
|
||||||
#[node(Show, Finalize, Layout, LayoutMath)]
|
#[node(Locatable, Synthesize, Show, Finalize, Layout, LayoutMath, Count, LocalName)]
|
||||||
pub struct EquationNode {
|
pub struct EquationNode {
|
||||||
/// Whether the equation is displayed as a separate block.
|
/// Whether the equation is displayed as a separate block.
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
pub block: bool,
|
pub block: bool,
|
||||||
|
|
||||||
|
/// How to [number]($func/numbering) block-level equations.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// #set math.equation(numbering: "(1)")
|
||||||
|
///
|
||||||
|
/// We define:
|
||||||
|
/// $ phi.alt := (1 + sqrt(5)) / 2 $ <ratio>
|
||||||
|
///
|
||||||
|
/// With @ratio, we get:
|
||||||
|
/// $ F_n = floor(1 / sqrt(5) phi.alt^n) $
|
||||||
|
/// ```
|
||||||
|
pub numbering: Option<Numbering>,
|
||||||
|
|
||||||
/// The contents of the equation.
|
/// The contents of the equation.
|
||||||
#[required]
|
#[required]
|
||||||
pub body: Content,
|
pub body: Content,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Synthesize for EquationNode {
|
||||||
|
fn synthesize(&mut self, _: &Vt, styles: StyleChain) {
|
||||||
|
self.push_block(self.block(styles));
|
||||||
|
self.push_numbering(self.numbering(styles));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Show for EquationNode {
|
impl Show for EquationNode {
|
||||||
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
|
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
|
||||||
let mut realized = self.clone().pack().guarded(Guard::Base(NodeId::of::<Self>()));
|
let mut realized = self.clone().pack().guarded(Guard::Base(NodeId::of::<Self>()));
|
||||||
@ -170,6 +193,8 @@ impl Layout for EquationNode {
|
|||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
regions: Regions,
|
regions: Regions,
|
||||||
) -> SourceResult<Fragment> {
|
) -> SourceResult<Fragment> {
|
||||||
|
const NUMBER_GUTTER: Em = Em::new(0.5);
|
||||||
|
|
||||||
let block = self.block(styles);
|
let block = self.block(styles);
|
||||||
|
|
||||||
// Find a math font.
|
// Find a math font.
|
||||||
@ -189,7 +214,34 @@ impl Layout for EquationNode {
|
|||||||
let mut ctx = MathContext::new(vt, styles, regions, &font, block);
|
let mut ctx = MathContext::new(vt, styles, regions, &font, block);
|
||||||
let mut frame = ctx.layout_frame(self)?;
|
let mut frame = ctx.layout_frame(self)?;
|
||||||
|
|
||||||
if !block {
|
if block {
|
||||||
|
if let Some(numbering) = self.numbering(styles) {
|
||||||
|
let pod = Regions::one(regions.base(), Axes::splat(false));
|
||||||
|
let counter = CounterNode::new(
|
||||||
|
Counter::of(Self::id()),
|
||||||
|
CounterAction::Get(numbering),
|
||||||
|
);
|
||||||
|
|
||||||
|
let sub = counter.pack().layout(vt, styles, pod)?.into_frame();
|
||||||
|
let width = if regions.size.x.is_finite() {
|
||||||
|
regions.size.x
|
||||||
|
} else {
|
||||||
|
frame.width() + 2.0 * (sub.width() + NUMBER_GUTTER.resolve(styles))
|
||||||
|
};
|
||||||
|
|
||||||
|
let height = frame.height().max(sub.height());
|
||||||
|
frame.resize(Size::new(width, height), Align::CENTER_HORIZON);
|
||||||
|
|
||||||
|
let x = if TextNode::dir_in(styles).is_positive() {
|
||||||
|
frame.width() - sub.width()
|
||||||
|
} else {
|
||||||
|
Abs::zero()
|
||||||
|
};
|
||||||
|
let y = (frame.height() - sub.height()) / 2.0;
|
||||||
|
|
||||||
|
frame.push_frame(Point::new(x, y), sub)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let slack = ParNode::leading_in(styles) * 0.7;
|
let slack = ParNode::leading_in(styles) * 0.7;
|
||||||
let top_edge = TextNode::top_edge_in(styles).resolve(styles, font.metrics());
|
let top_edge = TextNode::top_edge_in(styles).resolve(styles, font.metrics());
|
||||||
let bottom_edge =
|
let bottom_edge =
|
||||||
@ -205,6 +257,23 @@ impl Layout for EquationNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Count for EquationNode {
|
||||||
|
fn update(&self) -> Option<CounterUpdate> {
|
||||||
|
(self.block(StyleChain::default())
|
||||||
|
&& self.numbering(StyleChain::default()).is_some())
|
||||||
|
.then(|| CounterUpdate::Step(NonZeroUsize::ONE))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LocalName for EquationNode {
|
||||||
|
fn local_name(&self, lang: Lang) -> &'static str {
|
||||||
|
match lang {
|
||||||
|
Lang::GERMAN => "Gleichung",
|
||||||
|
Lang::ENGLISH | _ => "Equation",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait LayoutMath {
|
pub trait LayoutMath {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()>;
|
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()>;
|
||||||
}
|
}
|
||||||
|
BIN
tests/ref/math/numbering.png
Normal file
BIN
tests/ref/math/numbering.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
11
tests/typ/math/numbering.typ
Normal file
11
tests/typ/math/numbering.typ
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Test equation numbering.
|
||||||
|
|
||||||
|
---
|
||||||
|
#set page(width: 150pt)
|
||||||
|
#set math.equation(numbering: "(I)")
|
||||||
|
|
||||||
|
We define $x$ in preparation of @fib:
|
||||||
|
$ phi.alt := (1 + sqrt(5)) / 2 $ <ratio>
|
||||||
|
|
||||||
|
With @ratio, we get
|
||||||
|
$ F_n = floor(1 / sqrt(5) phi.alt^n) $ <fib>
|
Loading…
x
Reference in New Issue
Block a user