Skip to content

Commit 2a165f7

Browse files
committed
[Report] Support for multi-page PDFs of SCH/PCB
- So now we can use SVGs or PDFs for both
1 parent 2f664e2 commit 2a165f7

10 files changed

Lines changed: 126 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- KiCad Site:
2020
- `bom` configuration
2121
- `kiri` configuration
22+
- Report:
23+
- All PDF pages are included, not just the first
24+
- The full report now works with SVGs and PDFs for both (SCH and PCB),
25+
SVGs have priority
26+
- `remove_split_pdfs`: To control if we remove split PDFs
2227

2328
## Fixed
2429
- KiRi:
2530
- `kiri_server` path to the HTML
2631
- *SCH Print:
2732
- The list of targets now includes all schematic pages
2833
- Report:
29-
- Now all schematic pages are included, not just the first
34+
- Now all SVG schematic pages are included, not just the first
3035

3136
## Changed
3237
- E/DRC and BoM: As we now have dark mode support the CSS is more complex and
@@ -35,8 +40,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3540
created output is displayed.
3641
- When using `pcb_print` and including tables you no longer need to run the
3742
output that generates the CSV first, it gets generated on-the-fly
38-
- When using `report` the outputs that generates images no longer needs to be
39-
already executed, KiBot will run them
43+
- Report: the outputs that generates images no longer needs to be already
44+
executed, KiBot will run them
4045

4146

4247
## [1.9.0] - 2026-05-12

docs/samples/generic_plot.kibot.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4659,6 +4659,10 @@ outputs:
46594659
# Can be used to fine-tune a variant for a particular output that needs extra filtering done before the
46604660
# variant
46614661
pre_transform: '_null'
4662+
# [string='auto'] [auto,yes,no] When we use PDF files they are split because `pandoc` can't deal with more than
4663+
# one page. You can delete them after converting the output. The `auto` value will do it when
4664+
# `do_convert` is enabled
4665+
remove_split_pdfs: 'auto'
46624666
# [number=87.75] [0,100] Amount of metal in the solder paste (percentage). Used to compute solder paste usage
46634667
solder_paste_metal_amount: 87.75
46644668
# [number=0.12] Stencil thickness in mm. Used to compute solder paste usage

docs/source/Changelog.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ Added
4141
- ``bom`` configuration
4242
- ``kiri`` configuration
4343

44+
- Report:
45+
46+
- All PDF pages are included, not just the first
47+
- The full report now works with SVGs and PDFs for both (SCH and
48+
PCB), SVGs have priority
49+
- ``remove_split_pdfs``: To control if we remove split PDFs
50+
4451
Fixed
4552
-----
4653

@@ -54,7 +61,7 @@ Fixed
5461

5562
- Report:
5663

57-
- Now all schematic pages are included, not just the first
64+
- Now all SVG schematic pages are included, not just the first
5865

5966
Changed
6067
-------
@@ -66,8 +73,8 @@ Changed
6673
- When using ``pcb_print`` and including tables you no longer need to
6774
run the output that generates the CSV first, it gets generated
6875
on-the-fly
69-
- When using ``report`` the outputs that generates images no longer
70-
needs to be already executed, KiBot will run them
76+
- Report: the outputs that generates images no longer needs to be
77+
already executed, KiBot will run them
7178

7279
[1.9.0] - 2026-05-12
7380
--------------------

docs/source/configuration/outputs/ReportOptions.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ ReportOptions parameters
5151
Can be used to fine-tune a variant for a particular output that needs extra filtering done before the
5252
variant.
5353

