summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-01-22 13:30:59 +0100
committerLaurenz <laurmaedje@gmail.com>2023-01-22 13:30:59 +0100
commit203d5779f804532f9fe76da9c00765434bf1b357 (patch)
treeefb822dbc705169ca7a1de97e7f39e3f3daffce7 /library
parent57a636b3704e7002b0f895c0945ec2f720d75584 (diff)
Fraction layout
Diffstat (limited to 'library')
-rw-r--r--library/src/math/frac.rs101
-rw-r--r--library/src/math/mod.rs1
2 files changed, 84 insertions, 18 deletions
diff --git a/library/src/math/frac.rs b/library/src/math/frac.rs
index f3edf852..50a68fea 100644
--- a/library/src/math/frac.rs
+++ b/library/src/math/frac.rs
@@ -25,7 +25,7 @@ use super::*;
/// ## Category
/// math
#[func]
-#[capable(Texify)]
+#[capable(LayoutMath)]
#[derive(Debug, Hash)]
pub struct FracNode {
/// The numerator.
@@ -43,14 +43,9 @@ impl FracNode {
}
}
-impl Texify for FracNode {
- fn texify(&self, t: &mut Texifier) -> SourceResult<()> {
- t.push_str("\\frac{");
- self.num.texify_unparen(t)?;
- t.push_str("}{");
- self.denom.texify_unparen(t)?;
- t.push_str("}");
- Ok(())
+impl LayoutMath for FracNode {
+ fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
+ layout(ctx, &self.num, &self.denom, false)
}
}
@@ -72,7 +67,7 @@ impl Texify for FracNode {
/// ## Category
/// math
#[func]
-#[capable(Texify)]
+#[capable(LayoutMath)]
#[derive(Debug, Hash)]
pub struct BinomNode {
/// The upper index.
@@ -90,13 +85,83 @@ impl BinomNode {
}
}
-impl Texify for BinomNode {
- fn texify(&self, t: &mut Texifier) -> SourceResult<()> {
- t.push_str("\\binom{");
- self.upper.texify(t)?;
- t.push_str("}{");
- self.lower.texify(t)?;
- t.push_str("}");
- Ok(())
+impl LayoutMath for BinomNode {
+ fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
+ layout(ctx, &self.upper, &self.lower, true)
}
}
+
+/// Layout a fraction or binomial.
+fn layout(
+ ctx: &mut MathContext,
+ num: &Content,
+ denom: &Content,
+ binom: bool,
+) -> SourceResult<()> {
+ let axis = scaled!(ctx, axis_height);
+ let thickness = scaled!(ctx, fraction_rule_thickness);
+ let shift_up = scaled!(
+ ctx,
+ text: fraction_numerator_shift_up,
+ display: fraction_numerator_display_style_shift_up,
+ );
+ let shift_down = scaled!(
+ ctx,
+ text: fraction_denominator_shift_down,
+ display: fraction_denominator_display_style_shift_down,
+ );
+ let num_min = scaled!(
+ ctx,
+ text: fraction_numerator_gap_min,
+ display: fraction_num_display_style_gap_min,
+ );
+ let denom_min = scaled!(
+ ctx,
+ text: fraction_denominator_gap_min,
+ display: fraction_denom_display_style_gap_min,
+ );
+
+ ctx.style(ctx.style.for_numerator());
+ let num = ctx.layout_frame(num)?;
+ ctx.unstyle();
+
+ ctx.style(ctx.style.for_denominator());
+ let denom = ctx.layout_frame(denom)?;
+ ctx.unstyle();
+
+ let around = Em::new(0.1).scaled(ctx);
+ let num_gap = (shift_up - axis - num.descent()).max(num_min + thickness / 2.0);
+ let denom_gap = (shift_down + axis - denom.ascent()).max(denom_min + thickness / 2.0);
+
+ let line_width = num.width().max(denom.width());
+ let width = line_width + 2.0 * around;
+ let height = num.height() + num_gap + thickness + denom_gap + denom.height();
+ let size = Size::new(width, height);
+ let num_pos = Point::with_x((width - num.width()) / 2.0);
+ let line_pos =
+ Point::new((width - line_width) / 2.0, num.height() + num_gap + thickness / 2.0);
+ let denom_pos = Point::new((width - denom.width()) / 2.0, height - denom.height());
+ let baseline = line_pos.y + axis;
+
+ let mut frame = Frame::new(size);
+ frame.set_baseline(baseline);
+ frame.push_frame(num_pos, num);
+ frame.push_frame(denom_pos, denom);
+
+ if binom {
+ ctx.push(GlyphFragment::new(ctx, '('));
+ ctx.push(frame);
+ ctx.push(GlyphFragment::new(ctx, ')'));
+ } else {
+ frame.push(
+ line_pos,
+ Element::Shape(
+ Geometry::Line(Point::with_x(line_width))
+ .stroked(Stroke { paint: ctx.fill, thickness }),
+ ),
+ );
+ ctx.push(frame);
+ }
+
+ Ok(())
+}
diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs
index e3fc13f6..de954fbf 100644
--- a/library/src/math/mod.rs
+++ b/library/src/math/mod.rs
@@ -47,6 +47,7 @@ use crate::text::{families, variant, FallbackList, FontFamily, SpaceNode, Symbol
pub fn define(scope: &mut Scope) {
scope.def_func::<MathNode>("math");
scope.def_func::<FracNode>("frac");
+ scope.def_func::<BinomNode>("binom");
scope.def_func::<ScriptNode>("script");
scope.def_func::<SqrtNode>("sqrt");
scope.def_func::<RootNode>("root");