diff options
| author | Lex Neva <lexelby@users.noreply.github.com> | 2018-11-14 20:23:06 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-14 20:23:06 -0500 |
| commit | f5c85183d9c874fca806917e50992daea4101496 (patch) | |
| tree | a2450e2e37a7d94625a917240e78eadc939fd65b /lib/lettering/glyph.py | |
| parent | 238ad843dd658de6c7afd5b8697c0e080b1cf965 (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.py | 86 |
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) |
