diff --git a/CHANGELOG.md b/CHANGELOG.md index 59bd4f7f..216b04bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Marking components as "Do Not Fit" - Marking components as "Do Not Change" - The internal BoM format supports KiBoM and IBoM style variants -- Schematic print to PDF support for variants. Not fitted components are crossed. +- Schematic print to PDF/SVG support for variants. Not fitted components are + crossed. - Position (Pick & Place) support for variants. - All plot formats (gerber, pdf, svg, etc.) support for variants: - Pads removed from *.Paste diff --git a/Makefile b/Makefile index 1c1102b1..888d2f6f 100644 --- a/Makefile +++ b/Makefile @@ -109,6 +109,9 @@ gen_ref: src/kibot -c tests/yaml_samples/print_pdf_no_inductors_1.kibot.yaml -e tests/board_samples/test_v5.sch -d $(REFDIR) mv "$(REFDIR)no_inductor/test_v5-schematic_(no_L).pdf" $(REFDIR) rmdir $(REFDIR)no_inductor/ + src/kibot -c tests/yaml_samples/print_svg_no_inductors_1.kibot.yaml -e tests/board_samples/test_v5.sch -d $(REFDIR) + mv "$(REFDIR)no_inductor/test_v5-schematic_(no_L).svg" $(REFDIR) + -@rm -rf $(REFDIR)no_inductor/ src/kibot -b tests/board_samples/kibom-variant_4.kicad_pcb -c tests/yaml_samples/pdf_variant_1.kibot.yaml -d $(REFDIR) src/kibot -b tests/board_samples/kibom-variant_3.kicad_pcb -c tests/yaml_samples/pcbdraw_variant_1.kibot.yaml -d $(REFDIR) src/kibot -b tests/board_samples/kibom-variant_3.kicad_pcb -c tests/yaml_samples/pcbdraw_variant_2.kibot.yaml -d $(REFDIR) diff --git a/README.md b/README.md index 1d0ec688..70c8bf67 100644 --- a/README.md +++ b/README.md @@ -989,7 +989,11 @@ Next time you need this list just use an alias, like this: - `name`: [string=''] Used to identify this particular output definition. - `options`: [dict] Options for the `svg_sch_print` output. * Valid keys: + - `dnf_filter`: [string|list(string)=''] Name of the filter to mark components as not fitted. + A short-cut to use for simple cases where a variant is an overkill. - `output`: [string='%f-%i%v.%x'] filename for the output SVG (%i=schematic %x=svg). Affected by global options. + - `variant`: [string=''] Board variant to apply. + Not fitted components are crossed. ## Using KiBot diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 5824c260..3ad78c86 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -830,6 +830,12 @@ outputs: type: 'svg_sch_print' dir: 'Example/svg_sch_print_dir' options: + # [string|list(string)=''] Name of the filter to mark components as not fitted. + # A short-cut to use for simple cases where a variant is an overkill + dnf_filter: '' # [string='%f-%i%v.%x'] filename for the output SVG (%i=schematic %x=svg). Affected by global options output: '%f-%i%v.%x' + # [string=''] Board variant to apply. + # Not fitted components are crossed + variant: '' diff --git a/kibot/out_svg_sch_print.py b/kibot/out_svg_sch_print.py index dfd97e37..6cce25bf 100644 --- a/kibot/out_svg_sch_print.py +++ b/kibot/out_svg_sch_print.py @@ -5,26 +5,38 @@ # License: GPL-3.0 # Project: KiBot (formerly KiPlot) import os +from tempfile import mkdtemp +from shutil import rmtree from .gs import (GS) from .kiplot import check_eeschema_do, exec_with_retry from .misc import (CMD_EESCHEMA_DO, SVG_SCH_PRINT) -from .optionable import BaseOptions +from .out_base import VariantOptions from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger(__name__) -class SVG_Sch_PrintOptions(BaseOptions): +class SVG_Sch_PrintOptions(VariantOptions): def __init__(self): with document: self.output = GS.def_global_output """ filename for the output SVG (%i=schematic %x=svg) """ super().__init__() + self.add_to_doc('variant', "Not fitted components are crossed") def run(self, output_dir, board): + super().run(output_dir, board) check_eeschema_do() - cmd = [CMD_EESCHEMA_DO, 'export', '--all_pages', '--file_format', 'svg', GS.sch_file, output_dir] + if self._comps: + # Save it to a temporal dir + sch_dir = mkdtemp(prefix='tmp-kibot-svg_sch_print-') + fname = GS.sch.save_variant(sch_dir) + sch_file = os.path.join(sch_dir, fname) + else: + sch_dir = None + sch_file = GS.sch_file + cmd = [CMD_EESCHEMA_DO, 'export', '--all_pages', '--file_format', 'svg', sch_file, output_dir] if GS.debug_enabled: cmd.insert(1, '-vv') cmd.insert(1, '-r') @@ -39,6 +51,10 @@ class SVG_Sch_PrintOptions(BaseOptions): new = self.expand_filename_sch(output_dir, self.output, id, ext) logger.debug('Moving '+cur+' -> '+new) os.rename(cur, new) + # Remove the temporal dir if needed + if sch_dir: + logger.debug('Removing temporal variant dir `{}`'.format(sch_dir)) + rmtree(sch_dir) @output_class diff --git a/tests/reference/test_v5-schematic_(no_L).svg b/tests/reference/test_v5-schematic_(no_L).svg new file mode 100644 index 00000000..ee0b0375 --- /dev/null +++ b/tests/reference/test_v5-schematic_(no_L).svg @@ -0,0 +1,6561 @@ + + + +SVG Picture created as test_v5.svg date 2020/09/06 17:55:29 + Picture generated by Eeschema-SVG + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + + + + +2 + + + + + +3 + + + + + +4 + + + + + + +5 + + + + + +6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + + + + +2 + + + + + +3 + + + + + +4 + + + + + + +5 + + + + + +6 + + + + + + + + + + + + + + + + + + + + +A + + + + + + +B + + + + + +C + + + + + +D + + + + + + + + + + + + + + + + + + + + +A + + + + + + +B + + + + + +C + + + + + +D + + + + + +Date: 2020-08-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +KiCad E.D.A. eeschema 5.1.6+dfsg1-1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Rev: r1B + + + + + + + + + + + + + + + +Size: A4 + + + + + + + + + + + + + + + +Id: 1/5 + + + + + + + + + + + + + + + + + + +Title: Title + + + + + + + + + + + + + + + + + + + + + + +File: test_v5.sch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Sheet: / + + + + + + + + + + + + + + +Company + + + + + + + + + + + + + + + + + +Comment 1 + + + + + + + + + + + + + + + + + + + +Comment 2 + + + + + + + + + + + + + + + + + + +Comment 3 + + + + + + + + + + + + + + + + + + +Comment 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Sheet: Sub Sheet + + + + + + + + + + + + + + + + + + + + + + + + + +File: sub-sheet.sch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +OUT + + + + + + + + + +IN + + + + + + + + + + + + + + +Sheet: Sub Sheet 2 + + + + + + + + + + + + + + + + + + + + + + + + + + +File: sub-sheet.sch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +OUT + + + + + + + + + +IN + + + + + + + + + + + + + + + + + + + + + + + + + + + + +CAUTION + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R1 + + + + +R + + + + + + + + + + + + + + + + + + + + + + + + +L1 + + + +L + + + + + + + + + + + + + + + + + +C1 + + + +C + + + + + + + + + + + + + + + + + + +R2 + + + +R_US + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +L3D + + + + + + + +L3A + + + + + + + + + + +L3B + + + + + + + +L3C + + + + + + +L2C + + + + + + + +L2B + + + + + + + + +L2D + + + + + + + +L2A + + + + + + + + + + + +L1 + + + + + + + + +Text box D + + + + + + + + + + + + + + +Text box C + + + + + + + + + + + + + + + + +Text box B + + + + + + + + + + + + + + +Text box A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_plot/test_print_sch.py b/tests/test_plot/test_print_sch.py index dc6a1042..13604b7c 100644 --- a/tests/test_plot/test_print_sch.py +++ b/tests/test_plot/test_print_sch.py @@ -107,6 +107,18 @@ def test_print_sch_variant_ni_1(): ctx.clean_up() +def test_print_sch_svg_variant_ni_1(): + """ SVG using a variant """ + prj = 'test_v5' # Is the most complete, contains every KiCad object I know + ctx = context.TestContextSCH('test_print_sch_svg_variant_ni_1', prj, 'print_svg_no_inductors_1', PDF_DIR) + ctx.run() + r_name = 'test_v5-schematic_(no_L).svg' + o_name = os.path.join(NI_DIR, r_name) + ctx.expect_out_file(o_name) + ctx.compare_image(o_name, r_name) + ctx.clean_up() + + def test_print_sch_variant_ni_2(): """ Using a filter """ prj = 'test_v5' # Is the most complete, contains every KiCad object I know diff --git a/tests/utils/context.py b/tests/utils/context.py index 25ed5e1d..a873bc6d 100644 --- a/tests/utils/context.py +++ b/tests/utils/context.py @@ -318,12 +318,23 @@ class TestContext(object): reference = self.get_out_path(reference) else: reference = os.path.join(REF_DIR, reference) + image = self.get_out_path(image) + png_ref = None + if reference[-3:] == 'svg': + png_ref = reference[:-3]+'png' + subprocess.check_call(['rsvg-convert', '-d', '300', '-p', '300', '-o', png_ref, reference]) + reference = png_ref + png_image = None + if image[-3:] == 'svg': + png_image = image[:-3]+'png' + subprocess.check_call(['rsvg-convert', '-d', '300', '-p', '300', '-o', png_image, image]) + image = png_image cmd = ['compare', # Tolerate 5 % error in color '-fuzz', fuzz, # Count how many pixels differ '-metric', 'AE', - self.get_out_path(image), + image, reference, # Avoid the part where KiCad version is printed '-crop', '100%x92%+0+0', '+repage', @@ -336,6 +347,10 @@ class TestContext(object): # logging.debug('MSE={} ({})'.format(m.group(1), m.group(2))) ae = int(res.decode()) logging.debug('AE=%d' % ae) + if png_ref: + os.remove(png_ref) + if png_image: + os.remove(png_image) assert ae == 0 def compare_pdf(self, gen, reference=None, diff='diff-{}.png'): diff --git a/tests/yaml_samples/print_svg_no_inductors_1.kibot.yaml b/tests/yaml_samples/print_svg_no_inductors_1.kibot.yaml new file mode 100644 index 00000000..537614ef --- /dev/null +++ b/tests/yaml_samples/print_svg_no_inductors_1.kibot.yaml @@ -0,0 +1,25 @@ +# Example KiBot config file +kibot: + version: 1 + +filters: + - name: 'no_inductor' + comment: 'Inductors removed' + type: generic + exclude_refs: + - L* + +variants: + - name: 'no_inductor' + comment: 'Inductors removed' + type: kibom + file_id: '_(no_L)' + dnf_filter: 'no_inductor' + +outputs: + - name: 'no_inductor' + comment: "Inductors removed" + type: svg_sch_print + dir: no_inductor + options: + variant: 'no_inductor'