From b99eb3649ee383042c43d4e9ee477c8e92860358 Mon Sep 17 00:00:00 2001 From: ntjess Date: Sat, 2 Sep 2023 15:12:34 -0500 Subject: [PATCH 1/4] Add `fit-to-width` functionality --- utils/utils.typ | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/utils/utils.typ b/utils/utils.typ index ba2690b..880359f 100644 --- a/utils/utils.typ +++ b/utils/utils.typ @@ -40,7 +40,7 @@ #let last-slide-number = locate(loc => logic.logical-slide.final(loc).first()) -// HEIGHT FITTING +// HEIGHT/WIDTH FITTING #let _size-to-pt(size, styles, container-dimension) = { let to-convert = size @@ -129,6 +129,25 @@ }) } +#let fit-to-width(width: 100%, content) = { + style(styles => { + let content-size = measure(content, styles) + let content-width = content-size.width + if width < content-width { + let ratio = width / content-width * 100% + // The first box keeps content from prematurely wrapping + let scaled = scale( + box(content, width: content-width), origin: top + left, x: ratio, y: ratio + ) + // The second box lets typst know the post-scaled dimensions, since `scale` + // doesn't update layout information + box(scaled, width: width, height: content-size.height * ratio) + } else { + content + } + }) +} + // SIDE BY SIDE #let side-by-side(columns: none, gutter: 1em, ..bodies) = { From 1860c27d4025313aba130ae2c8a3effc9ac014a0 Mon Sep 17 00:00:00 2001 From: ntjess Date: Sat, 2 Sep 2023 15:13:31 -0500 Subject: [PATCH 2/4] Expose `fit-to-width` at polylux level --- polylux.typ | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polylux.typ b/polylux.typ index 25cfea1..d01b5c1 100644 --- a/polylux.typ +++ b/polylux.typ @@ -2,4 +2,4 @@ #import "logic.typ" #import "logic.typ": polylux-slide, uncover, only, alternatives, alternatives-match, alternatives-fn, alternatives-cases, one-by-one, line-by-line, list-one-by-one, enum-one-by-one, terms-one-by-one, pause, enable-handout-mode #import "utils/utils.typ" -#import "utils/utils.typ": polylux-outline, fit-to-height, side-by-side, pdfpc +#import "utils/utils.typ": polylux-outline, fit-to-height, fit-to-width, side-by-side, pdfpc From 0112c70e06d6814a146bbc90b4a47d0806a49d3e Mon Sep 17 00:00:00 2001 From: ntjess Date: Sat, 2 Sep 2023 15:24:48 -0500 Subject: [PATCH 3/4] Allow relative width in `fit-to-width` --- utils/utils.typ | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/utils/utils.typ b/utils/utils.typ index 880359f..ccc0c2c 100644 --- a/utils/utils.typ +++ b/utils/utils.typ @@ -129,22 +129,25 @@ }) } -#let fit-to-width(width: 100%, content) = { +#let fit-to-width(width, content) = { style(styles => { - let content-size = measure(content, styles) - let content-width = content-size.width - if width < content-width { - let ratio = width / content-width * 100% - // The first box keeps content from prematurely wrapping - let scaled = scale( - box(content, width: content-width), origin: top + left, x: ratio, y: ratio - ) - // The second box lets typst know the post-scaled dimensions, since `scale` - // doesn't update layout information - box(scaled, width: width, height: content-size.height * ratio) - } else { - content - } + layout(layout-size => { + let content-size = measure(content, styles) + let content-width = content-size.width + let width = _size-to-pt(width, styles, layout-size.width) + if width < content-width { + let ratio = width / content-width * 100% + // The first box keeps content from prematurely wrapping + let scaled = scale( + box(content, width: content-width), origin: top + left, x: ratio, y: ratio + ) + // The second box lets typst know the post-scaled dimensions, since `scale` + // doesn't update layout information + box(scaled, width: width, height: content-size.height * ratio) + } else { + content + } + }) }) } From 3c921180f84bbd03dc7b921d7180c7ffafddb4d1 Mon Sep 17 00:00:00 2001 From: Nathan Jessurun Date: Sat, 2 Sep 2023 18:27:52 -0500 Subject: [PATCH 4/4] Optionally restrict whether content can grow or shrink during `fit`ting --- utils/utils.typ | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/utils/utils.typ b/utils/utils.typ index ccc0c2c..66dd825 100644 --- a/utils/utils.typ +++ b/utils/utils.typ @@ -60,7 +60,9 @@ box(width: mutable-width, body) } -#let fit-to-height(height, width: none, prescale-width: none, body) = { +#let fit-to-height( + width: none, prescale-width: none, grow: true, shrink: true, height, body +) = { // Place two labels with the requested vertical separation to be able to // measure their vertical distance in pt. // Using this approach instead of using `measure` allows us to accept fractions @@ -113,29 +115,39 @@ let w-ratio = mutable-width / size.width let ratio = calc.min(h-ratio, w-ratio) * 100% - let new-width = size.width * ratio - v(-available-height) - // If not boxed, the content can overflow to the next page even though it will fit. - // This is because scale doesn't update the layout information. - // Boxing in a container without clipping will inform typst that content - // will indeed fit in the remaining space - box( - width: new-width, - height: available-height, - scale(x: ratio, y: ratio, origin: top + left, boxed-content) - ) + if ( + (shrink and (ratio < 100%)) + or (grow and (ratio > 100%)) + ) { + let new-width = size.width * ratio + v(-available-height) + // If not boxed, the content can overflow to the next page even though it will + // fit. This is because scale doesn't update the layout information. + // Boxing in a container without clipping will inform typst that content + // will indeed fit in the remaining space + box( + width: new-width, + height: available-height, + scale(x: ratio, y: ratio, origin: top + left, boxed-content) + ) + } else { + body + } }) }) }) } -#let fit-to-width(width, content) = { +#let fit-to-width(grow: true, shrink: true, width, content) = { style(styles => { layout(layout-size => { let content-size = measure(content, styles) let content-width = content-size.width let width = _size-to-pt(width, styles, layout-size.width) - if width < content-width { + if ( + (shrink and (width < content-width)) + or (grow and (width > content-width)) + ) { let ratio = width / content-width * 100% // The first box keeps content from prematurely wrapping let scaled = scale(