summaryrefslogtreecommitdiffstats
path: root/share/extensions/frame.py
diff options
context:
space:
mode:
Diffstat (limited to 'share/extensions/frame.py')
-rwxr-xr-xshare/extensions/frame.py127
1 files changed, 127 insertions, 0 deletions
diff --git a/share/extensions/frame.py b/share/extensions/frame.py
new file mode 100755
index 0000000..013e195
--- /dev/null
+++ b/share/extensions/frame.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+# coding=utf-8
+#
+# Copyright (C) 2016 Richard White, rwhite8282@gmail.com
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+"""
+An Inkscape extension that creates a frame around a selected object.
+"""
+
+import inkex
+from inkex import Group, PathElement, ClipPath
+
+def size_box(box, delta):
+ """ Returns a box with an altered size.
+ delta -- The amount the box should grow.
+ Returns a box with an altered size.
+ """
+ return (box.x.minimum - delta, box.x.maximum + delta,
+ box.y.minimum - delta, box.y.maximum + delta)
+
+
+# Frame maker Inkscape effect extension
+class Frame(inkex.EffectExtension):
+ """
+ An Inkscape extension that creates a frame around a selected object.
+ """
+ def add_arguments(self, pars):
+ # Parse the options.
+ pars.add_argument('--tab', default='object')
+ pars.add_argument('--clip', type=inkex.Boolean, default=False)
+ pars.add_argument('--corner_radius', type=int, default=0)
+ pars.add_argument('--fill_color', type=inkex.Color, default=inkex.Color(0))
+ pars.add_argument('--group', type=inkex.Boolean, default=False)
+ pars.add_argument('--position', default='outside')
+ pars.add_argument('--stroke_color', type=inkex.Color, default=inkex.Color(0))
+ pars.add_argument('--width', type=float, default=2.0)
+
+ def add_clip(self, node, clip_path):
+ """ Adds a new clip path node to the defs and sets
+ the clip-path on the node.
+ node -- The node that will be clipped.
+ clip_path -- The clip path object.
+ """
+ clip = ClipPath()
+ clip.append(PathElement(d=str(clip_path.path)))
+ clip_id = self.svg.get_unique_id('clipPath')
+ clip.set('id', clip_id)
+ self.svg.defs.append(clip)
+ node.set('clip-path', 'url(#{})'.format(str(clip_id)))
+
+ def add_frame(self, name, box, style, radius=0):
+ """
+ name -- The name of the new frame object.
+ box -- The boundary box of the node.
+ style -- The style used to draw the path.
+ radius -- The corner radius of the frame.
+ returns a new frame node.
+ """
+ r = min([radius, (abs(box[1] - box[0]) / 2), (abs(box[3] - box[2]) / 2)])
+ if radius > 0:
+ d = ' '.join(str(x) for x in
+ ['M', box[0], (box[2] + r),
+ 'A', r, r, '0 0 1', (box[0] + r), box[2],
+ 'L', (box[1] - r), box[2],
+ 'A', r, r, '0 0 1', box[1], (box[2] + r),
+ 'L', box[1], (box[3] - r),
+ 'A', r, r, '0 0 1', (box[1] - r), box[3],
+ 'L', (box[0] + r), box[3],
+ 'A', r, r, '0 0 1', box[0], (box[3] - r),
+ 'Z'])
+ else:
+ d = ' '.join(str(x) for x in
+ ['M', box[0], box[2],
+ 'L', box[1], box[2],
+ 'L', box[1], box[3],
+ 'L', box[0], box[3],
+ 'Z'])
+
+ elem = PathElement()
+ elem.style = style
+ elem.label = name
+ elem.path = d
+ return elem
+
+ def effect(self):
+ """Performs the effect."""
+ # Determine common properties.
+ width = self.options.width
+ style = inkex.Style({'stroke-width': width})
+ style.set_color(self.options.fill_color, 'fill')
+ style.set_color(self.options.stroke_color, 'stroke')
+ layer = self.svg.get_current_layer()
+
+ for node in self.svg.selected.values():
+ box = node.bounding_box()
+ if self.options.position == 'outside':
+ box = size_box(box, (width / 2))
+ else:
+ box = size_box(box, -(width / 2))
+
+ frame = self.add_frame("Frame", box, style, self.options.corner_radius)
+ if self.options.clip:
+ self.add_clip(node, frame)
+ if self.options.group:
+ group = layer.add(Group())
+ group.append(node)
+ group.append(frame)
+ else:
+ layer.append(frame)
+ return None
+
+if __name__ == '__main__':
+ Frame().run()