Auto-discover usvg and svg-flatten properly

wip v2.2.2
jaseg 2021-09-29 18:44:09 +02:00
rodzic a1e25a0cfb
commit 29c8245d0a
4 zmienionych plików z 65 dodań i 15 usunięć

Wyświetl plik

@ -624,17 +624,24 @@ def svg_to_gerber(infile, outfile,
candidates = [os.environ['SVG_FLATTEN']]
else:
# By default, try three options:
# By default, try four options:
candidates = [
# somewhere in $PATH
'svg-flatten',
'wasi-svg-flatten',
# in user-local pip installation
Path.home() / '.local' / 'bin' / 'svg-flatten',
# next to our current python interpreter (e.g. in virtualenv
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) ]

Wyświetl plik

@ -76,6 +76,9 @@ BINARY := svg-flatten
all: $(BUILDDIR)/$(BINARY) $(BUILDDIR)/nopencv-test
.PHONY: wasm
wasm: $(BUILDDIR)/$(BINARY).wasm
$(CACHEDIR)/$(WASI_SDK):
mkdir -p $(dir $@)
cd $(dir $@); curl -L ${WASI_SDK_URL} | tar xzf -

Wyświetl plik

@ -175,7 +175,7 @@ void gerbolyze::VoronoiVectorizer::vectorize_image(RenderContext &ctx, const pug
double off_y = 0;
handle_aspect_ratio(node.attribute("preserveAspectRatio").value(),
scale_x, scale_y, off_x, off_y, orig_cols, orig_rows);
cerr << "aspect " << scale_x << ", " << scale_y << " / " << off_x << ", " << off_y << endl;
//cerr << "aspect " << scale_x << ", " << scale_y << " / " << off_x << ", " << off_y << endl;
/* Adjust minimum feature size given in mm and translate into px document units in our local coordinate system. */
min_feature_size_px = img_ctx.mat().doc2phys_dist(min_feature_size_px);
@ -255,10 +255,10 @@ void gerbolyze::VoronoiVectorizer::vectorize_image(RenderContext &ctx, const pug
vector<double> adjusted_fill_factors;
adjusted_fill_factors.reserve(32); /* Vector to hold adjusted fill factors for each edge for gap filling */
/* now iterate over all voronoi cells again to generate each cell's scaled polygon halftone blob. */
cerr << " generating cells " << diagram.numsites << endl;
//cerr << " generating cells " << diagram.numsites << endl;
for (int i=0; i<diagram.numsites; i++) {
const jcv_point center = sites[i].p;
cerr << " site center " << center.x << ", " << center.y << endl;
//cerr << " site center " << center.x << ", " << center.y << endl;
double fill_factor_ours = fill_factors[sites[i].index];
/* Do not render halftone blobs that are too small */
@ -297,7 +297,7 @@ void gerbolyze::VoronoiVectorizer::vectorize_image(RenderContext &ctx, const pug
e = e->next;
}
cerr << " blob: ";
//cerr << " blob: ";
/* Now, generate the actual halftone blob polygon */
ClipperLib::Path cell_path;
double last_fill_factor = adjusted_fill_factors.back();
@ -312,7 +312,7 @@ void gerbolyze::VoronoiVectorizer::vectorize_image(RenderContext &ctx, const pug
off_x + center.x + (e->pos[0].x - center.x) * fill_factor,
off_y + center.y + (e->pos[0].y - center.y) * fill_factor
});
cerr << " - <" << p[0] << ", " << p[1] << ">";
//cerr << " - <" << p[0] << ", " << p[1] << ">";
cell_path.push_back({
(ClipperLib::cInt)round(p[0] * clipper_scale),
(ClipperLib::cInt)round(p[1] * clipper_scale)
@ -324,7 +324,7 @@ void gerbolyze::VoronoiVectorizer::vectorize_image(RenderContext &ctx, const pug
off_x + center.x + (e->pos[1].x - center.x) * fill_factor,
off_y + center.y + (e->pos[1].y - center.y) * fill_factor
});
cerr << " - [" << p[0] << ", " << p[1] << "]";
//cerr << " - [" << p[0] << ", " << p[1] << "]";
cell_path.push_back({
(ClipperLib::cInt)round(p[0] * clipper_scale),
(ClipperLib::cInt)round(p[1] * clipper_scale)
@ -334,7 +334,7 @@ void gerbolyze::VoronoiVectorizer::vectorize_image(RenderContext &ctx, const pug
last_fill_factor = fill_factor;
e = e->next;
}
cerr << endl;
//cerr << endl;
/* Now, clip the halftone blob generated above against the given clip path. We do this individually for each
* blob since this way is *much* faster than throwing a million blobs at once at poor clipper. */

Wyświetl plik

@ -1,13 +1,14 @@
import os
import sys
import subprocess
import tempfile
import wasmtime
import platform
import click
import pathlib
from pathlib import Path
import hashlib
import appdirs
import lzma
import appdirs
from importlib import resources as importlib_resources
try:
importlib_resources.files # py3.9+ stdlib
@ -36,7 +37,7 @@ def _run_wasm_app(wasm_filename, argv, cachedir="svg-flatten-wasi"):
module_path_digest = hashlib.sha256(__file__.encode()).hexdigest()
module_digest = hashlib.sha256(module_binary).hexdigest()
cache_path = pathlib.Path(os.getenv("SVG_FLATTEN_WASI_CACHE_DIR", appdirs.user_cache_dir(cachedir)))
cache_path = Path(os.getenv("SVG_FLATTEN_WASI_CACHE_DIR", appdirs.user_cache_dir(cachedir)))
cache_path.mkdir(parents=True, exist_ok=True)
cache_filename = (cache_path / f'{wasm_filename}-{module_path_digest[:8]}-{module_digest[:16]}')
@ -72,11 +73,50 @@ def _run_wasm_app(wasm_filename, argv, cachedir="svg-flatten-wasi"):
return trap.code
def run_usvg(input_file, output_file, dpi=96):
args = ['--keep-named-groups', '--dpi', str(dpi), input_file, output_file]
# By default, try a number of options:
candidates = [
# somewhere in $PATH
'usvg',
'wasi-usvg',
# in user-local cargo installation
Path.home() / '.cargo' / 'bin' / 'usvg',
# wasi-usvg in user-local pip installation
Path.home() / '.local' / 'bin' / 'wasi-usvg',
# next to our current python interpreter (e.g. in virtualenv)
str(Path(sys.executable).parent / 'wasi-usvg')
]
# if USVG envvar is set, try that first.
if 'USVG' in os.environ:
exec_candidates = [os.environ['USVG'], *exec_candidates]
for candidate in candidates:
try:
res = subprocess.run([candidate, *args], check=True)
print('used usvg:', candidate)
break
except FileNotFoundError:
continue
else:
raise SystemError('usvg executable not found')
@click.command(context_settings={'ignore_unknown_options': True})
@click.option('--no-usvg', is_flag=True)
@click.option('--usvg-dpi', type=int, default=96)
@click.argument('other_args', nargs=-1, type=click.UNPROCESSED)
@click.argument('input_file', type=click.Path(resolve_path=True, dir_okay=False))
@click.argument('output_file', type=click.Path(resolve_path=True, dir_okay=False, writable=True))
def run_usvg(input_file, output_file, other_args):
def run_svg_flatten(input_file, output_file, other_args, usvg_dpi, no_usvg):
with tempfile.NamedTemporaryFile() as f:
if not no_usvg:
run_usvg(input_file, f.name, dpi=usvg_dpi)
input_file = f.name
cmdline = ['svg-flatten', '--force-svg', '--no-usvg', *other_args, input_file, output_file]
sys.exit(_run_wasm_app("svg-flatten.wasm", cmdline))
cmdline = ['svg-flatten', *other_args, input_file, output_file]
sys.exit(_run_wasm_app("svg-flatten.wasm", cmdline))