diff --git a/CHANGELOG.md b/CHANGELOG.md index dd92c7f1..0227d523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ Release date: UNRELEASED ### New features and improvements * Added support for Python 3.12 and dropped support for Python 3.9 (#681) -* Added an option to the `reverse` command to also flip the line direction (#654) +* Added a `--no-bbox` option to the `layout` command to use the pre-existing page size instead of the geometry bounding box as basis for layout (#682) +* Added a `--flip` option to the `reverse` command to also flip the line direction (#654) * Added a `--hyphenate LANG` option to the `text` command (thanks to @pepijndevos) (#668) ### Bug fixes diff --git a/tests/test_commands.py b/tests/test_commands.py index 5387231b..53fdbd77 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -82,6 +82,14 @@ class Command: Command("reverse"), Command("reverse --flip"), Command("layout a4", keeps_page_size=False), + Command("layout -m 3cm a4", keeps_page_size=False), + Command( + "layout --no-bbox a4", + keeps_page_size=False, + exit_code_one_layer=2, + exit_code_no_layer=2, + exit_code_two_layers=2, + ), Command("squiggles"), Command("text 'hello wold'"), Command("penwidth 0.15mm", preserves_metadata=False), @@ -569,6 +577,12 @@ def test_layout_tight(): assert doc.page_size == pytest.approx((4 * CM, 5 * CM)) +def test_layout_no_bbox(): + doc = vpype_cli.execute("pagesize 10x10cm rect 0 0 1cm 1cm layout --no-bbox 30x30cm") + assert doc.page_size == pytest.approx((30 * CM, 30 * CM)) + assert doc.bounds() == pytest.approx((10 * CM, 10 * CM, 11 * CM, 11 * CM)) + + def test_layout_empty(): """page size is set to size provided to layout, unless it's tight, in which case it is unchanged""" diff --git a/vpype_cli/operations.py b/vpype_cli/operations.py index 2a2719b1..eff7aa28 100644 --- a/vpype_cli/operations.py +++ b/vpype_cli/operations.py @@ -529,6 +529,10 @@ def pagesize(document: vp.Document, size, landscape) -> vp.Document: geometries. If `--fit-to-margins` is used, the page size is increased to accommodate the margin. By construction, `--align` and `--valign` have no effect with `tight`. +By default, `layout` considers the bounding box of the existing geometries as the area to +fit on the page. Alternatively, the current page size can be used with the `--no-bbox` option. +Using `--no-box` without a page size set is an error. + On an empty pipeline, `layout` simply sets the page size to SIZE, unless `tight` is used. In this case, `layout` has no effect at all. @@ -571,6 +575,13 @@ def pagesize(document: vp.Document, size, landscape) -> vp.Document: default="center", help="Vertical alignment", ) +@click.option( + "-b", + "--no-bbox", + is_flag=True, + default=False, + help="Use existing page size instead of the geometry bounding box", +) @global_processor def layout( document: vp.Document, @@ -579,11 +590,24 @@ def layout( margin: float | None, align: str, valign: str, + no_bbox: bool, ) -> vp.Document: """Layout command""" size = _normalize_page_size(size, landscape) - bounds = document.bounds() + if no_bbox: + page_size = document.page_size + if page_size is None: + raise click.BadParameter("no page size defined and --no-bbox used") + bounds: tuple[float, float, float, float] | None = ( + 0.0, + 0.0, + page_size[0], + page_size[1], + ) + else: + bounds = document.bounds() + tight = size == vp.PAGE_SIZES["tight"] # handle empty geometry special cases