kopia lustrzana https://github.com/inkstitch/inkstitch
127 wiersze
4.7 KiB
Python
127 wiersze
4.7 KiB
Python
# Authors: see git history
|
|
#
|
|
# Copyright (c) 2010 Authors
|
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
|
|
|
from copy import copy
|
|
|
|
from inkex import paths, transforms, units
|
|
|
|
from ..svg import get_correction_transform, get_guides
|
|
from ..svg.tags import (CONNECTION_END, SVG_GROUP_TAG, SVG_PATH_TAG,
|
|
SVG_USE_TAG, XLINK_HREF)
|
|
|
|
|
|
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()
|
|
self._process_commands()
|
|
|
|
def _process_group(self, group):
|
|
new_group = copy(group)
|
|
# new_group.attrib.pop('transform', None)
|
|
# delete references to the original group's children
|
|
del new_group[:]
|
|
|
|
for node in group:
|
|
if node.tag == SVG_GROUP_TAG:
|
|
new_group.append(self._process_group(node))
|
|
else:
|
|
node_copy = copy(node)
|
|
transform = -transforms.Transform(get_correction_transform(node, True))
|
|
|
|
if "d" in node.attrib:
|
|
node_copy.path = node.path.transform(transform).to_absolute()
|
|
|
|
if not node.tag == SVG_USE_TAG:
|
|
# Delete transforms from paths and groups, since we applied
|
|
# them to the paths already.
|
|
node_copy.attrib.pop('transform', None)
|
|
else:
|
|
oldx = node.get('x', 0)
|
|
oldy = node.get('y', 0)
|
|
x, y = transform.apply_to_point((oldx, oldy))
|
|
node_copy.set('x', x)
|
|
node_copy.set('y', y)
|
|
|
|
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):
|
|
bbox = [paths.Path(node.get("d")).bounding_box() for node in self.node.iterdescendants(SVG_PATH_TAG) if not node.get(CONNECTION_END, None)]
|
|
left, right = min([box.left for box in bbox]), max([box.right for box in bbox])
|
|
self.width = right - left
|
|
self.min_x = left
|
|
|
|
def _process_commands(self):
|
|
# Save object ids with commands in a dictionary: {object_id: [connector_id, symbol_id]}
|
|
self.commands = {}
|
|
|
|
for node in self.node.iter(SVG_USE_TAG):
|
|
xlink = node.get(XLINK_HREF, ' ')
|
|
if not xlink.startswith('#inkstitch_'):
|
|
continue
|
|
|
|
try:
|
|
connector = self.node.xpath(".//*[@inkscape:connection-start='#%s']" % node.get('id', ' '))[0]
|
|
command_object = connector.get(CONNECTION_END)[1:]
|
|
try:
|
|
self.commands[command_object].append([connector.get_id(), node.get_id()])
|
|
except KeyError:
|
|
self.commands[command_object] = [[connector.get_id(), node.get_id()]]
|
|
except (IndexError, TypeError):
|
|
pass
|
|
|
|
def _move_to_origin(self):
|
|
translate_x = -self.min_x
|
|
translate_y = -self.baseline
|
|
transform = transforms.Transform("translate(%s, %s)" % (translate_x, translate_y))
|
|
|
|
for node in self.node.iter(SVG_PATH_TAG):
|
|
path = paths.Path(node.get("d"))
|
|
path = path.transform(transform)
|
|
node.set('d', str(path))
|
|
node.attrib.pop('transform', None)
|
|
|
|
# Move commands as well
|
|
for node in self.node.iter(SVG_USE_TAG):
|
|
oldx = units.convert_unit(node.get("x", 0), 'px', node.unit)
|
|
oldy = units.convert_unit(node.get("y", 0), 'px', node.unit)
|
|
x, y = transform.apply_to_point((oldx, oldy))
|
|
node.set('x', x)
|
|
node.set('y', y)
|