Added output to print PCB layers in SVG format

- Also added support for them in the reports
- Changed the full report to use them
This commit is contained in:
Salvador E. Tropea 2022-03-03 13:13:46 -03:00
parent 49962cafb8
commit 562e36d6f5
11 changed files with 352 additions and 162 deletions

View File

@ -66,6 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added global options to define the PCB details (`pcb_material`, - Added global options to define the PCB details (`pcb_material`,
`solder_mask_color`, `silk_screen_color` and `pcb_finish`) `solder_mask_color`, `silk_screen_color` and `pcb_finish`)
- Report generation (for design house) (#93) - Report generation (for design house) (#93)
- New output to print PCB layers in SVG format.
### Changed ### Changed
- Internal BoM: now components with different Tolerance, Voltage, Current - Internal BoM: now components with different Tolerance, Voltage, Current

View File

@ -1914,6 +1914,47 @@ Next time you need this list just use an alias, like this:
- `output_id`: [string=''] Text to use for the %I expansion content. To differentiate variations of this output. - `output_id`: [string=''] Text to use for the %I expansion content. To differentiate variations of this output.
- `run_by_default`: [boolean=true] When enabled this output will be created when no specific outputs are requested. - `run_by_default`: [boolean=true] When enabled this output will be created when no specific outputs are requested.
* SVG PCB Print (Scalable Vector Graphics)
* Type: `svg_pcb_print`
* Description: Exports the PCB to the scalable vector graphics format.
This output is what you get from the 'File/Print' menu in pcbnew.
* Valid keys:
- `comment`: [string=''] A comment for documentation purposes.
- `dir`: [string='./'] Output directory for the generated files. If it starts with `+` the rest is concatenated to the default dir.
- `disable_run_by_default`: [string|boolean] Use it to disable the `run_by_default` status of other output.
Useful when this output extends another and you don't want to generate the original.
Use the boolean true value to disable the output you are extending.
- `extends`: [string=''] Copy the `options` section from the indicated output.
- `layers`: [list(dict)|list(string)|string] [all,selected,copper,technical,user]
List of PCB layers to include in the PDF.
* Valid keys:
- `description`: [string=''] A description for the layer, for documentation purposes.
- `layer`: [string=''] Name of the layer. As you see it in KiCad.
- `suffix`: [string=''] Suffix used in file names related to this layer. Derived from the name if not specified.
- `name`: [string=''] Used to identify this particular output definition.
- `options`: [dict] Options for the `pdf_pcb_print` output.
* Valid keys:
- `dnf_filter`: [string|list(string)='_none'] Name of the filter to mark components as not fitted.
A short-cut to use for simple cases where a variant is an overkill.
- `drill_marks`: [string='full'] What to use to indicate the drill places, can be none, small or full (for real scale).
- `enable_ki6_page_fix`: [boolean=true] Enable workaround for KiCad 6 bug #11033.
- `force_edge_cuts`: [boolean=true] Only useful for KiCad 6 when printing in one page, you can disable the edge here.
KiCad 5 forces it by default, and you can't control it from config files.
Same for KiCad 6 when printing to separated pages.
- `hide_excluded`: [boolean=false] Hide components in the Fab layer that are marked as excluded by a variant.
- `mirror`: [boolean=false] Print mirrored (X axis inverted). ONLY for KiCad 6.
- `monochrome`: [boolean=false] Print in black and white.
- `output`: [string='%f-%i%I%v.%x'] Filename for the output SVG (%i=layers, %x=svg). Affected by global options.
- *output_name*: Alias for output.
- `plot_sheet_reference`: [boolean=true] Include the title-block.
- `scaling`: [number=1.0] Scale factor (0 means autoscaling).
- `separated`: [boolean=false] Print layers in separated pages.
- `title`: [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated.
- `variant`: [string=''] Board variant to apply.
- `output_id`: [string=''] Text to use for the %I expansion content. To differentiate variations of this output.
- `run_by_default`: [boolean=true] When enabled this output will be created when no specific outputs are requested.
* SVG Schematic Print * SVG Schematic Print
* Type: `svg_sch_print` * Type: `svg_sch_print`
* Description: Exports the PCB. Suitable for printing. * Description: Exports the PCB. Suitable for printing.

View File

@ -1342,6 +1342,45 @@ outputs:
# [string=''] Board variant to apply # [string=''] Board variant to apply
variant: '' variant: ''
layers: all layers: all
# SVG PCB Print (Scalable Vector Graphics):
# This output is what you get from the 'File/Print' menu in pcbnew.
- name: 'svg_pcb_print_example'
comment: 'Exports the PCB to the scalable vector graphics format.'
type: 'svg_pcb_print'
dir: 'Example/svg_pcb_print_dir'
options:
# [string|list(string)='_none'] 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: '_none'
# [string='full'] What to use to indicate the drill places, can be none, small or full (for real scale)
drill_marks: 'full'
# [boolean=true] Enable workaround for KiCad 6 bug #11033
enable_ki6_page_fix: true
# [boolean=true] Only useful for KiCad 6 when printing in one page, you can disable the edge here.
# KiCad 5 forces it by default, and you can't control it from config files.
# Same for KiCad 6 when printing to separated pages
force_edge_cuts: true
# [boolean=false] Hide components in the Fab layer that are marked as excluded by a variant
hide_excluded: false
# [boolean=false] Print mirrored (X axis inverted). ONLY for KiCad 6
mirror: false
# [boolean=false] Print in black and white
monochrome: false
# [string='%f-%i%I%v.%x'] Filename for the output SVG (%i=layers, %x=svg). Affected by global options
output: '%f-%i%I%v.%x'
# `output_name` is an alias for `output`
# [boolean=true] Include the title-block
plot_sheet_reference: true
# [number=1.0] Scale factor (0 means autoscaling)
scaling: 1.0
# [boolean=false] Print layers in separated pages
separated: false
# [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
# If it starts with `+` the text is concatenated
title: ''
# [string=''] Board variant to apply
variant: ''
layers: all
# SVG Schematic Print: # SVG Schematic Print:
# This is a format to document your schematic. # This is a format to document your schematic.
- name: 'svg_sch_print_example' - name: 'svg_sch_print_example'

145
kibot/out_any_pcb_print.py Normal file
View File

@ -0,0 +1,145 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
import os
from shutil import copy2, rmtree
from tempfile import mkdtemp
from .pre_base import BasePreFlight
from .error import KiPlotConfigurationError
from .gs import GS
from .kiplot import check_script, exec_with_retry, add_extra_options
from .misc import CMD_PCBNEW_PRINT_LAYERS, URL_PCBNEW_PRINT_LAYERS, PDF_PCB_PRINT
from .out_base import VariantOptions
from .macros import macros, document, output_class # noqa: F401
from .layer import Layer
from . import log
logger = log.get_logger()
class Any_PCB_PrintOptions(VariantOptions):
# Mappings to KiCad config values. They should be the same used in drill_marks.py
_drill_marks_map = {'none': 0, 'small': 1, 'full': 2}
def __init__(self):
with document:
self.output_name = None
""" {output} """
self.scaling = 1.0
""" Scale factor (0 means autoscaling)"""
self._drill_marks = 'full'
""" What to use to indicate the drill places, can be none, small or full (for real scale) """
self.plot_sheet_reference = True
""" Include the title-block """
self.monochrome = False
""" Print in black and white """
self.separated = False
""" Print layers in separated pages """
self.mirror = False
""" Print mirrored (X axis inverted). ONLY for KiCad 6 """
self.hide_excluded = False
""" Hide components in the Fab layer that are marked as excluded by a variant """
self.title = ''
""" Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated """
self.force_edge_cuts = True
""" Only useful for KiCad 6 when printing in one page, you can disable the edge here.
KiCad 5 forces it by default, and you can't control it from config files.
Same for KiCad 6 when printing to separated pages """
super().__init__()
@property
def drill_marks(self):
return self._drill_marks
@drill_marks.setter
def drill_marks(self, val):
if val not in self._drill_marks_map:
raise KiPlotConfigurationError("Unknown drill mark type: {}".format(val))
self._drill_marks = val
def config(self, parent):
super().config(parent)
self._drill_marks = Any_PCB_PrintOptions._drill_marks_map[self._drill_marks]
@staticmethod
def _copy_project(fname):
pro_name = GS.pcb_file.replace('.kicad_pcb', GS.pro_ext)
if not os.path.isfile(pro_name):
return None
pro_copy = fname.replace('.kicad_pcb', GS.pro_ext)
logger.debug('Copying project `{}` to `{}`'.format(pro_name, pro_copy))
copy2(pro_name, pro_copy)
return pro_copy
def filter_components(self, board, force_copy):
if not self._comps and not force_copy:
return GS.pcb_file, None
comps_hash = self.get_refs_hash()
self.cross_modules(board, comps_hash)
self.remove_paste_and_glue(board, comps_hash)
if self.hide_excluded:
self.remove_fab(board, comps_hash)
# Save the PCB to a temporal dir
pcb_dir = mkdtemp(prefix='tmp-kibot-pdf_pcb_print-')
fname = os.path.join(pcb_dir, GS.pcb_basename+'.kicad_pcb')
logger.debug('Storing filtered PCB to `{}`'.format(fname))
GS.board.Save(fname)
# Copy the project: avoids warnings, could carry some options
self._copy_project(fname)
self.uncross_modules(board, comps_hash)
self.restore_paste_and_glue(board, comps_hash)
if self.hide_excluded:
self.restore_fab(board, comps_hash)
return fname, pcb_dir
def get_targets(self, out_dir):
return [self._parent.expand_filename(out_dir, self.output)]
def run(self, output, svg=False):
super().run(self._layers)
check_script(CMD_PCBNEW_PRINT_LAYERS, URL_PCBNEW_PRINT_LAYERS, '1.6.4' if svg else '1.5.10')
# Output file name
cmd = [CMD_PCBNEW_PRINT_LAYERS, 'export', '--output_name', output]
if BasePreFlight.get_option('check_zone_fills'):
cmd.append('-f')
cmd.extend(['--scaling', str(self.scaling), '--pads', str(self._drill_marks)])
if not self.plot_sheet_reference:
cmd.append('--no-title')
if self.monochrome:
cmd.append('--monochrome')
if self.separated:
cmd.append('--separate')
if self.mirror:
cmd.append('--mirror')
if svg:
cmd.append('--svg')
self.set_title(self.title)
board_name, board_dir = self.filter_components(GS.board, self.title != '')
cmd.extend([board_name, os.path.dirname(output)])
cmd, video_remove = add_extra_options(cmd)
# Add the layers
cmd.extend([la.layer for la in self._layers])
if GS.ki6() and self.force_edge_cuts and not self.separated:
cmd.append('Edge.Cuts')
# Execute it
ret = exec_with_retry(cmd)
self.restore_title()
# Remove the temporal PCB
if board_dir:
logger.debug('Removing temporal variant dir `{}`'.format(board_dir))
rmtree(board_dir)
if ret:
logger.error(CMD_PCBNEW_PRINT_LAYERS+' returned %d', ret)
exit(PDF_PCB_PRINT)
if video_remove:
video_name = os.path.join(self.expand_filename_pcb(GS.out_dir), 'pcbnew_export_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
def set_layers(self, layers):
layers = Layer.solve(layers)
self._layers = layers
self._expand_id = '+'.join([la.suffix for la in layers])

View File

@ -1,17 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2020-2021 Salvador E. Tropea # Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial # Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0 # License: GPL-3.0
# Project: KiBot (formerly KiPlot) # Project: KiBot (formerly KiPlot)
import os from .gs import GS
from shutil import copy2, rmtree from .out_any_pcb_print import Any_PCB_PrintOptions
from tempfile import mkdtemp from .error import KiPlotConfigurationError
from .pre_base import BasePreFlight
from .error import (KiPlotConfigurationError)
from .gs import (GS)
from .kiplot import check_script, exec_with_retry, add_extra_options
from .misc import (CMD_PCBNEW_PRINT_LAYERS, URL_PCBNEW_PRINT_LAYERS, PDF_PCB_PRINT)
from .out_base import VariantOptions
from .macros import macros, document, output_class # noqa: F401 from .macros import macros, document, output_class # noqa: F401
from .layer import Layer from .layer import Layer
from . import log from . import log
@ -19,135 +13,17 @@ from . import log
logger = log.get_logger() logger = log.get_logger()
class PDF_Pcb_PrintOptions(VariantOptions): class PDF_PCB_PrintOptions(Any_PCB_PrintOptions):
# Mappings to KiCad config values. They should be the same used in drill_marks.py
_drill_marks_map = {'none': 0, 'small': 1, 'full': 2}
def __init__(self): def __init__(self):
with document: with document:
self.output = GS.def_global_output self.output = GS.def_global_output
""" Filename for the output PDF (%i=layers, %x=pdf)""" """ Filename for the output PDF (%i=layers, %x=pdf)"""
self.output_name = None
""" {output} """
self.scaling = 1.0
""" Scale factor (0 means autoscaling)"""
self._drill_marks = 'full'
""" What to use to indicate the drill places, can be none, small or full (for real scale) """
self.plot_sheet_reference = True
""" Include the title-block """
self.monochrome = False
""" Print in black and white """
self.separated = False
""" Print layers in separated pages """
self.mirror = False
""" Print mirrored (X axis inverted). ONLY for KiCad 6 """
self.hide_excluded = False
""" Hide components in the Fab layer that are marked as excluded by a variant """
self.title = ''
""" Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated """
self.force_edge_cuts = True
""" Only useful for KiCad 6 when printing in one page, you can disable the edge here.
KiCad 5 forces it by default, and you can't control it from config files.
Same for KiCad 6 when printing to separated pages """
super().__init__() super().__init__()
self._expand_ext = 'pdf' self._expand_ext = 'pdf'
@property
def drill_marks(self):
return self._drill_marks
@drill_marks.setter
def drill_marks(self, val):
if val not in self._drill_marks_map:
raise KiPlotConfigurationError("Unknown drill mark type: {}".format(val))
self._drill_marks = val
def config(self, parent):
super().config(parent)
self._drill_marks = PDF_Pcb_PrintOptions._drill_marks_map[self._drill_marks]
@staticmethod
def _copy_project(fname):
pro_name = GS.pcb_file.replace('.kicad_pcb', GS.pro_ext)
if not os.path.isfile(pro_name):
return None
pro_copy = fname.replace('.kicad_pcb', GS.pro_ext)
logger.debug('Copying project `{}` to `{}`'.format(pro_name, pro_copy))
copy2(pro_name, pro_copy)
return pro_copy
def filter_components(self, board, force_copy):
if not self._comps and not force_copy:
return GS.pcb_file, None
comps_hash = self.get_refs_hash()
self.cross_modules(board, comps_hash)
self.remove_paste_and_glue(board, comps_hash)
if self.hide_excluded:
self.remove_fab(board, comps_hash)
# Save the PCB to a temporal dir
pcb_dir = mkdtemp(prefix='tmp-kibot-pdf_pcb_print-')
fname = os.path.join(pcb_dir, GS.pcb_basename+'.kicad_pcb')
logger.debug('Storing filtered PCB to `{}`'.format(fname))
GS.board.Save(fname)
# Copy the project: avoids warnings, could carry some options
self._copy_project(fname)
self.uncross_modules(board, comps_hash)
self.restore_paste_and_glue(board, comps_hash)
if self.hide_excluded:
self.restore_fab(board, comps_hash)
return fname, pcb_dir
def get_targets(self, out_dir):
return [self._parent.expand_filename(out_dir, self.output)]
def run(self, output):
super().run(self._layers)
check_script(CMD_PCBNEW_PRINT_LAYERS, URL_PCBNEW_PRINT_LAYERS, '1.5.10')
# Output file name
cmd = [CMD_PCBNEW_PRINT_LAYERS, 'export', '--output_name', output]
if BasePreFlight.get_option('check_zone_fills'):
cmd.append('-f')
cmd.extend(['--scaling', str(self.scaling), '--pads', str(self._drill_marks)])
if not self.plot_sheet_reference:
cmd.append('--no-title')
if self.monochrome:
cmd.append('--monochrome')
if self.separated:
cmd.append('--separate')
if self.mirror:
cmd.append('--mirror')
self.set_title(self.title)
board_name, board_dir = self.filter_components(GS.board, self.title != '')
cmd.extend([board_name, os.path.dirname(output)])
cmd, video_remove = add_extra_options(cmd)
# Add the layers
cmd.extend([la.layer for la in self._layers])
if GS.ki6() and self.force_edge_cuts and not self.separated:
cmd.append('Edge.Cuts')
# Execute it
ret = exec_with_retry(cmd)
self.restore_title()
# Remove the temporal PCB
if board_dir:
logger.debug('Removing temporal variant dir `{}`'.format(board_dir))
rmtree(board_dir)
if ret:
logger.error(CMD_PCBNEW_PRINT_LAYERS+' returned %d', ret)
exit(PDF_PCB_PRINT)
if video_remove:
video_name = os.path.join(self.expand_filename_pcb(GS.out_dir), 'pcbnew_export_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
def set_layers(self, layers):
layers = Layer.solve(layers)
self._layers = layers
self._expand_id = '+'.join([la.suffix for la in layers])
@output_class @output_class
class PDF_Pcb_Print(BaseOutput): # noqa: F821 class PDF_PCB_Print(BaseOutput): # noqa: F821
""" PDF PCB Print (Portable Document Format) """ PDF PCB Print (Portable Document Format)
Exports the PCB to the most common exchange format. Suitable for printing. Exports the PCB to the most common exchange format. Suitable for printing.
This is the main format to document your PCB. This is the main format to document your PCB.
@ -155,7 +31,7 @@ class PDF_Pcb_Print(BaseOutput): # noqa: F821
def __init__(self): def __init__(self):
super().__init__() super().__init__()
with document: with document:
self.options = PDF_Pcb_PrintOptions self.options = PDF_PCB_PrintOptions
""" [dict] Options for the `pdf_pcb_print` output """ """ [dict] Options for the `pdf_pcb_print` output """
self.layers = Layer self.layers = Layer
""" [list(dict)|list(string)|string] [all,selected,copper,technical,user] """ [list(dict)|list(string)|string] [all,selected,copper,technical,user]

View File

@ -246,21 +246,29 @@ class ReportOptions(BaseOptions):
text += self.do_replacements(line, context) text += self.do_replacements(line, context)
return text return text
def context_layer_pdfs(self, line): def _context_images(self, line, images):
""" Replace iterator for the `layer_pdfs` context """ """ Replace iterator for the various contexts that expands images """
text = '' text = ''
for s in self._layer_pdfs: for s in images:
context = {'path': s[0], 'comment': s[1], 'new_line': '\n'} context = {'path': s[0], 'comment': s[1], 'new_line': '\n'}
text += self.do_replacements(line, context) text += self.do_replacements(line, context)
return text return text
def context_layer_pdfs(self, line):
""" Replace iterator for the `layer_pdfs` context """
return self._context_images(line, self._layer_pdfs)
def context_layer_svgs(self, line):
""" Replace iterator for the `layer_svgs` context """
return self._context_images(line, self._layer_svgs)
def context_schematic_pdfs(self, line): def context_schematic_pdfs(self, line):
""" Replace iterator for the `schematic_pdfs` context """ """ Replace iterator for the `schematic_pdfs` context """
text = '' return self._context_images(line, self._schematic_pdfs)
for s in self._schematic_pdfs:
context = {'path': s[0], 'comment': s[1], 'new_line': '\n'} def context_schematic_svgs(self, line):
text += self.do_replacements(line, context) """ Replace iterator for the `schematic_svgs` context """
return text return self._context_images(line, self._schematic_svgs)
@staticmethod @staticmethod
def is_pure_smd_5(m): def is_pure_smd_5(m):
@ -550,24 +558,32 @@ class ReportOptions(BaseOptions):
self._stackup = GS.stackup if GS.stackup else [] self._stackup = GS.stackup if GS.stackup else []
self.collect_data(GS.board) self.collect_data(GS.board)
base_dir = os.path.dirname(fname) base_dir = os.path.dirname(fname)
# Collect the PCB layers and schematic prints
self._layer_pdfs = [] self._layer_pdfs = []
self._layer_svgs = []
self._schematic_pdfs = [] self._schematic_pdfs = []
self._schematic_svgs = []
for o in RegOutput.get_outputs(): for o in RegOutput.get_outputs():
dest = None
if o.type == 'pdf_pcb_print': if o.type == 'pdf_pcb_print':
if not o._configured: dest = self._layer_pdfs
config_output(o) elif o.type == 'svg_pcb_print':
out_file = o.get_targets(o.expand_dirname(os.path.join(GS.out_dir, o.dir)))[0] dest = self._layer_svgs
rel_path = os.path.relpath(out_file, base_dir)
self._layer_pdfs.append((rel_path, o.comment))
elif o.type == 'pdf_sch_print': elif o.type == 'pdf_sch_print':
dest = self._schematic_pdfs
elif o.type == 'svg_sch_print':
dest = self._schematic_svgs
if dest is not None:
if not o._configured: if not o._configured:
config_output(o) config_output(o)
out_files = o.get_targets(o.expand_dirname(os.path.join(GS.out_dir, o.dir))) out_files = o.get_targets(o.expand_dirname(os.path.join(GS.out_dir, o.dir)))
for of in out_files: for of in out_files:
rel_path = os.path.relpath(of, base_dir) rel_path = os.path.relpath(of, base_dir)
self._schematic_pdfs.append((rel_path, o.comment)) dest.append((rel_path, o.comment))
self.layer_pdfs = len(self._layer_pdfs) > 0 self.layer_pdfs = len(self._layer_pdfs) > 0
self.layer_svgs = len(self._layer_svgs) > 0
self.schematic_pdfs = len(self._schematic_pdfs) > 0 self.schematic_pdfs = len(self._schematic_pdfs) > 0
self.schematic_svgs = len(self._schematic_svgs) > 0
self.do_template(self.template, fname) self.do_template(self.template, fname)

View File

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
import os
import re
from .gs import GS
from .out_any_pcb_print import Any_PCB_PrintOptions
from .error import KiPlotConfigurationError
from .macros import macros, document, output_class # noqa: F401
from .layer import Layer
from . import log
logger = log.get_logger()
class SVG_PCB_PrintOptions(Any_PCB_PrintOptions):
def __init__(self):
with document:
self.output = GS.def_global_output
""" Filename for the output SVG (%i=layers, %x=svg)"""
self.enable_ki6_page_fix = True
""" Enable workaround for KiCad 6 bug #11033 """
super().__init__()
self._expand_ext = 'svg'
def run(self, output):
super().run(output, svg=True)
if GS.ki6() and self.enable_ki6_page_fix:
# KiCad 6.0.2 bug: https://gitlab.com/kicad/code/kicad/-/issues/11033
o = self._parent
out_files = o.get_targets(o.expand_dirname(os.path.join(GS.out_dir, o.dir)))
for file in out_files:
logger.debug('Patching SVG file `{}`'.format(file))
with open(file, 'rt') as f:
text = f.read()
text = re.sub(r'<svg (.*) width="(.*)" height="(.*)" viewBox="(\S+) (\S+) (\S+) (\S+)"',
r'<svg \1 width="\3" height="\2" viewBox="\4 \5 \7 \6"', text)
text = re.sub(r'<rect x="(\S+)" y="(\S+)" width="(\S+)" height="(\S+)"',
r'<rect x="\1" y="\2" width="\4" height="\3"', text)
with open(file, 'wt') as f:
f.write(text)
@output_class
class SVG_PCB_Print(BaseOutput): # noqa: F821
""" SVG PCB Print (Scalable Vector Graphics)
Exports the PCB to the scalable vector graphics format.
This output is what you get from the 'File/Print' menu in pcbnew. """
def __init__(self):
super().__init__()
with document:
self.options = SVG_PCB_PrintOptions
""" [dict] Options for the `pdf_pcb_print` output """
self.layers = Layer
""" [list(dict)|list(string)|string] [all,selected,copper,technical,user]
List of PCB layers to include in the PDF """
def config(self, parent):
super().config(parent)
# We need layers
if isinstance(self.layers, type):
raise KiPlotConfigurationError("Missing `layers` list")
self.options.set_layers(self.layers)

View File

@ -98,17 +98,17 @@ Holes (excluding vias):
#hole_sizes_no_vias:- ${drill_mm} mm (${drill_mils} mils) (${count}) #hole_sizes_no_vias:- ${drill_mm} mm (${drill_mils} mils) (${count})
#?schematic_pdfs #?schematic_svgs
# Schematic # Schematic
#?schematic_pdfs #?schematic_svgs
#?schematic_pdfs #?schematic_svgs
#schematic_pdfs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line} #schematic_svgs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}
#?layer_pdfs #?layer_svgs
# PCB Layers # PCB Layers
#?layer_pdfs #?layer_svgs
#?layer_pdfs #?layer_svgs
#layer_pdfs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line} #layer_svgs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}

View File

@ -86,13 +86,13 @@ Holes (excluding vias):
# Schematic # Schematic
![Schematic](Schematic.pdf){ width=16.5cm height=11.7cm } ![Schematic](Schematic.svg){ width=16.5cm height=11.7cm }
# PCB Layers # PCB Layers
![Top copper and silkscreen](Layers/light_control-F_Cu+F_SilkS.pdf){ width=16.5cm height=11.7cm } ![Top copper and silkscreen](Layers/light_control-F_Cu+F_SilkS.svg){ width=16.5cm height=11.7cm }
![Bottom copper and silkscreen](Layers/light_control-B_Cu+B_SilkS.pdf){ width=16.5cm height=11.7cm } ![Bottom copper and silkscreen](Layers/light_control-B_Cu+B_SilkS.svg){ width=16.5cm height=11.7cm }

View File

@ -109,13 +109,13 @@ Holes (excluding vias):
# Schematic # Schematic
![Schematic](Schematic.pdf){ width=16.5cm height=11.7cm } ![Schematic](Schematic.svg){ width=16.5cm height=11.7cm }
# PCB Layers # PCB Layers
![Top copper and silkscreen](Layers/light_control-F_Cu+F_SilkS.pdf){ width=16.5cm height=11.7cm } ![Top copper and silkscreen](Layers/light_control-F_Cu+F_SilkS.svg){ width=16.5cm height=11.7cm }
![Bottom copper and silkscreen](Layers/light_control-B_Cu+B_SilkS.pdf){ width=16.5cm height=11.7cm } ![Bottom copper and silkscreen](Layers/light_control-B_Cu+B_SilkS.svg){ width=16.5cm height=11.7cm }

View File

@ -22,7 +22,7 @@ outputs:
- name: 'print_front' - name: 'print_front'
comment: "Top copper and silkscreen" comment: "Top copper and silkscreen"
type: pdf_pcb_print type: svg_pcb_print
dir: Layers dir: Layers
options: options:
title: 'Fake title for front copper and silk' title: 'Fake title for front copper and silk'
@ -32,7 +32,7 @@ outputs:
- name: 'print_bottom' - name: 'print_bottom'
comment: "Bottom copper and silkscreen" comment: "Bottom copper and silkscreen"
type: pdf_pcb_print type: svg_pcb_print
dir: Layers dir: Layers
options: options:
title: 'Fake title for bottom copper and silk' title: 'Fake title for bottom copper and silk'
@ -46,3 +46,10 @@ outputs:
dir: . dir: .
options: options:
output: Schematic.pdf output: Schematic.pdf
- name: 'print_sch_svg'
comment: "Schematic"
type: svg_sch_print
dir: .
options:
output: Schematic.svg