-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpysvglabel.py
109 lines (87 loc) · 4.28 KB
/
pysvglabel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import argparse
import csv
import xml.etree.ElementTree as ET
import os.path
from typing import Optional
from labelcore import SvgTemplate, InkscapeSubprocess, INKSCAPE_NAMESPACE, SODIPODI_NAMESPACE
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Create label sheets from SVG templates.')
parser.add_argument('template', type=str,
help='Input SVG template file.')
parser.add_argument('csv', type=str,
help='Input CSV data file.')
parser.add_argument('output', type=str,
help="Filename to write outputs to. Can have .svg or .pdf extensions."
+ " If multiple sheets are needed, appends a prefix to the second one, starting with _2."
+ " If PDF output is requested, inkscape must be on the system path.")
parser.add_argument('--print', type=str,
help="Optional printer name, to send output files to a printer as they are generated."
+ " The output must be a PDF.")
parser.add_argument('--inkscape_multipage', action='store_true', default=False,
help="Use Inkscape's nonstandard multipage functionality, instead of writing multiple files.")
args = parser.parse_args()
# instantiating the template messes with the system path, so abspath everything now
csvpath = os.path.abspath(args.csv)
outputpath = os.path.abspath(args.output)
template = SvgTemplate(args.template)
template_page_count = template.get_sheet_count()[0] * template.get_sheet_count()[1]
with open(csvpath, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
table = [row for row in reader]
output_name, output_ext = os.path.splitext(outputpath)
inkscape: Optional[InkscapeSubprocess] = None
if output_ext == '.pdf':
inkscape = InkscapeSubprocess()
if args.print:
import win32api # type:ignore
import win32print # type:ignore
assert output_ext == '.pdf', "PDF output required to print"
def write_file(filename: str, sheet: ET.Element) -> None:
outfiles = []
with open(filename + '.svg', 'wb') as file:
root = ET.ElementTree(sheet)
root.write(file)
outfiles.append(filename + '.svg')
if inkscape:
inkscape.convert(filename + '.svg', filename + '.pdf')
outfiles.append(filename + '.pdf')
print(f'Wrote {", ".join(outfiles)}')
if args.print:
win32api.ShellExecute(0, "print", filename + '.pdf', f'/d:"{args.print}"', ".", 0)
print(f'Print to {args.print}')
# chunk into page-sized tables
page_tables = [table[start: start + template_page_count]
for start in range(0, len(table), template_page_count)]
if args.inkscape_multipage:
multipage = template.create_sheet()
namedviews = multipage.findall(f'{SODIPODI_NAMESPACE}namedview')
assert len(namedviews) == 1, f"must have exactly one sodipodi:namedview tag, got {len(namedviews)}"
namedview = namedviews[0]
assert len(namedview.findall(f'{INKSCAPE_NAMESPACE}page')) == 0, "namedview must be empty"
(viewbox_scale_x, viewbox_scale_y) = template._viewbox_scale()
for (page_num, page_table) in enumerate(page_tables):
page = template.apply_page(page_table)
if not args.inkscape_multipage:
sheet = template.create_sheet()
sheet.append(page)
if page_num == 0:
filename = output_name # first page doesn't need an extension
else:
filename = output_name + f'_{page_num + 1}'
write_file(filename, sheet)
else:
assert 'transform' not in page.attrib
page.attrib['transform'] = f'translate({page_num * template.sheet.page[0].to_px() * viewbox_scale_x}, 0)'
multipage.append(page)
namedview_page = ET.Element(f'{INKSCAPE_NAMESPACE}page')
namedview_page.attrib['x'] = str(page_num * template.sheet.page[0].to_px() * viewbox_scale_x)
namedview_page.attrib['y'] = '0'
namedview_page.attrib['width'] = str(template.sheet.page[0].to_px() * viewbox_scale_x)
namedview_page.attrib['height'] = str(template.sheet.page[1].to_px() * viewbox_scale_y)
namedview.append(namedview_page)
print(f'Generate page {page_num}')
if args.inkscape_multipage:
write_file(output_name, multipage)
template.run_end()
if inkscape:
inkscape.close()