Commits: 3
Describe the stacking feature
index ef39395..5b2a3da 100644
--- a/playground.typ
+++ b/playground.typ
@@ -289,3 +289,17 @@ Now we have everything we need! Here are some examples.
=+ Multiple rows, each in an array
=+ Automatic vertical spacing
=+ In a box, to prevent page breaks inside
+
+== TODO: Stack of images within a row
+
+When some images are wide and some narrow, it might be desirable to stack several wide ones on top of each other. In that case, the length of each stacked image should be equal, and the combined height (including gutters) should be equal to the height of every image in the row. In the code, a stack should be represented as an array of paths, like this:
+
+
+```typst
+#image-row(
+ gutter: 4pt,
+ "left.jpg",
+ ("middle-top.jpg", "middlep-bottom.jpg"), // <-- a stack
+ "right.jpg",
+)
+```Set page height to automatic
Pages are broken on h2 elements.
index 5b2a3da..6800ddb 100644
--- a/playground.typ
+++ b/playground.typ
@@ -1,3 +1,5 @@
+#set page(height: auto)
+
== Layout Playground
=
=#let images = (
@@ -59,8 +61,8 @@ Sum the aspect ratios of all the images to get the total aspect ratio of the row
=#let total_aspect_ratio = aspects.map(a => a.ratio).sum()
=
=#rect(
- height: 100% / total_aspect_ratio,
- width: 100%,
+ height: 300pt / total_aspect_ratio,
+ width: 300pt,
= align(center + horizon)[1 × #calc.round(digits: 3, total_aspect_ratio)]
=)
=Implement partial solution for stacks
It works as long as there are no gutters. Gutters mess up the height.
index 6800ddb..f9341b2 100644
--- a/playground.typ
+++ b/playground.typ
@@ -305,3 +305,79 @@ When some images are wide and some narrow, it might be desirable to stack severa
= "right.jpg",
=)
=```
+
+
+#let describe_image(path) = {
+ let content = image(path)
+ let size = measure(content)
+ let ratio = size.width / size.height
+ return (path: path, content: content, ratio: ratio, ..size)
+}
+
+#let aspect_ratio(item) = {
+ if type(item) == array {
+ // It's a stack! Sum the inverted ratios, then invert it again
+ return 1.0 / item.map(i => 1.0 / i.ratio).sum()
+ } else {
+ return item.ratio
+ }
+}
+
+#let image-row(gutter: 0pt, ..paths) = {
+ context {
+ // An item is either an image or a stack
+ let items = paths.pos().map(path => {
+ if type(path) == array {
+ return path.map(describe_image)
+ } else {
+ return describe_image(path)
+ }
+ })
+
+
+ let total_ratio = items.fold(0, (acc, item) => acc + aspect_ratio(item))
+ let total_gutter = gutter * (items.len() - 1)
+
+ box(layout(parent => grid(
+ columns: items.len(),
+ column-gutter: gutter,
+
+ ..items.map((item) => {
+ let width_fraction = aspect_ratio(item) / total_ratio
+ let final_width = width_fraction * (parent.width - total_gutter)
+
+ if type(item) == array {
+ grid(
+ columns: 1,
+ gutter: gutter,
+ ..item.map(stacked => {
+ let scaling_factor = final_width / stacked.width * 100%
+ scale(stacked.content, scaling_factor, reflow: true)
+ })
+ )
+ } else {
+ let scaling_factor = final_width / item.width * 100%
+ scale(item.content, scaling_factor, reflow: true)
+ }
+ })
+ )))
+ }
+}
+
+This works now without gutters
+
+#image-row(
+ gutter: 0pt,
+ "300x600.jpg",
+ ("780x300.jpg", "500x480.jpg", "780x300.jpg"),
+ "360x480.jpg",
+)
+
+But adding a gutter messes the height of the stack:
+
+#image-row(
+ gutter: 20pt,
+ "300x600.jpg",
+ ("780x300.jpg", "500x480.jpg", "780x300.jpg"),
+ "360x480.jpg",
+)