From 241eca63ffce0bc634f510f6f8152e2b68e91386 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Thu, 8 Sep 2022 07:24:56 -0300 Subject: [PATCH] [PCB Print] Added option to customize the page numbers Related to #283 --- CHANGELOG.md | 1 + README.md | 5 +++- docs/samples/generic_plot.kibot.yaml | 10 +++++-- kibot/out_pcb_print.py | 34 +++++++++++++++++------ tests/test_plot/test_print_pcb.py | 4 +-- tests/yaml_samples/pcb_print_2.kibot.yaml | 4 +++ 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea11bb0f..8e6daaeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Option to control the resolution (DPI). (See #259) - Option to move the page number to the extension (page_number_as_extension) (See #283) + - Option to customize the page numbers (See #283) - Installation checker: option to show the tool paths. ### Fixed diff --git a/README.md b/README.md index 6bd847bb..483b4b46 100644 --- a/README.md +++ b/README.md @@ -2190,13 +2190,14 @@ Notes: - **`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. - **`output`**: [string='%f-%i%I%v.%x'] Filename for the output (%i=assembly, %x=pdf/ps)/(%i=assembly_page_NN, %x=svg/png/eps). - Consult the `page_number_as_extension`. Affected by global options. + Consult the `page_number_as_extension` and `page_id` options. Affected by global options. - *output_name*: Alias for output. - **`pages`**: [list(dict)] List of pages to include in the output document. Each page contains one or more layers of the PCB. * Valid keys: - **`layers`**: [list(dict)|list(string)|string] List of layers printed in this page. Order is important, the last goes on top. + You can reuse other layers lists, some options aren't used here, but they are valid. * Valid keys: - `color`: [string=''] Color used for this layer. - `description`: [string=''] A description for the layer, for documentation purposes. @@ -2214,6 +2215,7 @@ Notes: - `mirror`: [boolean=false] Print mirrored (X axis inverted). - `monochrome`: [boolean=false] Print in gray scale. - `negative_plot`: [boolean=false] Invert black and white. Only useful for a single layer. + - `page_id`: [string='%02d'] Text to differentiate the pages. Use %d (like in C) to get the page number. - `sheet`: [string='Assembly'] Text to use for the `sheet` in the title block. - `sheet_reference_color`: [string=''] Color to use for the frame and title block. - `tent_vias`: [boolean=true] Cover the vias. @@ -2246,6 +2248,7 @@ Notes: - `micro_via_color`: [string=''] Color used for micro `colored_vias`. - `pad_color`: [string=''] Color used for `colored_pads`. - `page_number_as_extension`: [boolean=false] When enabled the %i is always `assembly`, the %x will be NN.FORMAT (i.e. 01.png). + Note: page numbers can be customized using the `page_id` option for each page. - `png_width`: [number=1280] [0,7680] Width of the PNG in pixels. Use 0 to use as many pixels as the DPI needs for the page size. - `realistic_solder_mask`: [boolean=true] Try to draw the solder mask as a real solder mask, not the negative used for fabrication. In order to get a good looking select a color with transparency, i.e. '#14332440'. diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 98af0220..bef8dec8 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -1117,12 +1117,13 @@ outputs: # [string=''] Color used for micro `colored_vias` micro_via_color: '' # [string='%f-%i%I%v.%x'] Filename for the output (%i=assembly, %x=pdf/ps)/(%i=assembly_page_NN, %x=svg/png/eps). - # Consult the `page_number_as_extension`. Affected by global options + # Consult the `page_number_as_extension` and `page_id` options. Affected by global options output: '%f-%i%I%v.%x' # `output_name` is an alias for `output` # [string=''] Color used for `colored_pads` pad_color: '' - # [boolean=false] When enabled the %i is always `assembly`, the %x will be NN.FORMAT (i.e. 01.png) + # [boolean=false] When enabled the %i is always `assembly`, the %x will be NN.FORMAT (i.e. 01.png). + # Note: page numbers can be customized using the `page_id` option for each page page_number_as_extension: false # [list(dict)] List of pages to include in the output document. # Each page contains one or more layers of the PCB @@ -1134,7 +1135,8 @@ outputs: # [string='#000000'] Color used for the holes when `colored_holes` is enabled holes_color: '#000000' # [list(dict)|list(string)|string] List of layers printed in this page. - # Order is important, the last goes on top + # Order is important, the last goes on top. + # You can reuse other layers lists, some options aren't used here, but they are valid layers: # [string=''] Color used for this layer - color: '' @@ -1158,6 +1160,8 @@ outputs: monochrome: false # [boolean=false] Invert black and white. Only useful for a single layer negative_plot: false + # [string='%02d'] Text to differentiate the pages. Use %d (like in C) to get the page number + page_id: '%02d' # [number=1.0] Scale factor (0 means autoscaling) scaling: 1.0 # [string='Assembly'] Text to use for the `sheet` in the title block diff --git a/kibot/out_pcb_print.py b/kibot/out_pcb_print.py index 6d28ad03..5616a9e2 100644 --- a/kibot/out_pcb_print.py +++ b/kibot/out_pcb_print.py @@ -189,7 +189,10 @@ class PagesOptions(Optionable): """ *Try to sort the layers in the same order that uses KiCad for printing """ self.layers = LayerOptions """ *[list(dict)|list(string)|string] List of layers printed in this page. - Order is important, the last goes on top """ + Order is important, the last goes on top. + You can reuse other layers lists, some options aren't used here, but they are valid """ + self.page_id = '%02d' + """ Text to differentiate the pages. Use %d (like in C) to get the page number """ self._scaling_example = 1.0 def config(self, parent): @@ -221,9 +224,10 @@ class PCB_PrintOptions(VariantOptions): """ {output} """ self.output = GS.def_global_output """ *Filename for the output (%i=assembly, %x=pdf/ps)/(%i=assembly_page_NN, %x=svg/png/eps). - Consult the `page_number_as_extension` """ + Consult the `page_number_as_extension` and `page_id` options """ self.page_number_as_extension = False - """ When enabled the %i is always `assembly`, the %x will be NN.FORMAT (i.e. 01.png) """ + """ When enabled the %i is always `assembly`, the %x will be NN.FORMAT (i.e. 01.png). + Note: page numbers can be customized using the `page_id` option for each page """ self.hide_excluded = False """ Hide components in the Fab layer that are marked as excluded by a variant """ self.color_theme = '_builtin_classic' @@ -351,8 +355,12 @@ class PCB_PrintOptions(VariantOptions): if self.hide_excluded: self.restore_fab(GS.board, comps_hash) - def get_id_and_ext(self, n=None): - pn_str = '%02d' % (n+1) if n is not None else '%02d' + def get_id_and_ext(self, n=None, id='%02d'): + try: + pn_str = id % (n+1) if n is not None else id + except TypeError: + # If id doesn't contain %d we get this exception + pn_str = id if self.page_number_as_extension: return self._expand_id, pn_str+'.'+self._expand_ext return self._expand_id+'_page_'+pn_str, self._expand_ext @@ -360,8 +368,8 @@ class PCB_PrintOptions(VariantOptions): def get_targets(self, out_dir): if self.format in ['SVG', 'PNG', 'EPS']: files = [] - for n in range(len(self.pages)): - id, ext = self.get_id_and_ext(n) + for n, p in enumerate(self.pages): + id, ext = self.get_id_and_ext(n, p.page_id) files.append(self.expand_filename(out_dir, self.output, id, ext)) return files return [self._parent.expand_filename(out_dir, self.output)] @@ -936,6 +944,15 @@ class PCB_PrintOptions(VariantOptions): # if self.format == 'EPS': # self.rsvg_command_eps = self.ensure_tool('rsvg2') + def rename_pages(self, output_dir): + for n, p in enumerate(self.pages): + id, ext = self.get_id_and_ext(n) + cur_name = self.expand_filename(output_dir, self.output, id, ext) + id, ext = self.get_id_and_ext(n, p.page_id) + user_name = self.expand_filename(output_dir, self.output, id, ext) + if cur_name != user_name and os.path.isfile(cur_name): + os.rename(cur_name, user_name) + def generate_output(self, output): self.check_tools() output_dir = os.path.dirname(output) @@ -1025,7 +1042,7 @@ class PCB_PrintOptions(VariantOptions): filelist.append((GS.pcb_basename+"-frame.svg", color)) # 3) Stack all layers in one file if self.format == 'SVG': - id, ext = self.get_id_and_ext(n) + id, ext = self.get_id_and_ext(n, p.page_id) assembly_file = self.expand_filename(output_dir, self.output, id, ext) else: assembly_file = GS.pcb_basename+".svg" @@ -1056,6 +1073,7 @@ class PCB_PrintOptions(VariantOptions): else: # Use GS to create one PNG per page and then scale to the wanted width self.pdf_to_png(pdf_file, out_file) + self.rename_pages(output_dir) # Remove the temporal files if not self.keep_temporal_files: rmtree(temp_dir_base) diff --git a/tests/test_plot/test_print_pcb.py b/tests/test_plot/test_print_pcb.py index cf1ca491..98f28216 100644 --- a/tests/test_plot/test_print_pcb.py +++ b/tests/test_plot/test_print_pcb.py @@ -124,8 +124,8 @@ def test_pcb_print_simple_1(test_dir): prj = 'light_control' ctx = context.TestContext(test_dir, prj, 'pcb_print_2') ctx.run() - ctx.expect_out_file(prj+'-assembly_page_01.png') - ctx.expect_out_file(prj+'-assembly_page_02.png') + ctx.expect_out_file(prj+'-F_Cu_mono.png') + ctx.expect_out_file(prj+'-F_Cu_color.png') ctx.expect_out_file(prj+'-assembly_page_01.eps') ctx.expect_out_file(prj+'-assembly_page_01.svg') ctx.expect_out_file(prj+'-assembly.ps') diff --git a/tests/yaml_samples/pcb_print_2.kibot.yaml b/tests/yaml_samples/pcb_print_2.kibot.yaml index 29389550..2fa3032a 100644 --- a/tests/yaml_samples/pcb_print_2.kibot.yaml +++ b/tests/yaml_samples/pcb_print_2.kibot.yaml @@ -19,6 +19,8 @@ outputs: # enable_ki6_frame_fix: true add_background: true background_image: "tests/data/confidential_optimized.svg" + output: '%f-%I%v%x' + page_number_as_extension: true pages: - layers: - layer: F.Cu @@ -26,6 +28,7 @@ outputs: color: '#14332440' - layer: Edge.Cuts color: "#004040" + page_id: F_Cu_color - monochrome: true layers: - layer: F.Cu @@ -33,6 +36,7 @@ outputs: color: '#14332440' - layer: Edge.Cuts color: "#004040" + page_id: F_Cu_mono - name: 'print_bottom' comment: "Experiment"