Varius `pcb_print` details
- Added option `force_edge_cuts` so we get them on all pages. - Now `layers` can be a list of strings, or just an string. - Added default scaling for all pages. - Fixed: tracks removed after plotting another Cu layer. - Fixed: custom pads plotted as special vias. - Fixed: frame reference plotted mirrored on mirrored pages.
This commit is contained in:
parent
b6404cf940
commit
5c9dbc4072
|
|
@ -1547,6 +1547,7 @@ Next time you need this list just use an alias, like this:
|
|||
- `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).
|
||||
- `force_edge_cuts`: [boolean=false] Add the `Edge.Cuts` to all the pages.
|
||||
- `format`: [string='PDF'] [PDF,SVG,PNG,EPS,PS] Format for the output file/s.
|
||||
Note that for PS you need `ghostscript` which isn't part of the default docker images.
|
||||
- `frame_plot_mechanism`: [string='internal'] [gui,internal,plot] Plotting the frame from Python is problematic.
|
||||
|
|
@ -1569,7 +1570,7 @@ Next time you need this list just use an alias, like this:
|
|||
- `colored_holes`: [boolean=true] Change the drill holes to be colored instead of white.
|
||||
- `exclude_pads_from_silkscreen`: [boolean=false] Do not plot the component pads in the silk screen (KiCad 5.x only).
|
||||
- `holes_color`: [string='#000000'] Color used for the holes when `colored_holes` is enabled.
|
||||
- `layers`: [list(dict)] List of layers printed in this page. Order is important, the last goes on top.
|
||||
- `layers`: [list(dict)|list(string)|string] List of layers printed in this page. Order is important, the last goes on top.
|
||||
* Valid keys:
|
||||
- `color`: [string=''] Color used for this layer.
|
||||
- `description`: [string=''] A description for the layer, for documentation purposes.
|
||||
|
|
@ -1591,6 +1592,7 @@ Next time you need this list just use an alias, like this:
|
|||
If it starts with `+` the text is concatenated.
|
||||
- `plot_sheet_reference`: [boolean=true] Include the title-block (worksheet, frame, etc.).
|
||||
- `png_width`: [number=1280] Width of the PNG in pixels.
|
||||
- `scaling`: [number=1.0] Default scale factor (0 means autoscaling).
|
||||
- `sheet_reference_layout`: [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
|
||||
- `title`: [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
|
||||
If it starts with `+` the text is concatenated.
|
||||
|
|
|
|||
|
|
@ -978,6 +978,8 @@ outputs:
|
|||
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=false] Add the `Edge.Cuts` to all the pages
|
||||
force_edge_cuts: false
|
||||
# [string='PDF'] [PDF,SVG,PNG,EPS,PS] Format for the output file/s.
|
||||
# Note that for PS you need `ghostscript` which isn't part of the default docker images
|
||||
format: 'PDF'
|
||||
|
|
@ -1010,7 +1012,7 @@ outputs:
|
|||
exclude_pads_from_silkscreen: false
|
||||
# [string='#000000'] Color used for the holes when `colored_holes` is enabled
|
||||
holes_color: '#000000'
|
||||
# [list(dict)] List of layers printed in this page. Order is important, the last goes on top
|
||||
# [list(dict)|list(string)|string] List of layers printed in this page. Order is important, the last goes on top
|
||||
layers:
|
||||
# [string=''] Color used for this layer
|
||||
- color: ''
|
||||
|
|
@ -1051,6 +1053,8 @@ outputs:
|
|||
plot_sheet_reference: true
|
||||
# [number=1280] Width of the PNG in pixels
|
||||
png_width: 1280
|
||||
# [number=1.0] Default scale factor (0 means autoscaling)
|
||||
scaling: 1.0
|
||||
# [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project
|
||||
sheet_reference_layout: ''
|
||||
# [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
|
||||
|
|
|
|||
|
|
@ -168,8 +168,8 @@ class Layer(Optionable):
|
|||
self._protel_extension = 'gbr'
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
def solve(values):
|
||||
@classmethod
|
||||
def solve(cls, values):
|
||||
board = GS.board
|
||||
layer_cnt = 2
|
||||
if board:
|
||||
|
|
@ -213,12 +213,12 @@ class Layer(Optionable):
|
|||
elif layer == 'user':
|
||||
ext = Layer._get_layers(Layer._get_user())
|
||||
elif layer in Layer._pcb_layers:
|
||||
ext = [Layer.create_layer(layer)]
|
||||
ext = [cls.create_layer(layer)]
|
||||
# Give compatibility for the KiCad 5 default names (automagically renamed by KiCad 6)
|
||||
elif GS.ki6() and layer in Layer.KICAD6_RENAME:
|
||||
ext = [Layer.create_layer(Layer.KICAD6_RENAME[layer])]
|
||||
ext = [cls.create_layer(Layer.KICAD6_RENAME[layer])]
|
||||
elif layer in Layer.DEFAULT_LAYER_NAMES:
|
||||
ext = [Layer.create_layer(layer)]
|
||||
ext = [cls.create_layer(layer)]
|
||||
if ext is None:
|
||||
raise KiPlotConfigurationError("Unknown layer spec: `{}`".format(layer))
|
||||
new_vals.extend(ext)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
import re
|
||||
import os
|
||||
import subprocess
|
||||
from pcbnew import PLOT_CONTROLLER, FromMM, PLOT_FORMAT_SVG, F_Cu, B_Cu, wxSize, IsCopperLayer
|
||||
from pcbnew import B_Cu, F_Cu, FromMM, IsCopperLayer, PLOT_CONTROLLER, PLOT_FORMAT_SVG, wxSize
|
||||
from shutil import rmtree, which
|
||||
from tempfile import NamedTemporaryFile, mkdtemp
|
||||
from .svgutils.transform import fromstring
|
||||
|
|
@ -207,8 +207,8 @@ class PagesOptions(Optionable):
|
|||
""" Print mirrored (X axis inverted) """
|
||||
self.monochrome = False
|
||||
""" Print in gray scale """
|
||||
self.scaling = 1.0
|
||||
""" Scale factor (0 means autoscaling)"""
|
||||
self.scaling = None
|
||||
""" [number=1.0] Scale factor (0 means autoscaling)"""
|
||||
self.title = ''
|
||||
""" Text used to replace the sheet title. %VALUE expansions are allowed.
|
||||
If it starts with `+` the text is concatenated """
|
||||
|
|
@ -231,20 +231,25 @@ class PagesOptions(Optionable):
|
|||
self.sort_layers = False
|
||||
""" Try to sort the layers in the same order that uses KiCad for printing """
|
||||
self.layers = LayerOptions
|
||||
""" [list(dict)] List of layers printed in this page. Order is important, the last goes on top """
|
||||
""" [list(dict)|list(string)|string] List of layers printed in this page.
|
||||
Order is important, the last goes on top """
|
||||
self._scaling_example = 1.0
|
||||
|
||||
def config(self, parent):
|
||||
super().config(parent)
|
||||
if isinstance(self.layers, type):
|
||||
raise KiPlotConfigurationError("Missing `layers` list")
|
||||
# Fill the ID member for all the layers
|
||||
self.layers = Layer.solve(self.layers)
|
||||
self.layers = LayerOptions.solve(self.layers)
|
||||
if self.sort_layers:
|
||||
self.layers.sort(key=lambda x: get_priority(x._id), reverse=True)
|
||||
if self.sheet_reference_color:
|
||||
self.validate_color('sheet_reference_color')
|
||||
if self.holes_color:
|
||||
self.validate_color('holes_color')
|
||||
if self.scaling is None:
|
||||
logger.error('Scale from parent')
|
||||
self.scaling = parent.scaling
|
||||
|
||||
|
||||
class PCB_PrintOptions(VariantOptions):
|
||||
|
|
@ -307,6 +312,10 @@ class PCB_PrintOptions(VariantOptions):
|
|||
""" Color used for blind/buried `colored_vias` """
|
||||
self.keep_temporal_files = False
|
||||
""" Store the temporal page and layer files in the output dir and don't delete them """
|
||||
self.force_edge_cuts = False
|
||||
""" Add the `Edge.Cuts` to all the pages """
|
||||
self.scaling = 1.0
|
||||
""" Default scale factor (0 means autoscaling)"""
|
||||
super().__init__()
|
||||
self._expand_id = 'assembly'
|
||||
|
||||
|
|
@ -496,9 +505,9 @@ class PCB_PrintOptions(VariantOptions):
|
|||
# Make invisible anything but through-hole pads
|
||||
tmp_layer = GS.board.GetLayerID(GS.work_layer)
|
||||
moved = []
|
||||
resized = []
|
||||
removed = []
|
||||
vias = []
|
||||
size_0 = wxSize(0, 0)
|
||||
wxSize(0, 0)
|
||||
for m in GS.get_modules():
|
||||
for gi in m.GraphicalItems():
|
||||
if gi.GetLayer() == id:
|
||||
|
|
@ -508,9 +517,10 @@ class PCB_PrintOptions(VariantOptions):
|
|||
dr = pad.GetDrillSize()
|
||||
if dr.x:
|
||||
continue
|
||||
size = pad.GetSize()
|
||||
resized.append((pad, wxSize(size.x, size.y)))
|
||||
pad.SetSize(size_0)
|
||||
layers = pad.GetLayerSet()
|
||||
layers.removeLayer(id)
|
||||
pad.SetLayerSet(layers)
|
||||
removed.append(pad)
|
||||
for e in GS.board.GetDrawings():
|
||||
if e.GetLayer() == id:
|
||||
e.SetLayer(tmp_layer)
|
||||
|
|
@ -525,7 +535,7 @@ class PCB_PrintOptions(VariantOptions):
|
|||
vias.append((e, e.GetDrill(), e.GetWidth()))
|
||||
e.SetDrill(0)
|
||||
e.SetWidth(0)
|
||||
else:
|
||||
elif e.GetLayer() == id:
|
||||
e.SetLayer(tmp_layer)
|
||||
moved.append(e)
|
||||
# Plot the layer
|
||||
|
|
@ -536,8 +546,10 @@ class PCB_PrintOptions(VariantOptions):
|
|||
# Restore everything
|
||||
for e in moved:
|
||||
e.SetLayer(id)
|
||||
for (pad, size) in resized:
|
||||
pad.SetSize(size)
|
||||
for pad in removed:
|
||||
layers = pad.GetLayerSet()
|
||||
layers.addLayer(id)
|
||||
pad.SetLayerSet(layers)
|
||||
for (via, drill, width) in vias:
|
||||
via.SetDrill(drill)
|
||||
via.SetWidth(width)
|
||||
|
|
@ -550,18 +562,19 @@ class PCB_PrintOptions(VariantOptions):
|
|||
# Make invisible anything but vias
|
||||
tmp_layer = GS.board.GetLayerID(GS.work_layer)
|
||||
moved = []
|
||||
resized = []
|
||||
removed = []
|
||||
vias = []
|
||||
size_0 = wxSize(0, 0)
|
||||
wxSize(0, 0)
|
||||
for m in GS.get_modules():
|
||||
for gi in m.GraphicalItems():
|
||||
if gi.GetLayer() == id:
|
||||
gi.SetLayer(tmp_layer)
|
||||
moved.append(gi)
|
||||
for pad in m.Pads():
|
||||
size = pad.GetSize()
|
||||
resized.append((pad, wxSize(size.x, size.y)))
|
||||
pad.SetSize(size_0)
|
||||
layers = pad.GetLayerSet()
|
||||
layers.removeLayer(id)
|
||||
pad.SetLayerSet(layers)
|
||||
removed.append(pad)
|
||||
for e in GS.board.GetDrawings():
|
||||
if e.GetLayer() == id:
|
||||
e.SetLayer(tmp_layer)
|
||||
|
|
@ -595,7 +608,7 @@ class PCB_PrintOptions(VariantOptions):
|
|||
d = e.GetDrill()
|
||||
vias.append((e, d, w, top, bottom))
|
||||
e.SetWidth(0)
|
||||
else:
|
||||
elif e.GetLayer() == id:
|
||||
e.SetLayer(tmp_layer)
|
||||
moved.append(e)
|
||||
# Plot the layer
|
||||
|
|
@ -605,8 +618,10 @@ class PCB_PrintOptions(VariantOptions):
|
|||
# Restore everything
|
||||
for e in moved:
|
||||
e.SetLayer(id)
|
||||
for (pad, size) in resized:
|
||||
pad.SetSize(size)
|
||||
for pad in removed:
|
||||
layers = pad.GetLayerSet()
|
||||
layers.addLayer(id)
|
||||
pad.SetLayerSet(layers)
|
||||
for (via, drill, width, top, bottom) in vias:
|
||||
via.SetDrill(drill)
|
||||
via.SetWidth(width)
|
||||
|
|
@ -722,6 +737,16 @@ class PCB_PrintOptions(VariantOptions):
|
|||
self.paper_h = pcb.paper_h
|
||||
self.paper = pcb.paper
|
||||
|
||||
def plot_extra_cu(self, id, la, pc, p, filelist):
|
||||
""" Plot pads and vias to make them different """
|
||||
if id >= F_Cu and id <= B_Cu:
|
||||
if self.colored_pads:
|
||||
self.plot_pads(la, pc, p, filelist)
|
||||
if self.colored_vias:
|
||||
self.plot_vias(la, pc, p, filelist, VIATYPE_THROUGH, self.via_color)
|
||||
self.plot_vias(la, pc, p, filelist, VIATYPE_BLIND_BURIED, self.blind_via_color)
|
||||
self.plot_vias(la, pc, p, filelist, VIATYPE_MICROVIA, self.micro_via_color)
|
||||
|
||||
def generate_output(self, output):
|
||||
if self.format != 'SVG' and which(SVG2PDF) is None:
|
||||
logger.error('`{}` not installed. Install `librsvg2-bin` or equivalent'.format(SVG2PDF))
|
||||
|
|
@ -754,6 +779,15 @@ class PCB_PrintOptions(VariantOptions):
|
|||
po.SetExcludeEdgeLayer(True) # We plot it separately
|
||||
po.SetUseAuxOrigin(False)
|
||||
po.SetAutoScale(False)
|
||||
# Helpers for force_edge_cuts
|
||||
if self.force_edge_cuts:
|
||||
edge_layer = LayerOptions.create_layer('Edge.Cuts')
|
||||
edge_id = edge_layer._id
|
||||
layer_id2color = self._color_theme.layer_id2color
|
||||
if edge_id in layer_id2color:
|
||||
edge_layer.color = layer_id2color[edge_id]
|
||||
else:
|
||||
edge_layer.color = "#000000"
|
||||
# Generate the output
|
||||
pages = []
|
||||
for n, p in enumerate(self.pages):
|
||||
|
|
@ -774,6 +808,8 @@ class PCB_PrintOptions(VariantOptions):
|
|||
po.SetLineWidth(FromMM(p.line_width))
|
||||
po.SetPlotPadsOnSilkLayer(not p.exclude_pads_from_silkscreen)
|
||||
filelist = []
|
||||
if self.force_edge_cuts and next(filter(lambda x: x._id == edge_id, p.layers), None) is None:
|
||||
p.layers.append(edge_layer)
|
||||
for la in p.layers:
|
||||
id = la._id
|
||||
logger.debug('- Plotting layer {} ({})'.format(la.layer, id))
|
||||
|
|
@ -786,14 +822,9 @@ class PCB_PrintOptions(VariantOptions):
|
|||
pc.OpenPlotfile(la.suffix, PLOT_FORMAT_SVG, p.sheet)
|
||||
pc.PlotLayer()
|
||||
filelist.append((GS.pcb_basename+"-"+la.suffix+".svg", la.color))
|
||||
if id >= F_Cu and id <= B_Cu:
|
||||
if self.colored_pads:
|
||||
self.plot_pads(la, pc, p, filelist)
|
||||
if self.colored_vias:
|
||||
self.plot_vias(la, pc, p, filelist, VIATYPE_THROUGH, self.via_color)
|
||||
self.plot_vias(la, pc, p, filelist, VIATYPE_BLIND_BURIED, self.blind_via_color)
|
||||
self.plot_vias(la, pc, p, filelist, VIATYPE_MICROVIA, self.micro_via_color)
|
||||
self.plot_extra_cu(id, la, pc, p, filelist)
|
||||
# 2) Plot the frame using an empty layer and 1.0 scale
|
||||
po.SetMirror(False)
|
||||
if self.plot_sheet_reference:
|
||||
logger.debug('- Plotting the frame')
|
||||
if self.frame_plot_mechanism == 'gui':
|
||||
|
|
|
|||
Loading…
Reference in New Issue