54+
- ``remove_split_pdfs`` :index:`: <pair: output - report - options; remove_split_pdfs>` [:ref:`string <string>`] (default: ``'auto'``) (choices: "auto", "yes", "no") When we use PDF files they are split because `pandoc` can't deal with more than
55+
one page. You can delete them after converting the output. The `auto` value will do it when
56+
`do_convert` is enabled.
5457
- ``solder_paste_metal_amount`` :index:`: <pair: output - report - options; solder_paste_metal_amount>` [:ref:`number <number>`] (default: ``87.75``) (range: 0 to 100) Amount of metal in the solder paste (percentage). Used to compute solder paste usage.
5558
- ``stencil_thickness`` :index:`: <pair: output - report - options; stencil_thickness>` [:ref:`number <number>`] (default: ``0.12``) Stencil thickness in mm. Used to compute solder paste usage.
5659
- ``variant`` :index:`: <pair: output - report - options; variant>` [:ref:`string <string>`] (default: ``''``) Board variant to apply.

kibot/create_pdf.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (c) 2022 Salvador E. Tropea
3-
# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial
2+
# Copyright (c) 2022-2026 Salvador E. Tropea
3+
# Copyright (c) 2022-2026 Instituto Nacional de Tecnología Industrial
44
# Copyright (c) 2022 Albin Dennevi (create_pdf_from_pages)
5-
# License: GPL-3.0
5+
# License: AGPL-3.0
66
# Project: KiBot (formerly KiPlot)
7-
# Base idea: https://gitlab.com/dennevi/Board2Pdf/ (Released as Public Domain)
7+
# Base idea for create_pdf_from_pages: https://gitlab.com/dennevi/Board2Pdf/ (Released as Public Domain)
8+
# Base idea for split_pdf: Gemini 3.1 Pro
9+
import os
810
from . import PyPDF2
911
from . import log
1012

@@ -34,3 +36,26 @@ def create_pdf_from_pages(input_files, output_fn, forced_width=None):
3436
# Close the files
3537
for f in open_files:
3638
f.close()
39+
40+
41+
def split_pdf(input_pdf):
42+
with open(input_pdf, "rb") as infile:
43+
reader = PyPDF2.PdfFileReader(infile)
44+
num_pages = len(reader.pages)
45+
46+
if num_pages == 1:
47+
return [input_pdf]
48+
49+
base_name = os.path.splitext(input_pdf)[0]
50+
created = []
51+
for i in range(num_pages):
52+
writer = PyPDF2.PdfFileWriter()
53+
writer.addPage(reader.pages[i])
54+
55+
output_filepath = f"{base_name}-{i+1}.pdf"
56+
57+
logger.error(output_filepath)
58+
created.append(output_filepath)
59+
with open(output_filepath, "wb") as outfile:
60+
writer.write(outfile)
61+
return created

