From 44006784f0b72a3fe7e29c818e45a533a02641a7 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 8 Jan 2022 23:30:38 +0100 Subject: Basic SVG export seems to be working --- gerbonara/gerber/tests/image_support.py | 24 ++++++++++------- gerbonara/gerber/tests/test_rs274x.py | 48 ++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 11 deletions(-) (limited to 'gerbonara/gerber/tests') diff --git a/gerbonara/gerber/tests/image_support.py b/gerbonara/gerber/tests/image_support.py index db44157..dc2cbdb 100644 --- a/gerbonara/gerber/tests/image_support.py +++ b/gerbonara/gerber/tests/image_support.py @@ -60,16 +60,16 @@ def run_cargo_cmd(cmd, args, **kwargs): except FileNotFoundError: return subprocess.run([str(Path.home() / '.cargo' / 'bin' / cmd), *args], **kwargs) -def svg_to_png(in_svg, out_png): - run_cargo_cmd('resvg', ['--dpi', '100', in_svg, out_png], check=True, stdout=subprocess.DEVNULL) +def svg_to_png(in_svg, out_png, dpi=100): + run_cargo_cmd('resvg', ['--dpi', str(dpi), in_svg, out_png], check=True, stdout=subprocess.DEVNULL) -def gbr_to_svg(in_gbr, out_svg, origin=(0, 0), size=(6, 6)): +def gerbv_export(in_gbr, out_svg, format='svg', origin=(0, 0), size=(6, 6), fg='#ffffff'): x, y = origin w, h = size - cmd = ['gerbv', '-x', 'svg', + cmd = ['gerbv', '-x', format, '--border=0', f'--origin={x:.6f}x{y:.6f}', f'--window_inch={w:.6f}x{h:.6f}', - '--foreground=#ffffff', + f'--foreground={fg}', '-o', str(out_svg), str(in_gbr)] subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) @@ -94,12 +94,16 @@ def cleanup_clips(soup): # Apart from being graphically broken, this additionally causes very bad rendering performance. del group['clip-path'] +def cleanup_gerbv_svg(filename): + with svg_soup(filename) as soup: + cleanup_clips(soup) + def gerber_difference(reference, actual, diff_out=None, svg_transform=None, size=(10,10)): with tempfile.NamedTemporaryFile(suffix='.svg') as act_svg,\ tempfile.NamedTemporaryFile(suffix='.svg') as ref_svg: - gbr_to_svg(reference, ref_svg.name, size=size) - gbr_to_svg(actual, act_svg.name, size=size) + gerbv_export(reference, ref_svg.name, size=size, format='svg') + gerbv_export(actual, act_svg.name, size=size, format='svg') with svg_soup(ref_svg.name) as soup: if svg_transform is not None: @@ -116,9 +120,9 @@ def gerber_difference_merge(ref1, ref2, actual, diff_out=None, composite_out=Non tempfile.NamedTemporaryFile(suffix='.svg') as ref1_svg,\ tempfile.NamedTemporaryFile(suffix='.svg') as ref2_svg: - gbr_to_svg(ref1, ref1_svg.name, size=size) - gbr_to_svg(ref2, ref2_svg.name, size=size) - gbr_to_svg(actual, act_svg.name, size=size) + gerbv_export(ref1, ref1_svg.name, size=size, format='svg') + gerbv_export(ref2, ref2_svg.name, size=size, format='svg') + gerbv_export(actual, act_svg.name, size=size, format='svg') with svg_soup(ref1_svg.name) as soup1: if svg_transform1 is not None: diff --git a/gerbonara/gerber/tests/test_rs274x.py b/gerbonara/gerber/tests/test_rs274x.py index 90ccdb9..de06a16 100644 --- a/gerbonara/gerber/tests/test_rs274x.py +++ b/gerbonara/gerber/tests/test_rs274x.py @@ -17,7 +17,7 @@ import pytest from ..rs274x import GerberFile from ..cam import FileSettings -from .image_support import gerber_difference, gerber_difference_merge +from .image_support import * deg_to_rad = lambda a: a/180 * math.pi @@ -62,6 +62,30 @@ def temp_files(request): else: print(f'gerbv {perm_path_gbr} {reference_path(args["file_a"])} {reference_path(args["file_b"])}') +@pytest.fixture +def svg_temp_files(request): + with tempfile.NamedTemporaryFile(suffix='.svg') as out_svg,\ + tempfile.NamedTemporaryFile(suffix='.png') as out_png,\ + tempfile.NamedTemporaryFile(suffix='.png') as ref_png,\ + tempfile.NamedTemporaryFile(suffix='.png') as tmp_png: + yield Path(out_svg.name), Path(out_png.name), Path(ref_png.name), Path(tmp_png.name) + + if request.node.rep_call.failed: + module, _, test_name = request.node.nodeid.rpartition('::') + _test, _, test_name = test_name.partition('_') + test_name, _, _ext = test_name.partition('.') + test_name = re.sub(r'[^\w\d]', '_', test_name) + fail_dir.mkdir(exist_ok=True) + perm_path_out_svg = fail_dir / f'failure_{test_name}_actual.svg' + perm_path_png = fail_dir / f'failure_{test_name}_difference.png' + shutil.copy(out_svg.name, perm_path_out_svg) + shutil.copy(tmp_png.name, perm_path_png) + args = request.node.funcargs + print(f'Reference file is {reference_path(args["reference"])}') + print(f'Failing output saved to {perm_path_out_svg}') + print(f'Difference image saved to {perm_path_png}') + + to_gerbv_svg_units = lambda val, unit='mm': val*72 if unit == 'inch' else val/25.4*72 REFERENCE_FILES = [ l.strip() for l in ''' @@ -284,4 +308,26 @@ def test_compositing(temp_files, file_a, file_b, angle, offset): assert hist[9] < 100 assert hist[3:].sum() < 1e-3*hist.size +@pytest.mark.filterwarnings('ignore:Deprecated.*statement found.*:DeprecationWarning') +@pytest.mark.filterwarnings('ignore::SyntaxWarning') +@pytest.mark.parametrize('reference', REFERENCE_FILES) +def test_svg_export(svg_temp_files, reference): + ref = reference_path(reference) + grb = GerberFile.open(ref) + out_svg, out_png, ref_png, tmp_png = svg_temp_files + + bounds = (0.0, 0.0), (6.0, 6.0) # bottom left, top right + + with open(out_svg, 'w') as f: + f.write(str(grb.to_svg(force_bounds=bounds, arg_unit='inch'))) + + gerbv_export(ref, ref_png, origin=bounds[0], size=bounds[1], format='png', fg='#000000') + svg_to_png(out_svg, out_png, dpi=72) # make dpi match Cairo's default + + mean, _max, hist = image_difference(ref_png, out_png, diff_out=tmp_png) + assert mean < 1e-3 + assert hist[9] < 1 + assert hist[3:].sum() < 1e-3*hist.size + +# FIXME test svg margin, bounding box computation -- cgit