mirror of
https://github.com/typst/typst
synced 2025-05-13 12:36:23 +08:00
Code Review: Heap is Stack. Unsafe is Good.
Spaghetti Code is Style.
This commit is contained in:
parent
33213abe7d
commit
6a8a0ec6ec
@ -40,6 +40,14 @@ impl Frame {
|
||||
self.elements.insert(0, (pos, element));
|
||||
}
|
||||
|
||||
/// Add multiple elements at a position in the background.
|
||||
pub fn prepend_multiple<I>(&mut self, insert: I)
|
||||
where
|
||||
I: IntoIterator<Item = (Point, Element)>,
|
||||
{
|
||||
self.elements.splice(0 .. 0, insert);
|
||||
}
|
||||
|
||||
/// Add an element at a position in the foreground.
|
||||
pub fn push(&mut self, pos: Point, element: Element) {
|
||||
self.elements.push((pos, element));
|
||||
|
@ -64,51 +64,6 @@ impl Angle {
|
||||
pub fn cos(self) -> f64 {
|
||||
self.to_rad().cos()
|
||||
}
|
||||
|
||||
/// Get the control points for a bezier curve that describes a circular arc
|
||||
/// of this angle with the given radius.
|
||||
pub fn bezier_arc(
|
||||
self,
|
||||
radius: Length,
|
||||
rotate: bool,
|
||||
mirror_x: bool,
|
||||
mirror_y: bool,
|
||||
) -> [Point; 4] {
|
||||
let end = Point::new(self.cos() * radius - radius, self.sin() * radius);
|
||||
let center = Point::new(-radius, Length::zero());
|
||||
|
||||
let mut ts = if mirror_y {
|
||||
Transform::mirror_y()
|
||||
} else {
|
||||
Transform::identity()
|
||||
};
|
||||
|
||||
if mirror_x {
|
||||
ts = ts.pre_concat(Transform::mirror_x());
|
||||
}
|
||||
|
||||
if rotate {
|
||||
ts = ts.pre_concat(Transform::rotate(Angle::deg(90.0)));
|
||||
}
|
||||
|
||||
let a = center * -1.0;
|
||||
let b = end - center;
|
||||
|
||||
let q1 = a.x.to_raw() * a.x.to_raw() + a.y.to_raw() * a.y.to_raw();
|
||||
let q2 = q1 + a.x.to_raw() * b.x.to_raw() + a.y.to_raw() * b.y.to_raw();
|
||||
let k2 = (4.0 / 3.0) * ((2.0 * q1 * q2).sqrt() - q2)
|
||||
/ (a.x.to_raw() * b.y.to_raw() - a.y.to_raw() * b.x.to_raw());
|
||||
|
||||
let control_1 = Point::new(center.x + a.x - k2 * a.y, center.y + a.y + k2 * a.x);
|
||||
let control_2 = Point::new(center.x + b.x + k2 * b.y, center.y + b.y - k2 * b.x);
|
||||
|
||||
[
|
||||
Point::zero(),
|
||||
control_1.transform(ts),
|
||||
control_2.transform(ts),
|
||||
end.transform(ts),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl Numeric for Angle {
|
||||
|
@ -71,3 +71,48 @@ impl Path {
|
||||
self.0.push(PathElement::ClosePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the control points for a bezier curve that describes a circular arc
|
||||
/// of this angle with the given radius.
|
||||
pub fn bezier_arc(
|
||||
angle: Angle,
|
||||
radius: Length,
|
||||
rotate: bool,
|
||||
mirror_x: bool,
|
||||
mirror_y: bool,
|
||||
) -> [Point; 4] {
|
||||
let end = Point::new(angle.cos() * radius - radius, angle.sin() * radius);
|
||||
let center = Point::new(-radius, Length::zero());
|
||||
|
||||
let mut ts = if mirror_y {
|
||||
Transform::mirror_y()
|
||||
} else {
|
||||
Transform::identity()
|
||||
};
|
||||
|
||||
if mirror_x {
|
||||
ts = ts.pre_concat(Transform::mirror_x());
|
||||
}
|
||||
|
||||
if rotate {
|
||||
ts = ts.pre_concat(Transform::rotate(Angle::deg(90.0)));
|
||||
}
|
||||
|
||||
let a = center * -1.0;
|
||||
let b = end - center;
|
||||
|
||||
let q1 = a.x.to_raw() * a.x.to_raw() + a.y.to_raw() * a.y.to_raw();
|
||||
let q2 = q1 + a.x.to_raw() * b.x.to_raw() + a.y.to_raw() * b.y.to_raw();
|
||||
let k2 = (4.0 / 3.0) * ((2.0 * q1 * q2).sqrt() - q2)
|
||||
/ (a.x.to_raw() * b.y.to_raw() - a.y.to_raw() * b.x.to_raw());
|
||||
|
||||
let control_1 = Point::new(center.x + a.x - k2 * a.y, center.y + a.y + k2 * a.x);
|
||||
let control_2 = Point::new(center.x + b.x + k2 * b.y, center.y + b.y - k2 * b.x);
|
||||
|
||||
[
|
||||
Point::zero(),
|
||||
control_1.transform(ts),
|
||||
control_2.transform(ts),
|
||||
end.transform(ts),
|
||||
]
|
||||
}
|
||||
|
126
src/geom/rect.rs
126
src/geom/rect.rs
@ -3,7 +3,7 @@ use super::*;
|
||||
use std::mem;
|
||||
|
||||
/// A rectangle with rounded corners.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Rect {
|
||||
size: Size,
|
||||
radius: Sides<Length>,
|
||||
@ -19,7 +19,7 @@ impl Rect {
|
||||
/// in the foreground. The function will output multiple items if the stroke
|
||||
/// properties differ by side.
|
||||
pub fn shapes(
|
||||
&self,
|
||||
self,
|
||||
fill: Option<Paint>,
|
||||
stroke: Sides<Option<Stroke>>,
|
||||
) -> Vec<Shape> {
|
||||
@ -28,15 +28,13 @@ impl Rect {
|
||||
res.push(Shape {
|
||||
geometry: self.fill_geometry(),
|
||||
fill,
|
||||
stroke: stroke.is_uniform().then(|| stroke.top).flatten(),
|
||||
stroke: if stroke.is_uniform() { stroke.top } else { None },
|
||||
});
|
||||
}
|
||||
|
||||
if !stroke.is_uniform() {
|
||||
for (path, stroke) in self.stroke_segments(Some(stroke)) {
|
||||
if !stroke.is_some() {
|
||||
continue;
|
||||
}
|
||||
for (path, stroke) in self.stroke_segments(stroke) {
|
||||
if stroke.is_some() {
|
||||
res.push(Shape {
|
||||
geometry: Geometry::Path(path),
|
||||
fill: None,
|
||||
@ -44,32 +42,50 @@ impl Rect {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Output the shape of the rectangle as a path or primitive rectangle,
|
||||
/// depending on whether it is rounded.
|
||||
fn fill_geometry(self) -> Geometry {
|
||||
if self.radius.iter().copied().all(Length::is_zero) {
|
||||
Geometry::Rect(self.size)
|
||||
} else {
|
||||
let mut paths = self.stroke_segments(Sides::splat(None));
|
||||
assert_eq!(paths.len(), 1);
|
||||
|
||||
Geometry::Path(paths.pop().unwrap().0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Output the minimum number of paths along the rectangles border.
|
||||
fn stroke_segments(
|
||||
&self,
|
||||
strokes: Option<Sides<Option<Stroke>>>,
|
||||
self,
|
||||
strokes: Sides<Option<Stroke>>,
|
||||
) -> Vec<(Path, Option<Stroke>)> {
|
||||
let strokes = strokes.unwrap_or_else(|| Sides::splat(None));
|
||||
let mut res = vec![];
|
||||
|
||||
let mut connection = Connection::None;
|
||||
let mut connection = Connection::default();
|
||||
let mut path = Path::new();
|
||||
let mut always_continuous = true;
|
||||
|
||||
for side in [Side::Top, Side::Right, Side::Bottom, Side::Left] {
|
||||
let radius = [self.radius.get(side.next_ccw()), self.radius.get(side)];
|
||||
let is_continuous = strokes.get(side) == strokes.get(side.next_cw());
|
||||
connection = connection.advance(is_continuous && side != Side::Left);
|
||||
always_continuous &= is_continuous;
|
||||
|
||||
let stroke_continuity = strokes.get(side) == strokes.get(side.next_cw());
|
||||
connection = connection.advance(stroke_continuity && side != Side::Left);
|
||||
always_continuous &= stroke_continuity;
|
||||
draw_side(
|
||||
&mut path,
|
||||
side,
|
||||
self.size,
|
||||
self.radius.get(side.next_ccw()),
|
||||
self.radius.get(side),
|
||||
connection,
|
||||
);
|
||||
|
||||
draw_side(&mut path, side, self.size, radius[0], radius[1], connection);
|
||||
|
||||
if !stroke_continuity {
|
||||
if !is_continuous {
|
||||
res.push((mem::take(&mut path), strokes.get(side)));
|
||||
}
|
||||
}
|
||||
@ -84,19 +100,6 @@ impl Rect {
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Output the shape of the rectangle as a path or primitive rectangle,
|
||||
/// depending on whether it is rounded.
|
||||
fn fill_geometry(&self) -> Geometry {
|
||||
if self.radius.iter().copied().all(Length::is_zero) {
|
||||
Geometry::Rect(self.size)
|
||||
} else {
|
||||
let mut paths = self.stroke_segments(None);
|
||||
assert_eq!(paths.len(), 1);
|
||||
|
||||
Geometry::Path(paths.pop().unwrap().0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws one side of the rounded rectangle. Will always draw the left arc. The
|
||||
@ -110,19 +113,18 @@ fn draw_side(
|
||||
connection: Connection,
|
||||
) {
|
||||
let reversed = |angle: Angle, radius, rotate, mirror_x, mirror_y| {
|
||||
let [a, b, c, d] = angle.bezier_arc(radius, rotate, mirror_x, mirror_y);
|
||||
let [a, b, c, d] = bezier_arc(angle, radius, rotate, mirror_x, mirror_y);
|
||||
[d, c, b, a]
|
||||
};
|
||||
|
||||
let angle_left = Angle::deg(if connection.left() { 90.0 } else { 45.0 });
|
||||
let angle_right = Angle::deg(if connection.right() { 90.0 } else { 45.0 });
|
||||
let angle_left = Angle::deg(if connection.prev { 90.0 } else { 45.0 });
|
||||
let angle_right = Angle::deg(if connection.next { 90.0 } else { 45.0 });
|
||||
|
||||
let (arc1, arc2) = match side {
|
||||
Side::Top => {
|
||||
let arc1 = reversed(angle_left, radius_left, true, true, false)
|
||||
.map(|x| x + Point::with_x(radius_left));
|
||||
let arc2 = (-angle_right)
|
||||
.bezier_arc(radius_right, true, true, false)
|
||||
let arc2 = bezier_arc(-angle_right, radius_right, true, true, false)
|
||||
.map(|x| x + Point::with_x(size.x - radius_right));
|
||||
|
||||
(arc1, arc2)
|
||||
@ -131,8 +133,7 @@ fn draw_side(
|
||||
let arc1 = reversed(-angle_left, radius_left, false, false, false)
|
||||
.map(|x| x + Point::new(size.x, radius_left));
|
||||
|
||||
let arc2 = angle_right
|
||||
.bezier_arc(radius_right, false, false, false)
|
||||
let arc2 = bezier_arc(angle_right, radius_right, false, false, false)
|
||||
.map(|x| x + Point::new(size.x, size.y - radius_right));
|
||||
|
||||
(arc1, arc2)
|
||||
@ -141,8 +142,7 @@ fn draw_side(
|
||||
let arc1 = reversed(-angle_left, radius_left, true, false, false)
|
||||
.map(|x| x + Point::new(size.x - radius_left, size.y));
|
||||
|
||||
let arc2 = angle_right
|
||||
.bezier_arc(radius_right, true, false, false)
|
||||
let arc2 = bezier_arc(angle_right, radius_right, true, false, false)
|
||||
.map(|x| x + Point::new(radius_right, size.y));
|
||||
|
||||
(arc1, arc2)
|
||||
@ -151,15 +151,14 @@ fn draw_side(
|
||||
let arc1 = reversed(angle_left, radius_left, false, false, true)
|
||||
.map(|x| x + Point::with_y(size.y - radius_left));
|
||||
|
||||
let arc2 = (-angle_right)
|
||||
.bezier_arc(radius_right, false, false, true)
|
||||
let arc2 = bezier_arc(-angle_right, radius_right, false, false, true)
|
||||
.map(|x| x + Point::with_y(radius_right));
|
||||
|
||||
(arc1, arc2)
|
||||
}
|
||||
};
|
||||
|
||||
if !connection.left() {
|
||||
if !connection.prev {
|
||||
path.move_to(if radius_left.is_zero() { arc1[3] } else { arc1[0] });
|
||||
}
|
||||
|
||||
@ -169,51 +168,24 @@ fn draw_side(
|
||||
|
||||
path.line_to(arc2[0]);
|
||||
|
||||
if !connection.right() && !radius_right.is_zero() {
|
||||
if !connection.next && !radius_right.is_zero() {
|
||||
path.cubic_to(arc2[1], arc2[2], arc2[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/// A state machine that indicates which sides of the border strokes in a 2D
|
||||
/// polygon are connected to their neighboring sides.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum Connection {
|
||||
None,
|
||||
Left,
|
||||
Right,
|
||||
Both,
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
struct Connection {
|
||||
prev: bool,
|
||||
next: bool,
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
/// Advance to the next clockwise side of the polygon. The argument
|
||||
/// indicates whether the border is connected on the right side of the next
|
||||
/// edge.
|
||||
pub fn advance(self, right: bool) -> Self {
|
||||
match self {
|
||||
Self::Right | Self::Both => {
|
||||
if right {
|
||||
Self::Both
|
||||
} else {
|
||||
Self::Left
|
||||
}
|
||||
}
|
||||
Self::Left | Self::None => {
|
||||
if right {
|
||||
Self::Right
|
||||
} else {
|
||||
Self::None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether there is a connection on the left.
|
||||
fn left(self) -> bool {
|
||||
matches!(self, Self::Left | Self::Both)
|
||||
}
|
||||
|
||||
/// Whether there is a connection on the right.
|
||||
fn right(self) -> bool {
|
||||
matches!(self, Self::Right | Self::Both)
|
||||
pub fn advance(self, next: bool) -> Self {
|
||||
Self { prev: self.next, next }
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,19 @@ impl<T> Sides<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Zip two instances into an instance.
|
||||
pub fn zip<F, V, W>(self, other: Sides<V>, mut f: F) -> Sides<W>
|
||||
where
|
||||
F: FnMut(T, V, Side) -> W,
|
||||
{
|
||||
Sides {
|
||||
left: f(self.left, other.left, Side::Left),
|
||||
top: f(self.top, other.top, Side::Top),
|
||||
right: f(self.right, other.right, Side::Right),
|
||||
bottom: f(self.bottom, other.bottom, Side::Bottom),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over the sides.
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||
[&self.left, &self.top, &self.right, &self.bottom].into_iter()
|
||||
|
@ -26,26 +26,12 @@ impl Transform {
|
||||
|
||||
/// Transform by mirroring along the x-axis.
|
||||
pub fn mirror_x() -> Self {
|
||||
Self {
|
||||
sx: Ratio::one(),
|
||||
ky: Ratio::zero(),
|
||||
kx: Ratio::zero(),
|
||||
sy: -Ratio::one(),
|
||||
tx: Length::zero(),
|
||||
ty: Length::zero(),
|
||||
}
|
||||
Self::scale(Ratio::one(), -Ratio::one())
|
||||
}
|
||||
|
||||
/// Transform by mirroring along the y-axis.
|
||||
pub fn mirror_y() -> Self {
|
||||
Self {
|
||||
sx: -Ratio::one(),
|
||||
ky: Ratio::zero(),
|
||||
kx: Ratio::zero(),
|
||||
sy: Ratio::one(),
|
||||
tx: Length::zero(),
|
||||
ty: Length::zero(),
|
||||
}
|
||||
Self::scale(-Ratio::one(), Ratio::one())
|
||||
}
|
||||
|
||||
/// A translate transform.
|
||||
|
@ -78,7 +78,7 @@ impl<const S: ShapeKind> ShapeNode<S> {
|
||||
styles.set_opt(Self::INSET, args.named("inset")?);
|
||||
styles.set_opt(Self::OUTSET, args.named("outset")?);
|
||||
|
||||
if S != CIRCLE {
|
||||
if !is_round(S) {
|
||||
styles.set_opt(Self::RADIUS, args.named("radius")?);
|
||||
}
|
||||
|
||||
@ -97,10 +97,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> {
|
||||
if let Some(child) = &self.0 {
|
||||
let mut inset = styles.get(Self::INSET);
|
||||
if is_round(S) {
|
||||
inset = inset.map(|mut side| {
|
||||
side.rel += Ratio::new(0.5 - SQRT_2 / 4.0);
|
||||
side
|
||||
});
|
||||
inset = inset.map(|side| side + Ratio::new(0.5 - SQRT_2 / 4.0));
|
||||
}
|
||||
|
||||
// Pad the child.
|
||||
@ -158,18 +155,8 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> {
|
||||
}
|
||||
};
|
||||
|
||||
let outset = styles.get(Self::OUTSET);
|
||||
let outset = Sides {
|
||||
left: outset.left.relative_to(frame.size.x),
|
||||
top: outset.top.relative_to(frame.size.y),
|
||||
right: outset.right.relative_to(frame.size.x),
|
||||
bottom: outset.bottom.relative_to(frame.size.y),
|
||||
};
|
||||
|
||||
let size = Spec::new(
|
||||
frame.size.x + outset.left + outset.right,
|
||||
frame.size.y + outset.top + outset.bottom,
|
||||
);
|
||||
let outset = styles.get(Self::OUTSET).relative_to(frame.size);
|
||||
let size = frame.size + outset.sum_by_axis();
|
||||
|
||||
let radius = styles
|
||||
.get(Self::RADIUS)
|
||||
@ -186,11 +173,12 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> {
|
||||
};
|
||||
frame.prepend(pos, Element::Shape(shape));
|
||||
} else {
|
||||
for shape in
|
||||
Rect::new(size, radius).shapes(fill, stroke).into_iter().rev()
|
||||
{
|
||||
frame.prepend(pos, Element::Shape(shape));
|
||||
}
|
||||
frame.prepend_multiple(
|
||||
Rect::new(size, radius)
|
||||
.shapes(fill, stroke)
|
||||
.into_iter()
|
||||
.map(|x| (pos, Element::Shape(x))),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,8 @@ impl PageNode {
|
||||
|
||||
/// The page margin.
|
||||
#[property(fold)]
|
||||
pub const MARGINS: Sides<Smart<Relative<RawLength>>> = Sides::splat(Smart::Auto);
|
||||
pub const MARGINS: Sides<Option<Smart<Relative<RawLength>>>> =
|
||||
Sides::splat(Smart::Auto);
|
||||
|
||||
/// How many columns the page has.
|
||||
pub const COLUMNS: NonZeroUsize = NonZeroUsize::new(1).unwrap();
|
||||
@ -48,9 +49,7 @@ impl PageNode {
|
||||
|
||||
styles.set_opt(Self::WIDTH, args.named("width")?);
|
||||
styles.set_opt(Self::HEIGHT, args.named("height")?);
|
||||
|
||||
styles.set_opt(Self::MARGINS, args.named("margins")?);
|
||||
|
||||
styles.set_opt(Self::FLIPPED, args.named("flipped")?);
|
||||
styles.set_opt(Self::FILL, args.named("fill")?);
|
||||
styles.set_opt(Self::COLUMNS, args.named("columns")?);
|
||||
|
@ -466,12 +466,7 @@ where
|
||||
type Output = Sides<T::Output>;
|
||||
|
||||
fn fold(self, outer: Self::Output) -> Self::Output {
|
||||
Sides {
|
||||
left: self.left.fold(outer.left),
|
||||
top: self.top.fold(outer.top),
|
||||
right: self.right.fold(outer.right),
|
||||
bottom: self.bottom.fold(outer.bottom),
|
||||
}
|
||||
self.zip(outer, |inner, outer, _| inner.fold(outer))
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,25 +474,15 @@ impl Fold for Sides<Option<Relative<Length>>> {
|
||||
type Output = Sides<Relative<Length>>;
|
||||
|
||||
fn fold(self, outer: Self::Output) -> Self::Output {
|
||||
Sides {
|
||||
left: self.left.unwrap_or(outer.left),
|
||||
top: self.top.unwrap_or(outer.top),
|
||||
right: self.right.unwrap_or(outer.right),
|
||||
bottom: self.bottom.unwrap_or(outer.bottom),
|
||||
}
|
||||
self.zip(outer, |inner, outer, _| inner.unwrap_or(outer))
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold for Sides<Smart<Relative<RawLength>>> {
|
||||
impl Fold for Sides<Option<Smart<Relative<RawLength>>>> {
|
||||
type Output = Sides<Smart<Relative<RawLength>>>;
|
||||
|
||||
fn fold(self, outer: Self::Output) -> Self::Output {
|
||||
Sides {
|
||||
left: self.left.or(outer.left),
|
||||
top: self.top.or(outer.top),
|
||||
right: self.right.or(outer.right),
|
||||
bottom: self.bottom.or(outer.bottom),
|
||||
}
|
||||
self.zip(outer, |inner, outer, _| inner.unwrap_or(outer))
|
||||
}
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
@ -35,20 +35,20 @@
|
||||
|
||||
// Different strokes.
|
||||
[
|
||||
#set rect(stroke: (right: red,))
|
||||
#set rect(stroke: (right: red))
|
||||
#rect(width: 100%, fill: lime, stroke: (x: 5pt, y: 1pt))
|
||||
]
|
||||
|
||||
---
|
||||
// Outset padding.
|
||||
#let inline-code(body) = [
|
||||
#show node: raw as [
|
||||
#set text("IBM Plex Mono", 8pt)
|
||||
#h(.7em, weak: true)
|
||||
#rect(radius: 3pt, outset: (y: 3pt, x: 2.5pt), fill: rgb(239, 241, 243), body)
|
||||
#rect(radius: 3pt, outset: (y: 3pt, x: 2.5pt), fill: rgb(239, 241, 243))[{node.text}]
|
||||
#h(.7em, weak: true)
|
||||
]
|
||||
|
||||
Use the #inline-code[\*const ptr] pointer.
|
||||
Use the `*const ptr` pointer.
|
||||
|
||||
---
|
||||
// Error: 15-38 unexpected key "cake"
|
||||
|
@ -11,10 +11,10 @@
|
||||
---
|
||||
// Set individual margins.
|
||||
#set page(height: 40pt)
|
||||
[#set page(margins: (left: 0pt,)); #align(left)[Left]]
|
||||
[#set page(margins: (right: 0pt,)); #align(right)[Right]]
|
||||
[#set page(margins: (top: 0pt,)); #align(top)[Top]]
|
||||
[#set page(margins: (bottom: 0pt,)); #align(bottom)[Bottom]]
|
||||
[#set page(margins: (left: 0pt)); #align(left)[Left]]
|
||||
[#set page(margins: (right: 0pt)); #align(right)[Right]]
|
||||
[#set page(margins: (top: 0pt)); #align(top)[Top]]
|
||||
[#set page(margins: (bottom: 0pt)); #align(bottom)[Bottom]]
|
||||
|
||||
// Ensure that specific margins override general margins.
|
||||
[#set page(margins: (rest: 0pt, left: 20pt)); Overriden]
|
||||
|
@ -66,7 +66,7 @@ fn main() {
|
||||
styles.set(PageNode::HEIGHT, Smart::Auto);
|
||||
styles.set(
|
||||
PageNode::MARGINS,
|
||||
Sides::splat(Smart::Custom(Length::pt(10.0).into())),
|
||||
Sides::splat(Some(Smart::Custom(Length::pt(10.0).into()))),
|
||||
);
|
||||
styles.set(TextNode::SIZE, TextSize(Length::pt(10.0).into()));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user