summaryrefslogtreecommitdiffstats
path: root/share/extensions/printing_marks.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:24:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:24:48 +0000
commitcca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch)
tree146f39ded1c938019e1ed42d30923c2ac9e86789 /share/extensions/printing_marks.py
parentInitial commit. (diff)
downloadinkscape-upstream.tar.xz
inkscape-upstream.zip
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'share/extensions/printing_marks.py')
-rwxr-xr-xshare/extensions/printing_marks.py622
1 files changed, 622 insertions, 0 deletions
diff --git a/share/extensions/printing_marks.py b/share/extensions/printing_marks.py
new file mode 100755
index 0000000..272bc02
--- /dev/null
+++ b/share/extensions/printing_marks.py
@@ -0,0 +1,622 @@
+#!/usr/bin/env python
+# coding=utf-8
+#
+# Authors:
+# Nicolas Dufour - Association Inkscape-fr
+# Aurelio A. Heckert <aurium(a)gmail.com>
+#
+# Copyright (C) 2008 Authors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+"""
+This extension allows you to draw crop, registration and other
+printing marks in Inkscape.
+"""
+
+import math
+import inkex
+from inkex import Circle, Rectangle, TextElement
+
+
+class PrintingMarks(inkex.EffectExtension):
+ # Default parameters
+ stroke_width = 0.25
+
+ def add_arguments(self, pars):
+ pars.add_argument("--where", help="Apply crop marks to...", default="canvas")
+ pars.add_argument(
+ "--crop_marks", type=inkex.Boolean, default=True, help="Draw crop Marks"
+ )
+ pars.add_argument("--bleed_marks", type=inkex.Boolean, help="Draw Bleed Marks")
+ pars.add_argument(
+ "--registration_marks",
+ type=inkex.Boolean,
+ dest="reg_marks",
+ default=True,
+ help="Draw Registration Marks?",
+ )
+ pars.add_argument("--star_target", type=inkex.Boolean, help="Draw Star Target?")
+ pars.add_argument(
+ "--colour_bars", type=inkex.Boolean, help="Draw Colour Bars?", default=True
+ )
+ pars.add_argument(
+ "--page_info", type=inkex.Boolean, help="Draw Page Information?"
+ )
+ pars.add_argument("--unit", default="px", help="Draw measurement")
+ pars.add_argument("--crop_offset", type=float, default=5.0, help="Offset")
+ pars.add_argument("--bleed_top", type=float, default=5.0, help="Bleed Top Size")
+ pars.add_argument(
+ "--bleed_bottom", type=float, default=5.0, help="Bleed Bottom Size"
+ )
+ pars.add_argument(
+ "--bleed_left", type=float, default=5.0, help="Bleed Left Size"
+ )
+ pars.add_argument(
+ "--bleed_right", type=float, default=5.0, help="Bleed Right Size"
+ )
+ pars.add_argument("--tab", help="The selected UI-tab when OK was pressed")
+
+ def draw_crop_line(self, x1, y1, x2, y2, name, parent):
+ style = {
+ "stroke": "#000000",
+ "stroke-width": str(self.stroke_width),
+ "fill": "none",
+ }
+ line_attribs = {
+ "style": str(inkex.Style(style)),
+ "id": name,
+ "d": "M " + str(x1) + "," + str(y1) + " L " + str(x2) + "," + str(y2),
+ }
+ parent.add(inkex.PathElement(**line_attribs))
+
+ def draw_bleed_line(self, x1, y1, x2, y2, name, parent):
+ style = {
+ "stroke": "#000000",
+ "stroke-width": str(self.stroke_width),
+ "fill": "none",
+ "stroke-miterlimit": "4",
+ "stroke-dasharray": "4, 2, 1, 2",
+ "stroke-dashoffset": "0",
+ }
+ line_attribs = {
+ "style": str(inkex.Style(style)),
+ "id": name,
+ "d": "M " + str(x1) + "," + str(y1) + " L " + str(x2) + "," + str(y2),
+ }
+ parent.add(inkex.PathElement(**line_attribs))
+
+ def draw_reg_circles(self, cx, cy, r, name, colours, parent):
+ for i in range(len(colours)):
+ style = {
+ "stroke": colours[i],
+ "stroke-width": str(r / len(colours)),
+ "fill": "none",
+ }
+ circle_attribs = {
+ "style": str(inkex.Style(style)),
+ "inkscape:label": name,
+ "cx": str(cx),
+ "cy": str(cy),
+ "r": str((r / len(colours)) * (i + 0.5)),
+ }
+ parent.add(Circle(**circle_attribs))
+
+ def draw_reg_marks(self, cx, cy, rotate, name, parent):
+ colours = ["#000000", "#00ffff", "#ff00ff", "#ffff00", "#000000"]
+ g = parent.add(inkex.Group(id=name))
+ for i in range(len(colours)):
+ style = {"fill": colours[i], "fill-opacity": "1", "stroke": "none"}
+ r = self.mark_size / 2
+ step = r
+ stroke = r / len(colours)
+ regoffset = stroke * i
+ regmark_attribs = {
+ "style": str(inkex.Style(style)),
+ "d": "m"
+ + " "
+ + str(-regoffset)
+ + ","
+ + str(r)
+ + " "
+ + str(-stroke)
+ + ",0"
+ + " "
+ + str(step)
+ + ","
+ + str(-r)
+ + " "
+ + str(-step)
+ + ","
+ + str(-r)
+ + " "
+ + str(stroke)
+ + ",0"
+ + " "
+ + str(step)
+ + ","
+ + str(r)
+ + " "
+ + str(-step)
+ + ","
+ + str(r)
+ + " z",
+ "transform": "translate("
+ + str(cx)
+ + ","
+ + str(cy)
+ + ") rotate("
+ + str(rotate)
+ + ")",
+ }
+ g.add(inkex.PathElement(**regmark_attribs))
+
+ def draw_star_target(self, cx, cy, name, parent):
+ r = self.mark_size / 2
+ style = {
+ "fill": "#000 device-cmyk(1,1,1,1)",
+ "fill-opacity": "1",
+ "stroke": "none",
+ }
+ d = " M 0,0"
+ i = 0
+ while i < (2 * math.pi):
+ i += math.pi / 16
+ d += (
+ " L 0,0 "
+ + " L "
+ + str(math.sin(i) * r)
+ + ","
+ + str(math.cos(i) * r)
+ + " L "
+ + str(math.sin(i + 0.09) * r)
+ + ","
+ + str(math.cos(i + 0.09) * r)
+ )
+ elem = parent.add(inkex.PathElement())
+ elem.label = name
+ elem.transform.add_translate(cx, cy)
+ elem.path = d
+ elem.style = inkex.Style(style)
+
+ def draw_coluor_bars(self, cx, cy, rotate, name, parent, bbox):
+ group = parent.add(inkex.Group(id=name))
+ group.transform = inkex.Transform(translate=(cx, cy)) @ inkex.Transform(
+ rotate=rotate
+ )
+ loc = 0
+ if bbox:
+ loc = min(self.mark_size / 3, max(bbox.width, bbox.height) / 45)
+ for bar in [
+ {"c": "*", "stroke": "#000", "x": 0, "y": -(loc + 1)},
+ {"c": "r", "stroke": "#0FF", "x": 0, "y": 0},
+ {"c": "g", "stroke": "#F0F", "x": (loc * 11) + 1, "y": -(loc + 1)},
+ {"c": "b", "stroke": "#FF0", "x": (loc * 11) + 1, "y": 0},
+ ]:
+ i = 0
+ while i <= 1:
+ color = inkex.Color("white")
+ if bar["c"] == "r" or bar["c"] == "*":
+ color.red = 255 * i
+ if bar["c"] == "g" or bar["c"] == "*":
+ color.green = 255 * i
+ if bar["c"] == "b" or bar["c"] == "*":
+ color.blue = 255 * i
+ r_att = {
+ "fill": str(color),
+ "stroke": bar["stroke"],
+ "stroke-width": loc / 8,
+ "x": str((loc * i * 10) + bar["x"]),
+ "y": str(bar["y"]),
+ "width": loc,
+ "height": loc,
+ }
+ rect = Rectangle()
+ for att, value in r_att.items():
+ rect.set(att, value)
+ group.add(rect)
+ i += 0.1
+
+ def effect(self):
+ self.mark_size = self.svg.viewport_to_unit("1cm")
+ self.min_mark_margin = self.svg.viewport_to_unit("3mm")
+
+ if self.options.where == "selection":
+ bbox = self.svg.selection.bounding_box()
+ if bbox is None:
+ raise inkex.AbortExtension(_("Selection is empty"))
+ else:
+ bbox = self.svg.get_page_bbox()
+
+ # Get SVG document dimensions
+ # self.width must be replaced by bbox.right. same to others.
+ svg = self.document.getroot()
+
+ # Convert parameters to user unit
+ offset = self.svg.viewport_to_unit(
+ str(self.options.crop_offset) + self.options.unit
+ )
+ bt = self.svg.viewport_to_unit(str(self.options.bleed_top) + self.options.unit)
+ bb = self.svg.viewport_to_unit(
+ str(self.options.bleed_bottom) + self.options.unit
+ )
+ bl = self.svg.viewport_to_unit(str(self.options.bleed_left) + self.options.unit)
+ br = self.svg.viewport_to_unit(
+ str(self.options.bleed_right) + self.options.unit
+ )
+ # Bleed margin
+ if bt < offset:
+ bmt = 0
+ else:
+ bmt = bt - offset
+ if bb < offset:
+ bmb = 0
+ else:
+ bmb = bb - offset
+ if bl < offset:
+ bml = 0
+ else:
+ bml = bl - offset
+ if br < offset:
+ bmr = 0
+ else:
+ bmr = br - offset
+
+ # Define the new document limits
+ offset_left = bbox.left - offset
+ offset_right = bbox.right + offset
+ offset_top = bbox.top - offset
+ offset_bottom = bbox.bottom + offset
+
+ # Get middle positions
+ middle_vertical = bbox.top + (bbox.height / 2)
+ middle_horizontal = bbox.left + (bbox.width / 2)
+
+ # Test if printing-marks layer existis
+ layer = self.svg.xpath(
+ '//*[@id="printing-marks" and @inkscape:groupmode="layer"]'
+ )
+ if layer:
+ svg.remove(layer[0]) # remove if it existis
+ # Create a new layer
+ layer = svg.add(inkex.Layer.new("Printing Marks"))
+ layer.set("id", "printing-marks")
+ layer.set("sodipodi:insensitive", "true")
+
+ # Crop Mark
+ if self.options.crop_marks:
+ # Create a group for Crop Mark
+ g_crops = layer.add(inkex.Group(id="CropMarks"))
+ g_crops.label = "CropMarks"
+
+ # Top left Mark
+ self.draw_crop_line(
+ bbox.left,
+ offset_top,
+ bbox.left,
+ offset_top - self.mark_size,
+ "cropTL1",
+ g_crops,
+ )
+ self.draw_crop_line(
+ offset_left,
+ bbox.top,
+ offset_left - self.mark_size,
+ bbox.top,
+ "cropTL2",
+ g_crops,
+ )
+
+ # Top right Mark
+ self.draw_crop_line(
+ bbox.right,
+ offset_top,
+ bbox.right,
+ offset_top - self.mark_size,
+ "cropTR1",
+ g_crops,
+ )
+ self.draw_crop_line(
+ offset_right,
+ bbox.top,
+ offset_right + self.mark_size,
+ bbox.top,
+ "cropTR2",
+ g_crops,
+ )
+
+ # Bottom left Mark
+ self.draw_crop_line(
+ bbox.left,
+ offset_bottom,
+ bbox.left,
+ offset_bottom + self.mark_size,
+ "cropBL1",
+ g_crops,
+ )
+ self.draw_crop_line(
+ offset_left,
+ bbox.bottom,
+ offset_left - self.mark_size,
+ bbox.bottom,
+ "cropBL2",
+ g_crops,
+ )
+
+ # Bottom right Mark
+ self.draw_crop_line(
+ bbox.right,
+ offset_bottom,
+ bbox.right,
+ offset_bottom + self.mark_size,
+ "cropBR1",
+ g_crops,
+ )
+ self.draw_crop_line(
+ offset_right,
+ bbox.bottom,
+ offset_right + self.mark_size,
+ bbox.bottom,
+ "cropBR2",
+ g_crops,
+ )
+
+ # Bleed Mark
+ if self.options.bleed_marks:
+ # Create a group for Bleed Mark
+ g_bleed = layer.add(inkex.Group())
+ g_bleed.label = "BleedMarks"
+ g_bleed.set("id", "BleedMarks")
+
+ # Top left Mark
+ self.draw_bleed_line(
+ bbox.left - bl,
+ offset_top - bmt,
+ bbox.left - bl,
+ offset_top - bmt - self.mark_size,
+ "bleedTL1",
+ g_bleed,
+ )
+ self.draw_bleed_line(
+ offset_left - bml,
+ bbox.top - bt,
+ offset_left - bml - self.mark_size,
+ bbox.top - bt,
+ "bleedTL2",
+ g_bleed,
+ )
+
+ # Top right Mark
+ self.draw_bleed_line(
+ bbox.right + br,
+ offset_top - bmt,
+ bbox.right + br,
+ offset_top - bmt - self.mark_size,
+ "bleedTR1",
+ g_bleed,
+ )
+ self.draw_bleed_line(
+ offset_right + bmr,
+ bbox.top - bt,
+ offset_right + bmr + self.mark_size,
+ bbox.top - bt,
+ "bleedTR2",
+ g_bleed,
+ )
+
+ # Bottom left Mark
+ self.draw_bleed_line(
+ bbox.left - bl,
+ offset_bottom + bmb,
+ bbox.left - bl,
+ offset_bottom + bmb + self.mark_size,
+ "bleedBL1",
+ g_bleed,
+ )
+ self.draw_bleed_line(
+ offset_left - bml,
+ bbox.bottom + bb,
+ offset_left - bml - self.mark_size,
+ bbox.bottom + bb,
+ "bleedBL2",
+ g_bleed,
+ )
+
+ # Bottom right Mark
+ self.draw_bleed_line(
+ bbox.right + br,
+ offset_bottom + bmb,
+ bbox.right + br,
+ offset_bottom + bmb + self.mark_size,
+ "bleedBR1",
+ g_bleed,
+ )
+ self.draw_bleed_line(
+ offset_right + bmr,
+ bbox.bottom + bb,
+ offset_right + bmr + self.mark_size,
+ bbox.bottom + bb,
+ "bleedBR2",
+ g_bleed,
+ )
+
+ # Registration Mark
+ if self.options.reg_marks:
+ # Create a group for Registration Mark
+ g_center = layer.add(inkex.Group())
+ g_center.label = "RegistrationMarks"
+ g_center.set("id", "RegistrationMarks")
+ # Left Mark
+ cx = max(bml + offset, self.min_mark_margin)
+ self.draw_reg_marks(
+ bbox.left - cx - (self.mark_size / 2),
+ middle_vertical - self.mark_size * 1.5,
+ "0",
+ "regMarkL",
+ g_center,
+ )
+
+ # Right Mark
+ cx = max(bmr + offset, self.min_mark_margin)
+ self.draw_reg_marks(
+ bbox.right + cx + (self.mark_size / 2),
+ middle_vertical - self.mark_size * 1.5,
+ "180",
+ "regMarkR",
+ g_center,
+ )
+
+ # Top Mark
+ cy = max(bmt + offset, self.min_mark_margin)
+ self.draw_reg_marks(
+ middle_horizontal,
+ bbox.top - cy - (self.mark_size / 2),
+ "90",
+ "regMarkT",
+ g_center,
+ )
+
+ # Bottom Mark
+ cy = max(bmb + offset, self.min_mark_margin)
+ self.draw_reg_marks(
+ middle_horizontal,
+ bbox.bottom + cy + (self.mark_size / 2),
+ "-90",
+ "regMarkB",
+ g_center,
+ )
+
+ # Star Target
+ if self.options.star_target:
+ # Create a group for Star Target
+ g_center = layer.add(inkex.Group())
+ g_center.label = "StarTarget"
+ g_center.set("id", "StarTarget")
+
+ if bbox.height < bbox.width:
+ # Left Star
+ cx = max(bml + offset, self.min_mark_margin)
+ self.draw_star_target(
+ bbox.left - cx - (self.mark_size / 2),
+ middle_vertical,
+ "starTargetL",
+ g_center,
+ )
+ # Right Star
+ cx = max(bmr + offset, self.min_mark_margin)
+ self.draw_star_target(
+ bbox.right + cx + (self.mark_size / 2),
+ middle_vertical,
+ "starTargetR",
+ g_center,
+ )
+ else:
+ # Top Star
+ cy = max(bmt + offset, self.min_mark_margin)
+ self.draw_star_target(
+ middle_horizontal - self.mark_size * 1.5,
+ bbox.top - cy - (self.mark_size / 2),
+ "starTargetT",
+ g_center,
+ )
+ # Bottom Star
+ cy = max(bmb + offset, self.min_mark_margin)
+ self.draw_star_target(
+ middle_horizontal - self.mark_size * 1.5,
+ bbox.bottom + cy + (self.mark_size / 2),
+ "starTargetB",
+ g_center,
+ )
+
+ # Colour Bars
+ if self.options.colour_bars:
+ # Create a group for Colour Bars
+ g_center = layer.add(inkex.Group())
+ g_center.label = "ColourBars"
+ g_center.set("id", "PrintingColourBars")
+
+ if bbox.height > bbox.width:
+ # Left Bars
+ cx = max(bml + offset, self.min_mark_margin)
+ self.draw_coluor_bars(
+ bbox.left - cx - (self.mark_size / 2),
+ middle_vertical + self.mark_size,
+ 90,
+ "PrintingColourBarsL",
+ g_center,
+ bbox,
+ )
+ # Right Bars
+ cx = max(bmr + offset, self.min_mark_margin)
+ self.draw_coluor_bars(
+ bbox.right + cx + (self.mark_size / 2),
+ middle_vertical + self.mark_size,
+ 90,
+ "PrintingColourBarsR",
+ g_center,
+ bbox,
+ )
+ else:
+ # Top Bars
+ cy = max(bmt + offset, self.min_mark_margin)
+ self.draw_coluor_bars(
+ middle_horizontal + self.mark_size,
+ bbox.top - cy - (self.mark_size / 2),
+ 0,
+ "PrintingColourBarsT",
+ g_center,
+ bbox,
+ )
+ # Bottom Bars
+ cy = max(bmb + offset, self.min_mark_margin)
+ self.draw_coluor_bars(
+ middle_horizontal + self.mark_size,
+ bbox.bottom + cy + (self.mark_size / 2),
+ 0,
+ "PrintingColourBarsB",
+ g_center,
+ bbox,
+ )
+
+ # Page Information
+ if self.options.page_info:
+ # Create a group for Page Information
+ g_pag_info = layer.add(inkex.Group())
+ g_pag_info.label = "PageInformation"
+ g_pag_info.set("id", "PageInformation")
+ y_margin = max(bmb + offset, self.min_mark_margin)
+ font_size = self.svg.viewport_to_unit("9pt")
+ txt_attribs = {
+ "style": f"font-size:{font_size}px;font-style:normal;font-weight:normal;fill:#000000;font-family:Bitstream Vera Sans,sans-serif;text-anchor:middle;text-align:center",
+ "x": str(middle_horizontal),
+ "y": str(bbox.bottom + y_margin + self.mark_size + 20),
+ }
+ txt = g_pag_info.add(TextElement(**txt_attribs))
+ txt.text = (
+ "Page size: "
+ + str(
+ round(self.svg.unit_to_viewport(bbox.width, self.options.unit), 2)
+ )
+ + "x"
+ + str(
+ round(self.svg.unit_to_viewport(bbox.height, self.options.unit), 2)
+ )
+ + " "
+ + self.options.unit
+ )
+
+
+if __name__ == "__main__":
+ PrintingMarks().run()