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:
 | |
|                 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)
 |