Block sizing
This commit is contained in:
parent
72b60dfde7
commit
b1b4e52af9
@ -287,17 +287,17 @@ fn code_block(resolver: &dyn Resolver, lang: &str, text: &str) -> Html {
|
||||
|
||||
let source = Source::new(SourceId::from_u16(0), Path::new("main.typ"), compile);
|
||||
let world = DocWorld(source);
|
||||
let mut frame = match typst::compile(&world, &world.0) {
|
||||
Ok(doc) => doc.pages.into_iter().next().unwrap(),
|
||||
let mut frames = match typst::compile(&world, &world.0) {
|
||||
Ok(doc) => doc.pages,
|
||||
Err(err) => panic!("failed to compile {text}: {err:?}"),
|
||||
};
|
||||
|
||||
if let Some([x, y, w, h]) = zoom {
|
||||
frame.translate(Point::new(-x, -y));
|
||||
*frame.size_mut() = Size::new(w, h);
|
||||
frames[0].translate(Point::new(-x, -y));
|
||||
*frames[0].size_mut() = Size::new(w, h);
|
||||
}
|
||||
|
||||
resolver.example(highlighted, frame)
|
||||
resolver.example(highlighted, &frames)
|
||||
}
|
||||
|
||||
/// World for example compilations.
|
||||
|
@ -67,7 +67,7 @@ pub trait Resolver {
|
||||
fn image(&self, filename: &str, data: &[u8]) -> String;
|
||||
|
||||
/// Produce HTML for an example.
|
||||
fn example(&self, source: Html, frame: Frame) -> Html;
|
||||
fn example(&self, source: Html, frames: &[Frame]) -> Html;
|
||||
}
|
||||
|
||||
/// Details about a documentation page and its children.
|
||||
|
@ -41,20 +41,13 @@ use crate::prelude::*;
|
||||
/// - height: `Rel<Length>` (named)
|
||||
/// The height of the box.
|
||||
///
|
||||
/// - baseline: `Rel<Length>` (named)
|
||||
/// An amount to shift the box's baseline by.
|
||||
///
|
||||
/// ```example
|
||||
/// Image: #box(baseline: 40%, image("tiger.jpg", width: 2cm)).
|
||||
/// ```
|
||||
///
|
||||
/// ## Category
|
||||
/// layout
|
||||
#[func]
|
||||
#[capable(Layout)]
|
||||
#[derive(Debug, Hash)]
|
||||
pub struct BoxNode {
|
||||
/// The content to be sized.
|
||||
/// The box's content.
|
||||
pub body: Content,
|
||||
/// The box's width.
|
||||
pub width: Sizing,
|
||||
@ -64,7 +57,11 @@ pub struct BoxNode {
|
||||
|
||||
#[node]
|
||||
impl BoxNode {
|
||||
/// The box's baseline shift.
|
||||
/// An amount to shift the box's baseline by.
|
||||
///
|
||||
/// ```example
|
||||
/// Image: #box(baseline: 40%, image("tiger.jpg", width: 2cm)).
|
||||
/// ```
|
||||
#[property(resolve)]
|
||||
pub const BASELINE: Rel<Length> = Rel::zero();
|
||||
|
||||
@ -127,11 +124,12 @@ impl Layout for BoxNode {
|
||||
|
||||
// Resolve the sizing to a concrete size.
|
||||
let sizing = Axes::new(width, self.height);
|
||||
let expand = sizing.as_ref().map(Smart::is_custom);
|
||||
let size = sizing
|
||||
.resolve(styles)
|
||||
.zip(regions.base())
|
||||
.map(|(s, b)| s.map(|v| v.relative_to(b)))
|
||||
.unwrap_or(regions.size);
|
||||
.unwrap_or(regions.base());
|
||||
|
||||
// Apply inset.
|
||||
let mut child = self.body.clone();
|
||||
@ -142,8 +140,6 @@ impl Layout for BoxNode {
|
||||
|
||||
// Select the appropriate base and expansion for the child depending
|
||||
// on whether it is automatically or relatively sized.
|
||||
let is_auto = sizing.as_ref().map(Smart::is_auto);
|
||||
let expand = regions.expand | !is_auto;
|
||||
let pod = Regions::one(size, expand);
|
||||
let mut frame = child.layout(vt, styles, pod)?.into_frame();
|
||||
|
||||
@ -181,9 +177,9 @@ impl Layout for BoxNode {
|
||||
///
|
||||
/// ## Examples
|
||||
/// With a block, you can give a background to content while still allowing it
|
||||
/// to break across multiple pages. The documentation examples can only have a
|
||||
/// single page, but the example below demonstrates how this would work.
|
||||
/// to break across multiple pages.
|
||||
/// ```example
|
||||
/// #set page(height: 100pt)
|
||||
/// #block(
|
||||
/// fill: luma(230),
|
||||
/// inset: 8pt,
|
||||
@ -204,27 +200,55 @@ impl Layout for BoxNode {
|
||||
/// More text.
|
||||
/// ```
|
||||
///
|
||||
/// Last but not least, set rules for the block function can be used to
|
||||
/// configure the spacing around arbitrary block-level elements.
|
||||
/// ```example
|
||||
/// #set align(center)
|
||||
/// #show math.formula: set block(above: 8pt, below: 16pt)
|
||||
///
|
||||
/// This sum of $x$ and $y$:
|
||||
/// $ x + y = z $
|
||||
/// A second paragraph.
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - body: `Content` (positional)
|
||||
/// The contents of the block.
|
||||
///
|
||||
/// - width: `Smart<Rel<Length>>` (named)
|
||||
/// The block's width.
|
||||
///
|
||||
/// ```example
|
||||
/// #set align(center)
|
||||
/// #block(
|
||||
/// width: 60%,
|
||||
/// inset: 8pt,
|
||||
/// fill: silver,
|
||||
/// lorem(10),
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// - height: `Smart<Rel<Length>>` (named)
|
||||
/// The block's height. When the height is larger than the remaining space on
|
||||
/// a page and [`breakable`]($func/block.breakable) is `{true}`, the block
|
||||
/// will continue on the next page with the remaining height.
|
||||
///
|
||||
/// ```example
|
||||
/// #set page(height: 80pt)
|
||||
/// #set align(center)
|
||||
/// #block(
|
||||
/// width: 80%,
|
||||
/// height: 150%,
|
||||
/// fill: aqua,
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// - spacing: `Spacing` (named, settable)
|
||||
/// The spacing around this block.
|
||||
/// The spacing around this block. This is shorthand to set `above` and
|
||||
/// `below` to the same value.
|
||||
///
|
||||
/// ```example
|
||||
/// #set align(center)
|
||||
/// #show math.formula: set block(above: 8pt, below: 16pt)
|
||||
///
|
||||
/// This sum of $x$ and $y$:
|
||||
/// $ x + y = z $
|
||||
/// A second paragraph.
|
||||
/// ```
|
||||
///
|
||||
/// - above: `Spacing` (named, settable)
|
||||
/// The spacing between this block and its predecessor. Takes precedence over
|
||||
/// `spacing`.
|
||||
/// `spacing`. Can be used in combination with a show rule to adjust the
|
||||
/// spacing around arbitrary block-level elements.
|
||||
///
|
||||
/// The default value is `{1.2em}`.
|
||||
///
|
||||
@ -240,11 +264,30 @@ impl Layout for BoxNode {
|
||||
#[capable(Layout)]
|
||||
#[derive(Debug, Hash)]
|
||||
pub struct BlockNode {
|
||||
/// The block's content.
|
||||
pub body: Content,
|
||||
/// The box's width.
|
||||
pub width: Smart<Rel<Length>>,
|
||||
/// The box's height.
|
||||
pub height: Smart<Rel<Length>>,
|
||||
}
|
||||
|
||||
#[node]
|
||||
impl BlockNode {
|
||||
/// Whether the block can be broken and continue on the next page.
|
||||
///
|
||||
/// Defaults to `{true}`.
|
||||
/// ```example
|
||||
/// #set page(height: 80pt)
|
||||
/// The following block will
|
||||
/// jump to its own page.
|
||||
/// #block(
|
||||
/// breakable: false,
|
||||
/// lorem(15),
|
||||
/// )
|
||||
/// ```
|
||||
pub const BREAKABLE: bool = true;
|
||||
|
||||
/// The block's background color. See the
|
||||
/// [rectangle's documentation]($func/rect.fill) for more details.
|
||||
pub const FILL: Option<Paint> = None;
|
||||
@ -285,7 +328,9 @@ impl BlockNode {
|
||||
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
let body = args.eat()?.unwrap_or_default();
|
||||
Ok(Self { body }.pack())
|
||||
let width = args.named("width")?.unwrap_or_default();
|
||||
let height = args.named("height")?.unwrap_or_default();
|
||||
Ok(Self { body, width, height }.pack())
|
||||
}
|
||||
|
||||
fn set(...) {
|
||||
@ -315,8 +360,52 @@ impl Layout for BlockNode {
|
||||
child = child.clone().padded(inset.map(|side| side.map(Length::from)));
|
||||
}
|
||||
|
||||
// Resolve the sizing to a concrete size.
|
||||
let sizing = Axes::new(self.width, self.height);
|
||||
let mut expand = sizing.as_ref().map(Smart::is_custom);
|
||||
let mut size = sizing
|
||||
.resolve(styles)
|
||||
.zip(regions.base())
|
||||
.map(|(s, b)| s.map(|v| v.relative_to(b)))
|
||||
.unwrap_or(regions.base());
|
||||
|
||||
// Layout the child.
|
||||
let mut frames = child.layout(vt, styles, regions)?.into_frames();
|
||||
let mut frames = if styles.get(Self::BREAKABLE) {
|
||||
// Measure to ensure frames for all regions have the same width.
|
||||
if self.width == Smart::Auto {
|
||||
let pod = Regions::one(size, Axes::splat(false));
|
||||
let frame = child.layout(vt, styles, pod)?.into_frame();
|
||||
size.x = frame.width();
|
||||
expand.x = true;
|
||||
}
|
||||
|
||||
let mut pod = regions;
|
||||
pod.size.x = size.x;
|
||||
pod.expand = expand;
|
||||
|
||||
// Generate backlog for fixed height.
|
||||
let mut heights = vec![];
|
||||
if self.height.is_custom() {
|
||||
let mut remaining = size.y;
|
||||
for region in regions.iter() {
|
||||
let limited = region.y.min(remaining);
|
||||
heights.push(limited);
|
||||
remaining -= limited;
|
||||
if Abs::zero().fits(remaining) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pod.size.y = heights[0];
|
||||
pod.backlog = &heights[1..];
|
||||
pod.last = None;
|
||||
}
|
||||
|
||||
child.layout(vt, styles, pod)?.into_frames()
|
||||
} else {
|
||||
let pod = Regions::one(size, expand);
|
||||
child.layout(vt, styles, pod)?.into_frames()
|
||||
};
|
||||
|
||||
// Prepare fill and stroke.
|
||||
let fill = styles.get(Self::FILL);
|
||||
@ -326,9 +415,14 @@ impl Layout for BlockNode {
|
||||
|
||||
// Add fill and/or stroke.
|
||||
if fill.is_some() || stroke.iter().any(Option::is_some) {
|
||||
let mut skip = false;
|
||||
if let [first, rest @ ..] = frames.as_slice() {
|
||||
skip = first.is_empty() && rest.iter().any(|frame| !frame.is_empty());
|
||||
}
|
||||
|
||||
let outset = styles.get(Self::OUTSET);
|
||||
let radius = styles.get(Self::RADIUS);
|
||||
for frame in &mut frames {
|
||||
for frame in frames.iter_mut().skip(skip as usize) {
|
||||
frame.fill_and_stroke(fill, stroke, outset, radius);
|
||||
}
|
||||
}
|
||||
|
@ -25,12 +25,21 @@ use crate::prelude::*;
|
||||
/// #enum[First][Second]
|
||||
/// ```
|
||||
///
|
||||
/// You can easily switch all your enumerations to a different numbering style
|
||||
/// with a set rule.
|
||||
/// ```example
|
||||
/// #set enum(numbering: "a)")
|
||||
///
|
||||
/// + Starting off ...
|
||||
/// + Don't forget step two
|
||||
/// ```
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This functions also has dedicated syntax:
|
||||
///
|
||||
/// - Starting a line with a plus sign creates an automatically numbered
|
||||
/// enumeration item.
|
||||
/// - Start a line with a number followed by a dot creates an explicitly
|
||||
/// - Starting a line with a number followed by a dot creates an explicitly
|
||||
/// numbered enumeration item.
|
||||
///
|
||||
/// Enumeration items can contain multiple paragraphs and other block-level
|
||||
@ -98,10 +107,13 @@ impl EnumNode {
|
||||
///
|
||||
/// ```example
|
||||
/// #set enum(numbering: "(a)")
|
||||
///
|
||||
/// + Different
|
||||
/// + Numbering
|
||||
/// + Style
|
||||
///
|
||||
/// #set enum(numbering: n => super[#n])
|
||||
/// + Superscript
|
||||
/// + Numbering!
|
||||
/// ```
|
||||
#[property(referenced)]
|
||||
pub const NUMBERING: Numbering =
|
||||
|
@ -44,7 +44,10 @@ impl Layout for FlowNode {
|
||||
} else if child.has::<dyn Layout>() {
|
||||
layouter.layout_multiple(vt, child, styles)?;
|
||||
} else if child.is::<ColbreakNode>() {
|
||||
layouter.finish_region();
|
||||
if !layouter.regions.backlog.is_empty() || layouter.regions.last.is_some()
|
||||
{
|
||||
layouter.finish_region();
|
||||
}
|
||||
} else {
|
||||
panic!("unexpected flow child: {child:?}");
|
||||
}
|
||||
@ -207,7 +210,10 @@ impl<'a> FlowLayouter<'a> {
|
||||
// Layout the block itself.
|
||||
let sticky = styles.get(BlockNode::STICKY);
|
||||
let fragment = block.layout(vt, styles, self.regions)?;
|
||||
for frame in fragment {
|
||||
for (i, frame) in fragment.into_iter().enumerate() {
|
||||
if i > 0 {
|
||||
self.finish_region();
|
||||
}
|
||||
self.layout_item(FlowItem::Frame(frame, aligns, sticky));
|
||||
}
|
||||
|
||||
@ -264,8 +270,7 @@ impl<'a> FlowLayouter<'a> {
|
||||
|
||||
// Determine the size of the flow in this region depending on whether
|
||||
// the region expands.
|
||||
let mut size = self.expand.select(self.full, used);
|
||||
size.y.set_min(self.full.y);
|
||||
let mut size = self.expand.select(self.full, used).min(self.full);
|
||||
|
||||
// Account for fractional spacing in the size calculation.
|
||||
let remaining = self.full.y - used.y;
|
||||
|
@ -37,7 +37,7 @@ use super::Sizing;
|
||||
///
|
||||
/// ## Example
|
||||
/// ```example
|
||||
/// #set text(10pt, weight: "bold")
|
||||
/// #set text(10pt, style: "italic")
|
||||
/// #let cell = rect.with(
|
||||
/// inset: 8pt,
|
||||
/// fill: rgb("e4e5ea"),
|
||||
|
@ -13,7 +13,7 @@ use crate::prelude::*;
|
||||
///
|
||||
/// #pad(x: 16pt, image("typing.jpg"))
|
||||
/// _Typing speeds can be
|
||||
/// measured in words per minute._
|
||||
/// measured in words per minute._
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
|
@ -351,14 +351,14 @@ impl Debug for PageNode {
|
||||
/// more details on compound theory.
|
||||
/// #pagebreak()
|
||||
///
|
||||
/// // Examples only render the first
|
||||
/// // page, so this is not visible.
|
||||
/// == Compound Theory
|
||||
/// In 1984, the first ...
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - weak: `bool` (named)
|
||||
/// If `{true}`, the page break is skipped if the current page is already empty.
|
||||
/// If `{true}`, the page break is skipped if the current page is already
|
||||
/// empty.
|
||||
///
|
||||
/// ## Category
|
||||
/// layout
|
||||
|
@ -16,8 +16,8 @@ use crate::prelude::*;
|
||||
/// #place(
|
||||
/// top + right,
|
||||
/// square(
|
||||
/// width: 10pt,
|
||||
/// stroke: 1pt + blue
|
||||
/// width: 20pt,
|
||||
/// stroke: 2pt + blue
|
||||
/// ),
|
||||
/// )
|
||||
/// ```
|
||||
|
@ -147,7 +147,12 @@ impl Show for HeadingNode {
|
||||
if numbers != Value::None {
|
||||
realized = numbers.display() + SpaceNode.pack() + realized;
|
||||
}
|
||||
Ok(BlockNode { body: realized }.pack())
|
||||
Ok(BlockNode {
|
||||
body: realized,
|
||||
width: Smart::Auto,
|
||||
height: Smart::Auto,
|
||||
}
|
||||
.pack())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,12 @@ impl Show for RawNode {
|
||||
};
|
||||
|
||||
if self.block {
|
||||
realized = BlockNode { body: realized }.pack();
|
||||
realized = BlockNode {
|
||||
body: realized,
|
||||
width: Smart::Auto,
|
||||
height: Smart::Auto,
|
||||
}
|
||||
.pack();
|
||||
}
|
||||
|
||||
Ok(realized)
|
||||
|
@ -160,6 +160,8 @@ impl Layout for RectNode {
|
||||
) -> SourceResult<Fragment> {
|
||||
layout(
|
||||
vt,
|
||||
styles,
|
||||
regions,
|
||||
ShapeKind::Rect,
|
||||
&self.body,
|
||||
Axes::new(self.width, self.height),
|
||||
@ -168,8 +170,6 @@ impl Layout for RectNode {
|
||||
styles.get(Self::INSET),
|
||||
styles.get(Self::OUTSET),
|
||||
styles.get(Self::RADIUS),
|
||||
styles,
|
||||
regions,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -278,6 +278,8 @@ impl Layout for SquareNode {
|
||||
) -> SourceResult<Fragment> {
|
||||
layout(
|
||||
vt,
|
||||
styles,
|
||||
regions,
|
||||
ShapeKind::Square,
|
||||
&self.body,
|
||||
Axes::new(self.width, self.height),
|
||||
@ -286,8 +288,6 @@ impl Layout for SquareNode {
|
||||
styles.get(Self::INSET),
|
||||
styles.get(Self::OUTSET),
|
||||
styles.get(Self::RADIUS),
|
||||
styles,
|
||||
regions,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -372,6 +372,8 @@ impl Layout for EllipseNode {
|
||||
) -> SourceResult<Fragment> {
|
||||
layout(
|
||||
vt,
|
||||
styles,
|
||||
regions,
|
||||
ShapeKind::Ellipse,
|
||||
&self.body,
|
||||
Axes::new(self.width, self.height),
|
||||
@ -380,8 +382,6 @@ impl Layout for EllipseNode {
|
||||
styles.get(Self::INSET),
|
||||
styles.get(Self::OUTSET),
|
||||
Corners::splat(Rel::zero()),
|
||||
styles,
|
||||
regions,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -485,6 +485,8 @@ impl Layout for CircleNode {
|
||||
) -> SourceResult<Fragment> {
|
||||
layout(
|
||||
vt,
|
||||
styles,
|
||||
regions,
|
||||
ShapeKind::Circle,
|
||||
&self.body,
|
||||
Axes::new(self.width, self.height),
|
||||
@ -493,8 +495,6 @@ impl Layout for CircleNode {
|
||||
styles.get(Self::INSET),
|
||||
styles.get(Self::OUTSET),
|
||||
Corners::splat(Rel::zero()),
|
||||
styles,
|
||||
regions,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -502,6 +502,8 @@ impl Layout for CircleNode {
|
||||
/// Layout a shape.
|
||||
fn layout(
|
||||
vt: &mut Vt,
|
||||
styles: StyleChain,
|
||||
regions: Regions,
|
||||
kind: ShapeKind,
|
||||
body: &Option<Content>,
|
||||
sizing: Axes<Smart<Rel<Length>>>,
|
||||
@ -510,8 +512,6 @@ fn layout(
|
||||
mut inset: Sides<Rel<Abs>>,
|
||||
outset: Sides<Rel<Abs>>,
|
||||
radius: Corners<Rel<Abs>>,
|
||||
styles: StyleChain,
|
||||
regions: Regions,
|
||||
) -> SourceResult<Fragment> {
|
||||
let resolved = sizing
|
||||
.zip(regions.base())
|
||||
|
20
src/doc.rs
20
src/doc.rs
@ -17,7 +17,7 @@ use crate::model::{
|
||||
use crate::util::EcoString;
|
||||
|
||||
/// A finished document with metadata and page frames.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(Debug, Default, Clone, Hash)]
|
||||
pub struct Document {
|
||||
/// The page frames.
|
||||
pub pages: Vec<Frame>,
|
||||
@ -28,7 +28,7 @@ pub struct Document {
|
||||
}
|
||||
|
||||
/// A finished layout with elements at fixed positions.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Clone, Hash)]
|
||||
pub struct Frame {
|
||||
/// The size of the frame.
|
||||
size: Size,
|
||||
@ -304,12 +304,16 @@ impl Frame {
|
||||
|
||||
/// Arbitrarily transform the contents of the frame.
|
||||
pub fn transform(&mut self, transform: Transform) {
|
||||
self.group(|g| g.transform = transform);
|
||||
if !self.is_empty() {
|
||||
self.group(|g| g.transform = transform);
|
||||
}
|
||||
}
|
||||
|
||||
/// Clip the contents of a frame to its size.
|
||||
pub fn clip(&mut self) {
|
||||
self.group(|g| g.clips = true);
|
||||
if !self.is_empty() {
|
||||
self.group(|g| g.clips = true);
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrap the frame's contents in a group and modify that group with `f`.
|
||||
@ -386,7 +390,7 @@ impl Debug for Frame {
|
||||
}
|
||||
|
||||
/// The building block frames are composed of.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Hash)]
|
||||
pub enum Element {
|
||||
/// A group of elements.
|
||||
Group(Group),
|
||||
@ -413,7 +417,7 @@ impl Debug for Element {
|
||||
}
|
||||
|
||||
/// A group of elements with optional clipping.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Hash)]
|
||||
pub struct Group {
|
||||
/// The group's frame.
|
||||
pub frame: Frame,
|
||||
@ -442,7 +446,7 @@ impl Debug for Group {
|
||||
}
|
||||
|
||||
/// A run of shaped text.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Text {
|
||||
/// The font the glyphs are contained in.
|
||||
pub font: Font,
|
||||
@ -477,7 +481,7 @@ impl Debug for Text {
|
||||
}
|
||||
|
||||
/// A glyph in a run of shaped text.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Glyph {
|
||||
/// The glyph's index in the font.
|
||||
pub id: u16,
|
||||
|
@ -73,7 +73,7 @@ pub trait Get<Index> {
|
||||
}
|
||||
|
||||
/// A geometric shape with optional fill and stroke.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Shape {
|
||||
/// The shape's geometry.
|
||||
pub geometry: Geometry,
|
||||
@ -84,7 +84,7 @@ pub struct Shape {
|
||||
}
|
||||
|
||||
/// A shape's geometry.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Geometry {
|
||||
/// A line to a point (relative to its position).
|
||||
Line(Point),
|
||||
|
@ -1,11 +1,11 @@
|
||||
use super::*;
|
||||
|
||||
/// A bezier path.
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Path(pub Vec<PathElement>);
|
||||
|
||||
/// An element in a bezier path.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum PathElement {
|
||||
MoveTo(Point),
|
||||
LineTo(Point),
|
||||
|
BIN
tests/ref/bugs/flow-4.png
Normal file
BIN
tests/ref/bugs/flow-4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
BIN
tests/ref/layout/block-sizing.png
Normal file
BIN
tests/ref/layout/block-sizing.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
5
tests/typ/bugs/flow-4.typ
Normal file
5
tests/typ/bugs/flow-4.typ
Normal file
@ -0,0 +1,5 @@
|
||||
// In this bug, a frame intended for the second region ended up in the first.
|
||||
|
||||
---
|
||||
#set page(height: 105pt)
|
||||
#block(lorem(20))
|
16
tests/typ/layout/block-sizing.typ
Normal file
16
tests/typ/layout/block-sizing.typ
Normal file
@ -0,0 +1,16 @@
|
||||
// Test blocks with fixed height.
|
||||
|
||||
---
|
||||
#set page(height: 100pt)
|
||||
#set align(center)
|
||||
|
||||
#lorem(10)
|
||||
#block(width: 80%, height: 60pt, fill: aqua)
|
||||
#lorem(6)
|
||||
#block(
|
||||
breakable: false,
|
||||
width: 100%,
|
||||
inset: 4pt,
|
||||
fill: aqua,
|
||||
lorem(8) + colbreak(),
|
||||
)
|
@ -1,6 +1,6 @@
|
||||
#set page(height: 100pt)
|
||||
#let words = lorem(18).split()
|
||||
#block(inset: 8pt, fill: aqua, stroke: aqua.darken(30%))[
|
||||
#block(inset: 8pt, width: 100%, fill: aqua, stroke: aqua.darken(30%))[
|
||||
#words.slice(0, 12).join(" ")
|
||||
#box(fill: teal, outset: 2pt)[incididunt]
|
||||
#words.slice(12).join(" ")
|
||||
|
Loading…
x
Reference in New Issue
Block a user