summaryrefslogtreecommitdiff
path: root/lib/lettering/glyph.py
diff options
context:
space:
mode:
authorLex Neva <lexelby@users.noreply.github.com>2018-11-14 20:23:06 -0500
committerGitHub <noreply@github.com>2018-11-14 20:23:06 -0500
commitf5c85183d9c874fca806917e50992daea4101496 (patch)
treea2450e2e37a7d94625a917240e78eadc939fd65b /lib/lettering/glyph.py
parent238ad843dd658de6c7afd5b8697c0e080b1cf965 (diff)
basic lettering (#344)
Can handle multiple lines of text and routes the stitching in alternating directions on each line.
Diffstat (limited to 'lib/lettering/glyph.py')
-rw-r--r--lib/lettering/glyph.py86
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/lettering/glyph.py b/lib/lettering/glyph.py
new file mode 100644
index 00000000..bb1a971c
--- /dev/null
+++ b/lib/lettering/glyph.py
@@ -0,0 +1,86 @@
+from copy import copy
+
+import cubicsuperpath
+import simpletransform
+
+from ..svg import apply_transforms, get_guides
+from ..svg.tags import SVG_GROUP_TAG, SVG_PATH_TAG
+
+
+class Glyph(object):
+ """Represents a single character in a single font variant.
+
+ For example, the font inkstitch_small may have variants for left-to-right,
+ right-to-left, etc. Each variant would have a set of Glyphs, one for each
+ character in that variant.
+
+ Properties:
+ width -- total width of this glyph including all component satins
+ node -- svg:g XML node containing the component satins in this character
+ """
+
+ def __init__(self, group):
+ """Create a Glyph.
+
+ The nodes will be copied out of their parent SVG document (with nested
+ transforms applied). The original nodes will be unmodified.
+
+ Arguments:
+ group -- an svg:g XML node containing all the paths that make up
+ this Glyph. Nested groups are allowed.
+ """
+
+ self._process_baseline(group.getroottree().getroot())
+ self.node = self._process_group(group)
+ self._process_bbox()
+ self._move_to_origin()
+
+ def _process_group(self, group):
+ new_group = copy(group)
+ new_group.attrib.pop('transform', None)
+ del new_group[:] # delete references to the original group's children
+
+ for node in group:
+ if node.tag == SVG_GROUP_TAG:
+ new_group.append(self._process_group(node))
+ else:
+ node_copy = copy(node)
+
+ if "d" in node.attrib:
+ # Convert the path to absolute coordinates, incorporating all
+ # nested transforms.
+ path = cubicsuperpath.parsePath(node.get("d"))
+ apply_transforms(path, node)
+ node_copy.set("d", cubicsuperpath.formatPath(path))
+
+ # Delete transforms from paths and groups, since we applied
+ # them to the paths already.
+ node_copy.attrib.pop('transform', None)
+
+ new_group.append(node_copy)
+
+ return new_group
+
+ def _process_baseline(self, svg):
+ for guide in get_guides(svg):
+ if guide.label == "baseline":
+ self._baseline = guide.position.y
+ break
+ else:
+ # no baseline guide found, assume 0 for lack of anything better to use...
+ self._baseline = 0
+
+ def _process_bbox(self):
+ left, right, top, bottom = simpletransform.computeBBox(self.node.iterdescendants())
+
+ self.width = right - left
+ self._min_x = left
+
+ def _move_to_origin(self):
+ translate_x = -self._min_x
+ translate_y = -self._baseline
+ transform = "translate(%s, %s)" % (translate_x, translate_y)
+
+ for node in self.node.iter(SVG_PATH_TAG):
+ node.set('transform', transform)
+ simpletransform.fuseTransform(node)