summaryrefslogtreecommitdiff
path: root/lib/extensions/lettering_along_path.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/extensions/lettering_along_path.py')
-rw-r--r--lib/extensions/lettering_along_path.py143
1 files changed, 84 insertions, 59 deletions
diff --git a/lib/extensions/lettering_along_path.py b/lib/extensions/lettering_along_path.py
index 608479be..10e62dd6 100644
--- a/lib/extensions/lettering_along_path.py
+++ b/lib/extensions/lettering_along_path.py
@@ -6,7 +6,7 @@
import json
from math import atan2, degrees
-from inkex import Boolean, Transform, errormsg
+from inkex import Transform, errormsg
from inkex.units import convert_unit
from ..elements import Stroke
@@ -26,7 +26,7 @@ class LetteringAlongPath(InkstitchExtension):
def __init__(self, *args, **kwargs):
InkstitchExtension.__init__(self, *args, **kwargs)
self.arg_parser.add_argument("--notebook")
- self.arg_parser.add_argument("-s", "--stretch-spaces", type=Boolean, default=False, dest="stretch_spaces")
+ self.arg_parser.add_argument("-p", "--text-position", type=str, default='left', dest="text_position")
def effect(self):
# we ignore everything but the first path/text
@@ -35,32 +35,70 @@ class LetteringAlongPath(InkstitchExtension):
errormsg(_("Please select one path and one Ink/Stitch lettering group."))
return
- glyphs = [glyph for glyph in text.iterdescendants(SVG_GROUP_TAG) if glyph.label and len(glyph.label) == 1]
- if not glyphs:
+ TextAlongPath(self.svg, text, path, self.options.text_position)
+
+ def get_selection(self):
+ groups = list()
+ paths = list()
+
+ for node in self.svg.selection:
+ lettering = False
+ if node.tag == SVG_GROUP_TAG and INKSTITCH_LETTERING in node.attrib:
+ groups.append(node)
+ lettering = True
+ continue
+
+ for group in node.iterancestors(SVG_GROUP_TAG):
+ if INKSTITCH_LETTERING in group.attrib:
+ groups.append(group)
+ lettering = True
+ break
+
+ if not lettering and node.tag in EMBROIDERABLE_TAGS:
+ paths.append(node)
+
+ if not groups or not paths:
+ return [None, None]
+
+ return [groups[0], paths[0]]
+
+
+class TextAlongPath:
+ '''
+ Aligns an Ink/Stitch Lettering group along a path
+ '''
+ def __init__(self, svg, text, path, text_position):
+ self.svg = svg
+ self.text = text
+ self.path = Stroke(path).as_multi_line_string().geoms[0]
+ self.text_position = text_position
+
+ self.glyphs = [glyph for glyph in self.text.iterdescendants(SVG_GROUP_TAG) if glyph.label and len(glyph.label) == 1]
+ if not self.glyphs:
errormsg(_("The text doesn't contain any glyphs."))
return
- self.load_settings(text)
+ self.load_settings()
- if glyphs[0].get('transform', None) is not None:
- glyphs = self._reset_glyph_transforms(text, glyphs)
+ if self.glyphs[0].get('transform', None) is not None:
+ self._reset_glyph_transforms()
- path = Stroke(path).as_multi_line_string().geoms[0]
- hidden_commands = self.hide_commands(glyphs)
- space_indices, stretch_space, text_baseline = self.get_position_and_stretch_values(path, text, glyphs)
- self.transform_glyphs(glyphs, path, stretch_space, space_indices, text_baseline)
+ hidden_commands = self.hide_commands()
+ space_indices, stretch_space, text_baseline = self.get_position_and_stretch_values()
+ start_position = self.get_start_position()
+ self.transform_glyphs(start_position, stretch_space, space_indices, text_baseline)
self.restore_commands(hidden_commands)
- def _reset_glyph_transforms(self, text_group, glyphs):
+ def _reset_glyph_transforms(self):
font = get_font_by_id(self.settings.font)
if font is not None:
try:
- text_group = list(text_group.iterchildren(SVG_GROUP_TAG))[0]
+ text_group = list(self.text.iterchildren(SVG_GROUP_TAG))[0]
except IndexError:
pass
for glyph in text_group.iterchildren():
text_group.remove(glyph)
- text = font.render_text(
+ rendered_text = font.render_text(
self.settings.text,
text_group,
None, # we don't know the font variant (?)
@@ -68,21 +106,30 @@ class LetteringAlongPath(InkstitchExtension):
self.settings.trim_option,
self.settings.use_trim_symbols
)
- return [glyph for glyph in text.iterdescendants(SVG_GROUP_TAG) if glyph.label and len(glyph.label) == 1]
- return glyphs
-
- def get_position_and_stretch_values(self, path, text, glyphs):
- text_bbox = glyphs[0].getparent().bounding_box()
+ self.glyphs = [glyph for glyph in rendered_text.iterdescendants(SVG_GROUP_TAG) if glyph.label and len(glyph.label) == 1]
+
+ def get_start_position(self):
+ start_position = 0
+ text_length = self.text_length()
+ path_length = self.path.length
+ if self.text_position == 'center':
+ start_position = (path_length - text_length) / 2
+ if self.text_position == 'right':
+ start_position = path_length - text_length
+ return start_position
+
+ def get_position_and_stretch_values(self):
+ text_bbox = self.glyphs[0].getparent().bounding_box()
text_baseline = text_bbox.bottom
- if self.options.stretch_spaces:
- text_content = self.settings["text"]
+ if self.text_position == 'stretch':
+ text_content = self.settings.text
space_indices = [i for i, t in enumerate(text_content) if t == " "]
- text_bbox = text.bounding_box()
+ text_bbox = self.text.bounding_box()
text_width = convert_unit(text_bbox.width, 'px', self.svg.unit)
if len(text_content) - 1 != 0:
- path_length = path.length
+ path_length = self.path.length
stretch_space = (path_length - text_width) / (len(text_content) - 1)
else:
stretch_space = 0
@@ -92,10 +139,13 @@ class LetteringAlongPath(InkstitchExtension):
return space_indices, stretch_space, text_baseline
- def hide_commands(self, glyphs):
+ def text_length(self):
+ return convert_unit(self.text.bounding_box().width, 'px', self.svg.unit)
+
+ def hide_commands(self):
# hide commmands for bounding box calculation
hidden_commands = []
- for glyph in glyphs:
+ for glyph in self.glyphs:
for group in glyph.iterdescendants(SVG_GROUP_TAG):
if group.get_id().startswith("command_group") and group.style('display', 'inline') != 'none':
hidden_commands.append(group)
@@ -106,13 +156,13 @@ class LetteringAlongPath(InkstitchExtension):
for command in hidden_commands:
command.style['display'] = "inline"
- def transform_glyphs(self, glyphs, path, stretch_space, space_indices, text_baseline):
+ def transform_glyphs(self, start_position, stretch_space, space_indices, text_baseline):
text_scale = Transform(f'scale({self.settings.scale / 100})')
- distance = 0
+ distance = start_position
old_bbox = None
i = 0
- for glyph in glyphs:
+ for glyph in self.glyphs:
# dimensions
bbox = glyph.bounding_box()
transformed_bbox = glyph.bounding_box(glyph.getparent().composed_transform())
@@ -124,15 +174,15 @@ class LetteringAlongPath(InkstitchExtension):
if old_bbox:
distance += convert_unit(transformed_left - old_bbox.right, 'px', self.svg.unit) + stretch_space
- if self.options.stretch_spaces and i in space_indices:
+ if self.text_position == 'stretch' and i in space_indices:
distance += stretch_space
i += 1
new_distance = distance + width
# calculate and apply transform
- first = path.interpolate(distance)
- last = path.interpolate(new_distance)
+ first = self.path.interpolate(distance)
+ last = self.path.interpolate(new_distance)
angle = degrees(atan2(last.y - first.y, last.x - first.x)) % 360
translate = InkstitchPoint(first.x, first.y) - InkstitchPoint(left, text_baseline)
@@ -146,7 +196,7 @@ class LetteringAlongPath(InkstitchExtension):
old_bbox = transformed_bbox
i += 1
- def load_settings(self, text):
+ def load_settings(self):
"""Load the settings saved into the text element"""
self.settings = DotDict({
@@ -158,33 +208,8 @@ class LetteringAlongPath(InkstitchExtension):
"use_trim_symbols": False
})
- if INKSTITCH_LETTERING in text.attrib:
+ if INKSTITCH_LETTERING in self.text.attrib:
try:
- self.settings.update(json.loads(text.get(INKSTITCH_LETTERING)))
+ self.settings.update(json.loads(self.text.get(INKSTITCH_LETTERING)))
except (TypeError, ValueError):
pass
-
- def get_selection(self):
- groups = list()
- paths = list()
-
- for node in self.svg.selection:
- lettering = False
- if node.tag == SVG_GROUP_TAG and INKSTITCH_LETTERING in node.attrib:
- groups.append(node)
- lettering = True
- continue
-
- for group in node.iterancestors(SVG_GROUP_TAG):
- if INKSTITCH_LETTERING in group.attrib:
- groups.append(group)
- lettering = True
- break
-
- if not lettering and node.tag in EMBROIDERABLE_TAGS:
- paths.append(node)
-
- if not groups or not paths:
- return [None, None]
-
- return [groups[0], paths[0]]