kibot/out_report.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (c) 2022-2024 Salvador E. Tropea
3-
# Copyright (c) 2022-2024 Instituto Nacional de Tecnología Industrial
2+
# Copyright (c) 2022-2026 Salvador E. Tropea
3+
# Copyright (c) 2022-2026 Instituto Nacional de Tecnología Industrial
44
# License: AGPL-3.0
55
# Project: KiBot (formerly KiPlot)
66
"""
@@ -20,6 +20,7 @@
2020
import re
2121
import pcbnew
2222

23+
from .create_pdf import split_pdf
2324
from .gs import GS
2425
from .misc import (UI_SMD, UI_VIRTUAL, MOD_THROUGH_HOLE, MOD_SMD, MOD_EXCLUDE_FROM_POS_FILES, W_WRONGEXT, W_UNKPADSH,
2526
W_WRONGOAR, W_ECCLASST, W_BLINDVIAS, W_MICROVIAS, W_BURIEDVIAS)
@@ -238,6 +239,10 @@ def __init__(self):
238239
self.csv_remove_leading_spaces = False
239240
""" Remove any leading spaces/tabs at the end of each separator.
240241
Used por templates that generates CSV files where elements are aligned for easier reading """
242+
self.remove_split_pdfs = 'auto'
243+
""" [auto,yes,no] When we use PDF files they are split because `pandoc` can't deal with more than
244+
one page. You can delete them after converting the output. The `auto` value will do it when
245+
`do_convert` is enabled """
241246
super().__init__()
242247
self._expand_id = 'report'
243248
self._expand_ext = 'txt'
@@ -1137,7 +1142,7 @@ def expand_converted_output(self, out_dir):
11371142
def get_targets(self, out_dir):
11381143
files = [self._parent.expand_filename(out_dir, self.output)]
11391144
if self.do_convert:
1140-
files.append(self.expand_converted_output(out_dir))
1145+
files.insert(0, self.expand_converted_output(out_dir))
11411146
return files
11421147

11431148
def convert(self, fname):
@@ -1183,6 +1188,7 @@ def run(self, fname):
11831188
self._layer_svgs = []
11841189
self._schematic_pdfs = []
11851190
self._schematic_svgs = []
1191+
split_pdfs = []
11861192
for o in RegOutput.get_outputs():
11871193
dest = None
11881194
if o.type == 'pdf_pcb_print' or o.type == 'pcb_print':
@@ -1210,13 +1216,24 @@ def run(self, fname):
12101216
comment = o.comment
12111217
if is_pcb_print_svg and o.options.pages[n].sheet:
12121218
comment += ' '+o.options.pages[n].sheet
1219+
# Split PDFs, otherwise we get the first page
1220+
if of.endswith('.pdf'):
1221+
split = split_pdf(of)
1222+
split_pdfs.extend(split)
1223+
if len(split) > 1:
1224+
for pdf_page, pdf_name in enumerate(split):
1225+
dest.append((os.path.relpath(pdf_name, base_dir), comment+f" page {pdf_page+1}", o.name))
1226+
continue
12131227
dest.append((rel_path, comment, o.name))
12141228
self.layer_pdfs = len(self._layer_pdfs) > 0
12151229
self.layer_svgs = len(self._layer_svgs) > 0
12161230
self.schematic_pdfs = len(self._schematic_pdfs) > 0
12171231
self.schematic_svgs = len(self._schematic_svgs) > 0
12181232
self.do_template(self.template, fname)
12191233
self.convert(fname)
1234+
if self.remove_split_pdfs == 'yes' or (self.remove_split_pdfs == 'auto' and self.do_convert):
1235+
for pdf_name in split_pdfs:
1236+
os.remove(pdf_name)
12201237

12211238

12221239
@output_class

kibot/resources/report_templates/report_full.txt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,25 @@ Note: this is just an approximation to the theoretical value. Margins of the sol
133133
#schematic_svgs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}
134134

135135

136-
#?layer_pdfs
136+
#?schematic_pdfs and not schematic_svgs
137+
# Schematic
138+
#?schematic_pdfs and not schematic_svgs
139+
140+
#?schematic_pdfs and not schematic_svgs
141+
#schematic_pdfs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}
142+
143+
144+
#?layer_svgs
145+
# PCB Layers
146+
#?layer_svgs
147+
148+
#?layer_svgs
149+
#layer_svgs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}
150+
151+
152+
#?layer_pdfs and not layer_svgs
137153
# PCB Layers
138-
#?layer_pdfs
154+
#?layer_pdfs and not layer_svgs
139155

140-
#?layer_pdfs
156+
#?layer_pdfs and not layer_svgs
141157
#layer_pdfs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}

kibot/resources/report_templates/report_full_svg.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,25 @@ Note: this is just an approximation to the theoretical value. Margins of the sol
133133
#schematic_svgs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}
134134

135135

136+
#?schematic_pdfs and not schematic_svgs
137+
# Schematic
138+
#?schematic_pdfs and not schematic_svgs
139+
140+
#?schematic_pdfs and not schematic_svgs
141+
#schematic_pdfs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}
142+
143+
136144
#?layer_svgs
137145
# PCB Layers
138146
#?layer_svgs
139147

140148
#?layer_svgs
141149
#layer_svgs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}
150+
151+
152+
#?layer_svgs and not layer_svgs
153+
# PCB Layers
154+
#?layer_svgs and not layer_svgs
155+
156+
#?layer_svgs and not layer_svgs
157+
#layer_svgs:![${comment}](${path}){ width=16.5cm height=11.7cm }${new_line}

tests/GUI/outputs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14411,6 +14411,13 @@
1441114411
],
1441214412
null
1441314413
],
14414+
[
14415+
"remove_split_pdfs",
14416+
[
14417+
"DataTypeChoice"
14418+
],
14419+
null
14420+
],
1441414421
[
1441514422
"variant",
1441614423
[

tests/GUI/stats

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
56 outputs types with a total of 2249 different parameters
2-
Single type parameters: 2058 (92 %)
1+
56 outputs types with a total of 2250 different parameters
2+
Single type parameters: 2059 (92 %)
33
Multi type parameters: 191 (8 %)
44
Average parameters: 40
55
Maximum number of parameters: 218
@@ -61,10 +61,10 @@ Outputs sorted by parameters:
6161
- pdf_pcb_print: 31
6262
- kicad_site: 33
6363
- position: 33
64-
- report: 33
6564
- svg_pcb_print: 33
6665
- gerb_drill: 34
6766
- pcb2blender_tools: 34
67+
- report: 34
6868
- vrml: 34
6969
- kicost: 37
7070
- diff: 42
@@ -157,7 +157,7 @@ Outputs sorted by depth:
157157
- Boolean: 566
158158
- ListStringSingular: 307
159159
- Number: 304
160-
- Choice: 112
160+
- Choice: 113
161161
- Dict: 92
162162
- ListDictOrString: 24
163163
- ListDict: 20
@@ -173,7 +173,7 @@ Used as single data type:
173173
- Boolean: 496
174174
- ListStringSingular: 303
175175
- Number: 210
176-
- Choice: 109
176+
- Choice: 110
177177
- Dict: 79
178178
- ListDict: 20
179179
- ListString: 9 ['blender_export.options.pcb3d.highlight', 'bom.options.group_fields', 'bom.options.group_fields_fallbacks', 'bom.options.no_conflict', 'kibom.options.conf.group_fields', 'pcbdraw.options.libs', 'pcbdraw.options.highlight', 'render_3d.options.highlight', 'vrml.options.highlight']
@@ -414,8 +414,8 @@ Used as single data type:
414414
- Number,String: 15
415415
================================================================================
416416
================================================================================
417-
97 totals types with a total of 2647 different parameters
418-
Single type parameters: 2430 (92 %)
417+
97 totals types with a total of 2648 different parameters
418+
Single type parameters: 2431 (92 %)
419419
Multi type parameters: 217 (8 %)
420420
Average parameters: 27
421421
Maximum number of parameters: 218
@@ -517,10 +517,10 @@ Totals sorted by parameters:
517517
- pdf_pcb_print: 31
518518
- kicad_site: 33
519519
- position: 33
520-
- report: 33
521520
- svg_pcb_print: 33
522521
- gerb_drill: 34
523522
- pcb2blender_tools: 34
523+
- report: 34
524524
- vrml: 34
525525
- generic: 35
526526
- kicost: 37
@@ -655,7 +655,7 @@ Totals sorted by depth:
655655
- Boolean: 669
656656
- Number: 357
657657
- ListStringSingular: 337
658-
- Choice: 144
658+
- Choice: 145
659659
- Dict: 103
660660
- ListDict: 30
661661
- ListDictOrString: 27
@@ -671,7 +671,7 @@ Used as single data type:
671671
- Boolean: 589
672672
- ListStringSingular: 333
673673
- Number: 248
674-
- Choice: 141
674+
- Choice: 142
675675
- Dict: 82
676676
- ListDict: 30
677677
- ListDictSingular: 15

0 commit comments

Comments
 (0)