From 48c8765e82da6938aae397ae07127778918f8a27 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Sat, 20 Nov 2021 19:06:10 +0100 Subject: [PATCH] Fix viewer crash with empty layers (#339) Fixes #338 --- .gitignore | 3 +- CHANGELOG.md | 1 + tests/test_viewer.py | 79 ++++++++++++++++++++++-------------------- vpype_viewer/engine.py | 6 ++-- 4 files changed, 48 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index 6c090d04..8e373fb0 100644 --- a/.gitignore +++ b/.gitignore @@ -144,4 +144,5 @@ cython_debug/ /bug_reports /W3C_SVG_11_TestSuite /my_work -/pip-wheel-metadata \ No newline at end of file +/pip-wheel-metadata +/test_report_img_sim/ diff --git a/CHANGELOG.md b/CHANGELOG.md index a9842515..65d89db1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ New features and improvements: Bug fixes: * Fixed issue with HPGL export where page size auto-detection would fail when using the default device from the config file (instead of specifying the device with `--device`) (#328) +* Fixed issue where the viewer would crash with empty layers (#339) #### 1.7 (2021-06-10) diff --git a/tests/test_viewer.py b/tests/test_viewer.py index 2adc5488..d84550fb 100644 --- a/tests/test_viewer.py +++ b/tests/test_viewer.py @@ -14,6 +14,38 @@ from .utils import TEST_FILE_DIRECTORY +RENDER_KWARGS = [ + pytest.param({"view_mode": ViewMode.OUTLINE}, id="outline"), + pytest.param({"view_mode": ViewMode.OUTLINE_COLORFUL}, id="outline_colorful"), + pytest.param({"view_mode": ViewMode.PREVIEW}, id="preview"), + pytest.param({"view_mode": ViewMode.OUTLINE, "show_points": True}, id="points"), + pytest.param( + {"view_mode": ViewMode.OUTLINE_COLORFUL, "show_points": True}, id="colorful_points" + ), + pytest.param({"view_mode": ViewMode.OUTLINE, "show_pen_up": True}, id="outline_pen_up"), + pytest.param({"view_mode": ViewMode.PREVIEW, "show_pen_up": True}, id="preview_pen_up"), + pytest.param( + {"view_mode": ViewMode.PREVIEW, "pen_opacity": 0.3}, id="preview_transparent" + ), + pytest.param({"view_mode": ViewMode.PREVIEW, "pen_width": 4.0}, id="preview_thick"), + pytest.param( + {"view_mode": ViewMode.OUTLINE, "show_ruler": True, "unit_type": UnitType.PIXELS}, + id="outline_pixels", + ), + pytest.param( + {"view_mode": ViewMode.OUTLINE, "show_ruler": True, "unit_type": UnitType.METRIC}, + id="outline_metric", + ), + pytest.param( + { + "view_mode": ViewMode.OUTLINE, + "show_ruler": True, + "unit_type": UnitType.IMPERIAL, + }, + id="outline_imperial", + ), +] + # assert_image_similarity fixture added for automated exclusion on unsupported runner def test_viewer_engine_properties(assert_image_similarity): @@ -67,44 +99,7 @@ def test_viewer_engine_properties(assert_image_similarity): ["misc/empty.svg", "misc/multilayer.svg", "issue_124/plotter.svg"], ids=lambda s: os.path.splitext(s)[0], ) -@pytest.mark.parametrize( - "render_kwargs", - [ - pytest.param({"view_mode": ViewMode.OUTLINE}, id="outline"), - pytest.param({"view_mode": ViewMode.OUTLINE_COLORFUL}, id="outline_colorful"), - pytest.param({"view_mode": ViewMode.PREVIEW}, id="preview"), - pytest.param({"view_mode": ViewMode.OUTLINE, "show_points": True}, id="points"), - pytest.param( - {"view_mode": ViewMode.OUTLINE_COLORFUL, "show_points": True}, id="colorful_points" - ), - pytest.param( - {"view_mode": ViewMode.OUTLINE, "show_pen_up": True}, id="outline_pen_up" - ), - pytest.param( - {"view_mode": ViewMode.PREVIEW, "show_pen_up": True}, id="preview_pen_up" - ), - pytest.param( - {"view_mode": ViewMode.PREVIEW, "pen_opacity": 0.3}, id="preview_transparent" - ), - pytest.param({"view_mode": ViewMode.PREVIEW, "pen_width": 4.0}, id="preview_thick"), - pytest.param( - {"view_mode": ViewMode.OUTLINE, "show_ruler": True, "unit_type": UnitType.PIXELS}, - id="outline_pixels", - ), - pytest.param( - {"view_mode": ViewMode.OUTLINE, "show_ruler": True, "unit_type": UnitType.METRIC}, - id="outline_metric", - ), - pytest.param( - { - "view_mode": ViewMode.OUTLINE, - "show_ruler": True, - "unit_type": UnitType.IMPERIAL, - }, - id="outline_imperial", - ), - ], -) +@pytest.mark.parametrize("render_kwargs", RENDER_KWARGS) def test_viewer(assert_image_similarity, file, render_kwargs): doc = vp.read_multilayer_svg(str(TEST_FILE_DIRECTORY / file), 0.4) @@ -112,6 +107,14 @@ def test_viewer(assert_image_similarity, file, render_kwargs): assert_image_similarity(render_image(doc, (1024, 1024), **render_kwargs)) +@pytest.mark.parametrize("render_kwargs", RENDER_KWARGS) +def test_viewer_empty_layer(assert_image_similarity, render_kwargs): + # Note: assert_image_similarity added to avoid running CI tests on Linux + doc = vp.Document() + doc.add(vp.LineCollection(), 1) + render_image(doc, (1024, 1024), **render_kwargs) + + def test_viewer_zoom_scale(assert_image_similarity): doc = vp.read_multilayer_svg(str(TEST_FILE_DIRECTORY / "issue_124/plotter.svg"), 0.4) renderer = ImageRenderer((1024, 1024)) diff --git a/vpype_viewer/engine.py b/vpype_viewer/engine.py index e29a680a..cc08e002 100644 --- a/vpype_viewer/engine.py +++ b/vpype_viewer/engine.py @@ -427,7 +427,11 @@ def _rebuild(self): color_index = 0 for layer_id in sorted(self._document.layers): layer_color: ColorType = _COLORS[color_index % len(_COLORS)] + color_index += 1 + lc = self._document.layers[layer_id] + if lc.is_empty(): + continue if self.view_mode == ViewMode.OUTLINE: self._layer_painters[layer_id].append( @@ -463,8 +467,6 @@ def _rebuild(self): LineCollectionPointsPainter(self._ctx, lc=lc, color=layer_color) ) - color_index += 1 - page_size = self._document.page_size if page_size is not None: self._paper_bounds_painter = PaperBoundsPainter(