From b3807b6530af906faf3a0113a98c994cb7f394a5 Mon Sep 17 00:00:00 2001
From: jaseg <git@jaseg.de>
Date: Fri, 20 May 2022 16:55:28 +0200
Subject: WIP

---
 gerbolyze/gerbolyze.py | 131 ++++++++++++++++---------------------------------
 setup.py               |   4 +-
 2 files changed, 43 insertions(+), 92 deletions(-)

diff --git a/gerbolyze/gerbolyze.py b/gerbolyze/gerbolyze.py
index 53b10a4..aaac83d 100755
--- a/gerbolyze/gerbolyze.py
+++ b/gerbolyze/gerbolyze.py
@@ -19,36 +19,13 @@ import gerberex
 import gerberex.rs274x
 import numpy as np
 import click
-from slugify import slugify
+
+import gerbonara as gn
 
 @click.group()
 def cli():
     pass
 
-
-@cli.command()
-@click.option('-l', '--layer', type=click.Choice(['silk', 'mask', 'copper']), default='silk')
-@click.option('-x', '--exact', flag_value=True)
-@click.option('--trace-space', type=float, default=0.1, help='passed through to svg-flatten')
-@click.argument('side', type=click.Choice(['top', 'bottom']))
-@click.argument('source')
-@click.argument('target')
-@click.argument('image')
-@click.pass_context
-def vectorize(ctx, side, layer, exact, source, target, image, trace_space):
-    """ Compatibility command for Gerbolyze version 1.
-
-        This command is deprecated, please update your code to call "gerbolyze paste" instead.
-    """
-    ctx.invoke(paste, 
-        input_gerbers=source,
-        output_gerbers=target,
-        **{side: image, f'layer_{side}': layer},
-        no_subtract=exact,
-        trace_space=trace_space,
-        vectorizer='binary-contours',
-        preserve_aspect_ratio='meet')
-
 @cli.command()
 @click.argument('input_gerbers')
 @click.argument('output_gerbers')
