summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/typst-layout/src/flow/block.rs6
-rw-r--r--crates/typst-layout/src/inline/box.rs3
-rw-r--r--crates/typst-layout/src/shapes.rs5
-rw-r--r--crates/typst-library/src/visualize/path.rs20
-rw-r--r--tests/ref/box-clip-outset.pngbin0 -> 1442 bytes
-rw-r--r--tests/suite/layout/container.typ13
6 files changed, 41 insertions, 6 deletions
diff --git a/crates/typst-layout/src/flow/block.rs b/crates/typst-layout/src/flow/block.rs
index 1dd98812..48ca1fba 100644
--- a/crates/typst-layout/src/flow/block.rs
+++ b/crates/typst-layout/src/flow/block.rs
@@ -84,8 +84,7 @@ pub fn layout_single_block(
// Clip the contents, if requested.
if elem.clip(styles) {
- let size = frame.size() + outset.relative_to(frame.size()).sum_by_axis();
- frame.clip(clip_rect(size, &radius, &stroke));
+ frame.clip(clip_rect(frame.size(), &radius, &stroke, &outset));
}
// Add fill and/or stroke.
@@ -231,8 +230,7 @@ pub fn layout_multi_block(
// Clip the contents, if requested.
if clip {
- let size = frame.size() + outset.relative_to(frame.size()).sum_by_axis();
- frame.clip(clip_rect(size, &radius, &stroke));
+ frame.clip(clip_rect(frame.size(), &radius, &stroke, &outset));
}
// Add fill and/or stroke.
diff --git a/crates/typst-layout/src/inline/box.rs b/crates/typst-layout/src/inline/box.rs
index 30572e4e..62054bea 100644
--- a/crates/typst-layout/src/inline/box.rs
+++ b/crates/typst-layout/src/inline/box.rs
@@ -61,8 +61,7 @@ pub fn layout_box(
// Clip the contents, if requested.
if elem.clip(styles) {
- let size = frame.size() + outset.relative_to(frame.size()).sum_by_axis();
- frame.clip(clip_rect(size, &radius, &stroke));
+ frame.clip(clip_rect(frame.size(), &radius, &stroke, &outset));
}
// Add fill and/or stroke.
diff --git a/crates/typst-layout/src/shapes.rs b/crates/typst-layout/src/shapes.rs
index 31f8c42b..81be1219 100644
--- a/crates/typst-layout/src/shapes.rs
+++ b/crates/typst-layout/src/shapes.rs
@@ -412,7 +412,11 @@ pub fn clip_rect(
size: Size,
radius: &Corners<Rel<Abs>>,
stroke: &Sides<Option<FixedStroke>>,
+ outset: &Sides<Rel<Abs>>,
) -> Path {
+ let outset = outset.relative_to(size);
+ let size = size + outset.sum_by_axis();
+
let stroke_widths = stroke
.as_ref()
.map(|s| s.as_ref().map_or(Abs::zero(), |s| s.thickness / 2.0));
@@ -441,6 +445,7 @@ pub fn clip_rect(
}
}
path.close_path();
+ path.translate(Point::new(-outset.left, -outset.top));
path
}
diff --git a/crates/typst-library/src/visualize/path.rs b/crates/typst-library/src/visualize/path.rs
index 76fd0df0..f592a712 100644
--- a/crates/typst-library/src/visualize/path.rs
+++ b/crates/typst-library/src/visualize/path.rs
@@ -1,4 +1,5 @@
use kurbo::ParamCurveExtrema;
+use typst_utils::Numeric;
use self::PathVertex::{AllControlPoints, MirroredControlPoint, Vertex};
use crate::diag::{bail, SourceResult};
@@ -228,6 +229,25 @@ impl Path {
self.0.push(PathItem::ClosePath);
}
+ /// Translate all points in this path by the given offset.
+ pub fn translate(&mut self, offset: Point) {
+ if offset.is_zero() {
+ return;
+ }
+ for item in self.0.iter_mut() {
+ match item {
+ PathItem::MoveTo(p) => *p += offset,
+ PathItem::LineTo(p) => *p += offset,
+ PathItem::CubicTo(p1, p2, p3) => {
+ *p1 += offset;
+ *p2 += offset;
+ *p3 += offset;
+ }
+ PathItem::ClosePath => (),
+ }
+ }
+ }
+
/// Computes the size of bounding box of this path.
pub fn bbox_size(&self) -> Size {
let mut min_x = Abs::inf();
diff --git a/tests/ref/box-clip-outset.png b/tests/ref/box-clip-outset.png
new file mode 100644
index 00000000..21538e85
--- /dev/null
+++ b/tests/ref/box-clip-outset.png
Binary files differ
diff --git a/tests/suite/layout/container.typ b/tests/suite/layout/container.typ
index e1367967..799300f0 100644
--- a/tests/suite/layout/container.typ
+++ b/tests/suite/layout/container.typ
@@ -251,6 +251,19 @@ First!
image("/assets/images/rhino.png", width: 30pt)
)
+--- box-clip-outset ---
+// Test clipping with `outset`.
+#set page(height: 60pt)
+
+#box(
+ outset: 5pt,
+ stroke: 2pt + black,
+ width: 20pt,
+ height: 20pt,
+ clip: true,
+ image("/assets/images/rhino.png", width: 30pt)
+)
+
--- container-layoutable-child ---
// Test box/block sizing with directly layoutable child.
//