mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Add gap
and justify
parameters to repeat
(#4644)
Co-authored-by: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
parent
d221a89a40
commit
4853726e5b
@ -5,7 +5,7 @@ use crate::foundations::{
|
||||
};
|
||||
use crate::introspection::Locator;
|
||||
use crate::layout::{
|
||||
Abs, AlignElem, Axes, BlockElem, Frame, Point, Region, Regions, Size,
|
||||
Abs, AlignElem, Axes, BlockElem, Frame, Length, Point, Region, Regions, Size,
|
||||
};
|
||||
use crate::utils::Numeric;
|
||||
|
||||
@ -14,7 +14,7 @@ use crate::utils::Numeric;
|
||||
/// This can be useful when implementing a custom index, reference, or outline.
|
||||
///
|
||||
/// Space may be inserted between the instances of the body parameter, so be
|
||||
/// sure to include negative space if you need the instances to overlap.
|
||||
/// sure to adjust the [`justify`]($repeat.justify) parameter accordingly.
|
||||
///
|
||||
/// Errors if there no bounds on the available space, as it would create
|
||||
/// infinite content.
|
||||
@ -35,6 +35,15 @@ pub struct RepeatElem {
|
||||
/// The content to repeat.
|
||||
#[required]
|
||||
pub body: Content,
|
||||
|
||||
/// The gap between each instance of the body.
|
||||
#[default]
|
||||
pub gap: Length,
|
||||
|
||||
/// Whether to increase the gap between instances to completely fill the
|
||||
/// available space.
|
||||
#[default(true)]
|
||||
pub justify: bool,
|
||||
}
|
||||
|
||||
impl Show for Packed<RepeatElem> {
|
||||
@ -56,15 +65,6 @@ fn layout_repeat(
|
||||
) -> SourceResult<Frame> {
|
||||
let pod = Regions::one(region.size, Axes::new(false, false));
|
||||
let piece = elem.body().layout(engine, locator, styles, pod)?.into_frame();
|
||||
|
||||
let align = AlignElem::alignment_in(styles).resolve(styles);
|
||||
|
||||
let fill = region.size.x;
|
||||
let width = piece.width();
|
||||
let count = (fill / width).floor();
|
||||
let remaining = fill % width;
|
||||
let apart = remaining / (count - 1.0);
|
||||
|
||||
let size = Size::new(region.size.x, piece.height());
|
||||
|
||||
if !size.is_finite() {
|
||||
@ -76,15 +76,30 @@ fn layout_repeat(
|
||||
frame.set_baseline(piece.baseline());
|
||||
}
|
||||
|
||||
let mut gap = elem.gap(styles).resolve(styles);
|
||||
let fill = region.size.x;
|
||||
let width = piece.width();
|
||||
|
||||
// count * width + (count - 1) * gap = fill, but count is an integer so
|
||||
// we need to round down and get the remainder.
|
||||
let count = ((fill + gap) / (width + gap)).floor();
|
||||
let remaining = (fill + gap) % (width + gap);
|
||||
|
||||
let justify = elem.justify(styles);
|
||||
if justify {
|
||||
gap += remaining / (count - 1.0);
|
||||
}
|
||||
|
||||
let align = AlignElem::alignment_in(styles).resolve(styles);
|
||||
let mut offset = Abs::zero();
|
||||
if count == 1.0 {
|
||||
if count == 1.0 || !justify {
|
||||
offset += align.x.position(remaining);
|
||||
}
|
||||
|
||||
if width > Abs::zero() {
|
||||
for _ in 0..(count as usize).min(1000) {
|
||||
frame.push_frame(Point::with_x(offset), piece.clone());
|
||||
offset += piece.width() + apart;
|
||||
offset += piece.width() + gap;
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
tests/ref/repeat-gap.png
Normal file
BIN
tests/ref/repeat-gap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 293 B |
BIN
tests/ref/repeat-no-justify-align.png
Normal file
BIN
tests/ref/repeat-no-justify-align.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
BIN
tests/ref/repeat-no-justify.png
Normal file
BIN
tests/ref/repeat-no-justify.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
@ -42,3 +42,18 @@ A#box(width: 1fr, repeat(rect(width: 6em, height: 0.7em)))B
|
||||
// Error: 2:2-2:13 repeat with no size restrictions
|
||||
#set page(width: auto)
|
||||
#repeat(".")
|
||||
|
||||
--- repeat-gap ---
|
||||
// Test repeat with custom gap.
|
||||
A#box(width: 1fr, repeat(rect(width: 2em, height: 1em), gap: 1em))B
|
||||
|
||||
--- repeat-no-justify ---
|
||||
// Test repeat with disabled justification.
|
||||
#set repeat(justify: false)
|
||||
A#box(width: 1fr, repeat(rect(width: 2em, height: 1em), gap: 1em))B
|
||||
|
||||
--- repeat-no-justify-align ---
|
||||
// Test repeat with alignment and disabled justification.
|
||||
#set repeat(justify: false)
|
||||
#set align(right)
|
||||
A#box(width: 1fr, repeat(rect(width: 2em, height: 1em), gap: 1em))B
|
||||
|
Loading…
x
Reference in New Issue
Block a user