KiBot/kiplot/out_any_layer.py

155 lines
6.1 KiB
Python

import os
from pcbnew import (GERBER_JOBFILE_WRITER, PCB_PLOT_PARAMS, FromMM, PLOT_CONTROLLER, IsCopperLayer, SKETCH)
from .out_base import (BaseOutput)
from .error import (PlotError, KiPlotConfigurationError)
from .kiplot import (GS)
from kiplot.macros import macros, document # noqa: F401
from . import log
logger = log.get_logger(__name__)
AUTO_SCALE = 0
class AnyLayer(BaseOutput):
def __init__(self, name, type, description):
super(AnyLayer, self).__init__(name, type, description)
# Options
with document:
self.exclude_edge_layer = True
""" do not include the PCB edge layer """
self.exclude_pads_from_silkscreen = False
""" do not plot the component pads in the silk screen """
self.plot_sheet_reference = False
""" currently without effect """
self.plot_footprint_refs = True
""" include the footprint references """
self.plot_footprint_values = True
""" include the footprint values """
self.force_plot_invisible_refs_vals = False
""" include references and values even when they are marked as invisible """
self.tent_vias = True
""" cover the vias """ # pragma: no cover
# Mappings to KiCad values
self._drill_marks_map = {
'none': PCB_PLOT_PARAMS.NO_DRILL_SHAPE,
'small': PCB_PLOT_PARAMS.SMALL_DRILL_SHAPE,
'full': PCB_PLOT_PARAMS.FULL_DRILL_SHAPE,
}
def config(self, outdir, options, layers):
super().config(outdir, options, layers)
# We need layers
if not self._layers:
raise KiPlotConfigurationError("Missing `layers` list")
def _configure_plot_ctrl(self, po, output_dir):
logger.debug("Configuring plot controller for output")
po.SetOutputDirectory(output_dir)
po.SetLineWidth(FromMM(self.get_line_width()))
# Scaling/Autoscale
scaling = self.get_scaling()
if scaling == AUTO_SCALE:
po.SetAutoScale(True)
po.SetScale(1)
else:
po.SetAutoScale(False)
po.SetScale(scaling)
po.SetMirror(self.get_mirror_plot())
po.SetNegative(self.get_negative_plot())
po.SetPlotFrameRef(self.plot_sheet_reference)
po.SetPlotReference(self.plot_footprint_refs)
po.SetPlotValue(self.plot_footprint_values)
po.SetPlotInvisibleText(self.force_plot_invisible_refs_vals)
po.SetExcludeEdgeLayer(self.exclude_edge_layer)
po.SetPlotPadsOnSilkLayer(not self.exclude_pads_from_silkscreen)
po.SetUseAuxOrigin(self.get_use_aux_axis_as_origin())
po.SetPlotViaOnMaskLayer(not self.tent_vias)
# in general, false, but gerber will set it back later
po.SetUseGerberAttributes(False)
# Only useful for gerber outputs
po.SetCreateGerberJobFile(False)
# How we draw drill marks
po.SetDrillMarksType(self.get_drill_marks())
# We'll come back to this on a per-layer basis
po.SetSkipPlotNPTH_Pads(False)
if self.get_sketch_plot():
po.SetPlotMode(SKETCH)
def get_plot_format(self):
return self._plot_format
def run(self, output_dir, board):
# fresh plot controller
plot_ctrl = PLOT_CONTROLLER(board)
# set up plot options for the whole output
po = plot_ctrl.GetPlotOptions()
self._configure_plot_ctrl(po, output_dir)
layer_cnt = board.GetCopperLayerCount()
# Gerber Job files aren't automagically created
# We need to assist KiCad
create_job = po.GetCreateGerberJobFile()
if create_job:
jobfile_writer = GERBER_JOBFILE_WRITER(board)
plot_ctrl.SetColorMode(True)
# plot every layer in the output
for l in self._layers:
suffix = l.suffix
desc = l.desc
id = l.get_layer_id_from_name(layer_cnt)
# Set current layer
plot_ctrl.SetLayer(id)
# Skipping NPTH is controlled by whether or not this is
# a copper layer
is_cu = IsCopperLayer(id)
po.SetSkipPlotNPTH_Pads(is_cu)
plot_format = self.get_plot_format()
# Plot single layer to file
logger.debug("Opening plot file for layer `{}` format `{}`".format(l, plot_format))
if not plot_ctrl.OpenPlotfile(suffix, plot_format, desc):
raise PlotError("OpenPlotfile failed!")
logger.debug("Plotting layer `{}` to `{}`".format(l, plot_ctrl.GetPlotFileName()))
plot_ctrl.PlotLayer()
plot_ctrl.ClosePlot()
if create_job:
jobfile_writer.AddGbrFile(id, os.path.basename(plot_ctrl.GetPlotFileName()))
if create_job:
base_fn = os.path.join(
os.path.dirname(plot_ctrl.GetPlotFileName()),
os.path.basename(GS.pcb_file))
base_fn = os.path.splitext(base_fn)[0]
job_fn = base_fn+'-job.gbrjob'
jobfile_writer.CreateJobFile(job_fn)
# Default values
# We concentrate all the KiCad plot initialization in one place.
# Here we provide default values for settings not contained in an output object
# TODO: avoid them?
def get_line_width(self):
return self.line_width if 'line_width' in self.__dict__ else 0
def get_scaling(self):
return self.scaling if 'scaling' in self.__dict__ else 1
def get_mirror_plot(self):
return self.mirror_plot if 'mirror_plot' in self.__dict__ else False
def get_negative_plot(self):
return self.negative_plot if 'negative_plot' in self.__dict__ else False
def get_use_aux_axis_as_origin(self):
return self.use_aux_axis_as_origin if 'use_aux_axis_as_origin' in self.__dict__ else False
def get_drill_marks(self):
return self.drill_marks if '_drill_marks' in self.__dict__ else PCB_PLOT_PARAMS.NO_DRILL_SHAPE
def get_sketch_plot(self):
return self.sketch_plot if 'sketch_plot' in self.__dict__ else False