# Authors: see git history # # Copyright (c) 2021 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. import inkex from shapely.geometry import Point from ..i18n import _ from ..svg import PIXELS_PER_MM from ..svg.tags import INKSTITCH_ATTRIBS from .base import InkstitchExtension class LetteringForceLockStitches(InkstitchExtension): ''' This extension helps font creators to add the force lock stitches attribute to the last objects of each glyph Font creators to add forced lock stitches on glyphs with accents / spaces. ''' def __init__(self, *args, **kwargs): InkstitchExtension.__init__(self, *args, **kwargs) self.arg_parser.add_argument("-s", "--satin_only", type=inkex.Boolean, dest="satin_only") self.arg_parser.add_argument("-a", "--max_distance", type=float, default=3, dest="max_distance") self.arg_parser.add_argument("-i", "--min_distance", type=float, default=1, dest="min_distance") self.arg_parser.add_argument("-l", "--last_element", type=inkex.Boolean, dest="last_element") def effect(self): if self.options.max_distance < self.options.min_distance: inkex.errormssg(_("The maximum value is smaller than the minimum value.")) # Set glyph layers to be visible. We don't want them to be ignored by self.elements self._update_layer_visibility('inline') # mark last elements of a glyph xpath = ".//svg:g[@inkscape:groupmode='layer']//svg:path[last()]" last_elements = self.document.xpath(xpath, namespaces=inkex.NSS) for last_element in last_elements: last_element.set('lastglyphelement', str(True)) # find last point of an element if not self.get_elements(): return previous_element = None last_stitch = None for element in self.elements: stitch_group = element.to_stitch_groups(None) # if the distance of the last stitch of the previous object to the first stitch of this objects # lies within the user defined distance range, set the force_lock_stitches-attribute. if last_stitch: first_stitch = stitch_group[0].stitches[0] first_stitch = Point(first_stitch.x, first_stitch.y) self._set_force_attribute(first_stitch, last_stitch, previous_element) # if this is the last element of a glyph, we don't want to compare it to the next element if element.node.get('lastglyphelement', False): previous_element = None last_stitch = None else: previous_element = element last_stitch = stitch_group[-1].stitches[-1] last_stitch = Point(last_stitch.x, last_stitch.y) # remove last element attributes again # set force lock stitches attribute if needed for last_element in last_elements: last_element.attrib.pop('lastglyphelement') if self.options.last_element and not (self.options.satin_only and not last_element.get('inkstitch:satin_column', False)): last_element.set(INKSTITCH_ATTRIBS['force_lock_stitches'], True) # hide glyph layers again self._update_layer_visibility('none') def _set_force_attribute(self, first_stitch, last_stitch, previous_element): distance_mm = first_stitch.distance(last_stitch) / PIXELS_PER_MM if (distance_mm < self.options.max_distance and distance_mm > self.options.min_distance and not (self.options.satin_only and not previous_element.get_boolean_param('satin_column', False))): previous_element.node.set(INKSTITCH_ATTRIBS['force_lock_stitches'], True) def _update_layer_visibility(self, display): xpath = ".//svg:g[@inkscape:groupmode='layer']" layers = self.document.xpath(xpath, namespaces=inkex.NSS) for layer in layers: display_style = 'display:%s' % display style = inkex.Style(layer.get('style', '')) + inkex.Style(display_style) layer.set('style', style)