@@ -159,9 +136,9 @@ def paste(input_gerbers, output_gerbers,
                 print('rendering layer', layer)
                 overlay_file = tmpdir / f'overlay-{side}-{layer}.gbr'
                 layer_arg = layer if target_layer is None else None # slightly confusing but trust me :)
-                svg_to_gerber(in_svg_or_png, overlay_file, layer_arg,
+                svg_to_gerber(in_svg_or_png, overlay_file, only_groups=f'g-{layer_arg.lower()}',
                         trace_space, vectorizer, vectorizer_map, exclude_groups, curve_tolerance,
-                        bounds_for_png=bounds, preserve_aspect_ratio=preserve_aspect_ratio,
+                        layer_bounds=bounds, preserve_aspect_ratio=preserve_aspect_ratio,
                         outline_mode=(layer == 'outline'))
 
                 overlay_grb = gerberex.read(str(overlay_file))
@@ -502,7 +479,7 @@ def load_side(side_matches):
 DEFAULT_EXTRA_LAYERS = [ layer for layer in LAYER_RENDER_ORDER if layer != "drill" ]
 
 def template_layer(name):
-    return f'<g id="g-{slugify(name)}" inkscape:label="{name}" inkscape:groupmode="layer"></g>'
+    return f'<g id="g-{name.lower()}" inkscape:label="{name}" inkscape:groupmode="layer"></g>'
 
 def template_svg_for_png(bounds, png_data, extra_layers=DEFAULT_EXTRA_LAYERS, current_layer='silk'):
     (x1, x2), (y1, y2) = bounds
@@ -519,7 +496,7 @@ def template_svg_for_png(bounds, png_data, extra_layers=DEFAULT_EXTRA_LAYERS, cu
            xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
            width="{w_mm}mm" height="{h_mm}mm" viewBox="0 0 {w_mm} {h_mm}" >
           <defs/>
-          <sodipodi:namedview inkscape:current-layer="g-{slugify(current_layer)}" />
+          <sodipodi:namedview inkscape:current-layer="g-{current_layer.lower()}" />
           <g inkscape:label="Preview" inkscape:groupmode="layer" id="g-preview" sodipodi:insensitive="true" style="opacity:0.5">
             <image x="0" y="0" width="{w_mm}" height="{h_mm}"
                xlink:href="data:image/jpeg;base64,{base64.b64encode(png_data).decode()}" />
@@ -571,7 +548,7 @@ def create_template_from_svg(bounds, svg_data, extra_layers=DEFAULT_EXTRA_LAYERS
     # add layers
     for layer in extra_layers:
         new_g = etree.SubElement(svg, SVG_NS+'g')
-        new_g.set('id', f'g-{slugify(layer)}')
+        new_g.set('id', f'g-{layer.lower()}')
         new_g.set(INKSCAPE_NS+'label', layer)
         new_g.set(INKSCAPE_NS+'groupmode', 'layer')
 
@@ -601,91 +578,65 @@ def dilate_gerber(layers, layer_name, dilation, bbox, tmpdir, outfile, units, cu
         f'--origin={origin_x:.6f}x{origin_y:.6f}', f'--window_inch={width:.6f}x{height:.6f}',
         '--foreground=#ffffff',
         '-o', str(tmpfile), str(path)]
-    print('dilation cmd:', ' '.join(cmd))
     subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 
     # dilate & render back to gerber
     # TODO: the scale parameter is a hack. ideally we would fix svg-flatten to handle input units correctly.
-    svg_to_gerber(tmpfile, outfile, dilate=-dilation*72.0/25.4, dpi=72, scale=25.4/72.0, curve_tolerance=curve_tolerance)
+    svg_to_gerber(tmpfile, outfile, dilate=-dilation*72.0/25.4, usvg_dpi=72, scale=25.4/72.0, curve_tolerance=curve_tolerance)
 
 def svg_to_gerber(infile, outfile,
-        layer=None, trace_space:'mm'=0.1,
-        vectorizer=None, vectorizer_map=None,
-        exclude_groups=None,
-        dilate=None, curve_tolerance=None,
-        dpi=None, scale=None, bounds_for_png=None,
-        preserve_aspect_ratio=None,
-        force_png=False, force_svg=False,
-        outline_mode=False):
+        layer_bounds=None, outline_mode=False,
+        **kwargs):
+
+        trace_space:'mm'=0.1,
 
     infile = Path(infile)
 
+    args = [ '--format', ('gerber-outline' if outline_mode else 'gerber'),
+            '--precision', '6', # intermediate file, use higher than necessary precision
+            ]
+    
+    if kwargs.get('force_png') or (infile.suffix.lower() in ['.jpg', '.png'] and not kwargs.get('force_svg')):
+        (min_x, max_x), (min_y, max_y) = layer_bounds
+        kwargs['size'] = f'{max_x - min_x}x{max_y - min_y}'
+
+    for k, v in kwargs.items():
+        if v is not None:
+            args.append('--' + k.replace('_', '-'))
+            if not isinstance(v, bool):
+                args.append(str(v))
+
+    args += [str(infile), str(outfile)]
+
     if 'SVG_FLATTEN' in os.environ:
-        candidates = [os.environ['SVG_FLATTEN']]
+        subprocess.run([os.environ['SVG_FLATTEN'], *args], check=True)
 
     else:
         # By default, try four options:
-        candidates = [
+        for candidate in [
                 # somewhere in $PATH
                 'svg-flatten',
                 'wasi-svg-flatten',
+
                 # in user-local pip installation
                 Path.home() / '.local' / 'bin' / 'svg-flatten',
                 Path.home() / '.local' / 'bin' / 'wasi-svg-flatten',
+
                 # next to our current python interpreter (e.g. in virtualenv)
                 str(Path(sys.executable).parent / 'svg-flatten'),
                 str(Path(sys.executable).parent / 'wasi-svg-flatten'),
-                # next to this python source file in the development repo
-                str(Path(__file__).parent.parent / 'svg-flatten' / 'build' / 'svg-flatten') ]
-
-        # if SVG_FLATTEN envvar is set, try that first.
-        if 'SVG_FLATTEN' in os.environ:
-            candidates = [os.environ['SVG_FLATTEN'], *candidates]
 
-    args = [ '--format', ('gerber-outline' if outline_mode else 'gerber'),
-            '--precision', '6', # intermediate file, use higher than necessary precision
-            '--trace-space', str(trace_space) ]
-    if layer:
-        args += ['--only-groups', f'g-{slugify(layer)}']
-    if vectorizer:
-        args += ['--vectorizer', vectorizer]
-    if vectorizer_map:
-        args += ['--vectorizer-map', vectorizer_map]
-    if exclude_groups:
-        args += ['--exclude-groups', exclude_groups]
-    if dilate:
-        args += ['--dilate', str(dilate)]
-    if curve_tolerance is not None:
-        print('applying curve tolerance', curve_tolerance)
-        args += ['--curve-tolerance', str(curve_tolerance)]
-    if dpi:
-        args += ['--usvg-dpi', str(dpi)]
-    if scale:
-        args += ['--scale', str(scale)]
-    if force_png or (infile.suffix.lower() in ['.jpg', '.png'] and not force_svg):
-        (min_x, max_x), (min_y, max_y) = bounds_for_png
-        args += ['--size', f'{max_x - min_x}x{max_y - min_y}']
-    if force_svg and force_png:
-        raise ValueError('both force_svg and force_png given')
-    if force_svg:
-        args += ['--force-svg']
-    if force_png:
-        args += ['--force-png']
-    if preserve_aspect_ratio:
-        args += ['--preserve-aspect-ratio', preserve_aspect_ratio]
+                # next to this python source file in the development repo
+                str(Path(__file__).parent.parent / 'svg-flatten' / 'build' / 'svg-flatten') ]:
 
-    args += [str(infile), str(outfile)]
+            try:
+                subprocess.run([candidate, *args], check=True)
+                break
+            except FileNotFoundError:
+                continue
 
-    print('svg-flatten args:', ' '.join(args))
-    for candidate in candidates:
-        try:
-            res = subprocess.run([candidate, *args], check=True)
-            print('used svg-flatten:', candidate)
-            break
-        except FileNotFoundError:
-            continue
-    else:
-        raise SystemError('svg-flatten executable not found')
+        else:
+            raise SystemError('svg-flatten executable not found')
     
 
 if __name__ == '__main__':
diff --git a/setup.py b/setup.py
index a3005b5..be92a3f 100755
--- a/setup.py
+++ b/setup.py
@@ -38,8 +38,8 @@ setup(
         "Bug Tracker": "https://github.com/jaseg/gerbolyze/issues",
     },
     author = 'jaseg',
-    author_email = 'github@jaseg.de',
-    install_requires = ['pcb-tools', 'numpy', 'python-slugify', 'lxml', 'click', 'pcb-tools-extension'],
+    author_email = 'gerbonara@jaseg.de',
+    install_requires = ['gerbonara', 'numpy', 'python-slugify', 'lxml', 'click'],
     extras_require = {
         'wasi': [f'svg-flatten-wasi[resvg-wasi] >= {version()}'],
     },
-- 
cgit