diff options
Diffstat (limited to 'lib/__init__.py')
| -rw-r--r-- | lib/__init__.py | 298 |
1 files changed, 0 insertions, 298 deletions
diff --git a/lib/__init__.py b/lib/__init__.py index 2c0ee620..e69de29b 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,298 +0,0 @@ -#!/usr/bin/env python -# http://www.achatina.de/sewing/main/TECHNICL.HTM - -import os -import sys -import gettext -from copy import deepcopy -import math -import libembroidery -from .utils import cache -from .utils.geometry import Point - -import inkex -import simplepath -import simplestyle -import simpletransform -from bezmisc import bezierlength, beziertatlength, bezierpointatt -from cspsubdiv import cspsubdiv -import cubicsuperpath -from shapely import geometry as shgeo - - -# modern versions of Inkscape use 96 pixels per inch as per the CSS standard -PIXELS_PER_MM = 96 / 25.4 - -SVG_PATH_TAG = inkex.addNS('path', 'svg') -SVG_POLYLINE_TAG = inkex.addNS('polyline', 'svg') -SVG_DEFS_TAG = inkex.addNS('defs', 'svg') -SVG_GROUP_TAG = inkex.addNS('g', 'svg') -INKSCAPE_LABEL = inkex.addNS('label', 'inkscape') -INKSCAPE_GROUPMODE = inkex.addNS('groupmode', 'inkscape') - -EMBROIDERABLE_TAGS = (SVG_PATH_TAG, SVG_POLYLINE_TAG) - -dbg = open(os.devnull, "w") - -translation = None -_ = lambda message: message - - -def localize(): - if getattr(sys, 'frozen', False): - # we are in a pyinstaller installation - locale_dir = sys._MEIPASS - else: - locale_dir = os.path.dirname(__file__) - - locale_dir = os.path.join(locale_dir, 'locales') - - global translation, _ - - translation = gettext.translation("inkstitch", locale_dir, fallback=True) - _ = translation.gettext - -localize() - -# cribbed from inkscape-silhouette -def parse_length_with_units( str ): - - ''' - Parse an SVG value which may or may not have units attached - This version is greatly simplified in that it only allows: no units, - units of px, mm, and %. Everything else, it returns None for. - There is a more general routine to consider in scour.py if more - generality is ever needed. - ''' - - u = 'px' - s = str.strip() - if s[-2:] == 'px': - s = s[:-2] - elif s[-2:] == 'mm': - u = 'mm' - s = s[:-2] - elif s[-2:] == 'pt': - u = 'pt' - s = s[:-2] - elif s[-2:] == 'pc': - u = 'pc' - s = s[:-2] - elif s[-2:] == 'cm': - u = 'cm' - s = s[:-2] - elif s[-2:] == 'in': - u = 'in' - s = s[:-2] - elif s[-1:] == '%': - u = '%' - s = s[:-1] - try: - v = float( s ) - except: - raise ValueError(_("parseLengthWithUnits: unknown unit %s") % s) - - return v, u - - -def convert_length(length): - value, units = parse_length_with_units(length) - - if not units or units == "px": - return value - - if units == 'pt': - value /= 72 - units = 'in' - - if units == 'pc': - value /= 6 - units = 'in' - - if units == 'cm': - value *= 10 - units = 'mm' - - if units == 'mm': - value = value / 25.4 - units = 'in' - - if units == 'in': - # modern versions of Inkscape use CSS's 96 pixels per inch. When you - # open an old document, inkscape will add a viewbox for you. - return value * 96 - - raise ValueError(_("Unknown unit: %s") % units) - - -@cache -def get_doc_size(svg): - doc_width = convert_length(svg.get('width')) - doc_height = convert_length(svg.get('height')) - - return doc_width, doc_height - -@cache -def get_viewbox_transform(node): - # somewhat cribbed from inkscape-silhouette - doc_width, doc_height = get_doc_size(node) - - viewbox = node.get('viewBox').strip().replace(',', ' ').split() - - dx = -float(viewbox[0]) - dy = -float(viewbox[1]) - transform = simpletransform.parseTransform("translate(%f, %f)" % (dx, dy)) - - try: - sx = doc_width / float(viewbox[2]) - sy = doc_height / float(viewbox[3]) - scale_transform = simpletransform.parseTransform("scale(%f, %f)" % (sx, sy)) - transform = simpletransform.composeTransform(transform, scale_transform) - except ZeroDivisionError: - pass - - return transform - -@cache -def get_stroke_scale(node): - doc_width, doc_height = get_doc_size(node) - viewbox = node.get('viewBox').strip().replace(',', ' ').split() - return doc_width / float(viewbox[2]) - - -class Stitch(Point): - def __init__(self, x, y, color=None, jump=False, stop=False, trim=False, no_ties=False): - self.x = x - self.y = y - self.color = color - self.jump = jump - self.trim = trim - self.stop = stop - self.no_ties = no_ties - - def __repr__(self): - return "Stitch(%s, %s, %s, %s, %s, %s, %s)" % (self.x, self.y, self.color, "JUMP" if self.jump else " ", "TRIM" if self.trim else " ", "STOP" if self.stop else " ", "NO TIES" if self.no_ties else " ") - - -def make_thread(color): - thread = libembroidery.EmbThread() - thread.color = libembroidery.embColor_make(*color.rgb) - - thread.description = color.name - thread.catalogNumber = "" - - return thread - -def add_thread(pattern, thread): - """Add a thread to a pattern and return the thread's index""" - - libembroidery.embPattern_addThread(pattern, thread) - - return libembroidery.embThreadList_count(pattern.threadList) - 1 - -def get_flags(stitch): - flags = 0 - - if stitch.jump: - flags |= libembroidery.JUMP - - if stitch.trim: - flags |= libembroidery.TRIM - - if stitch.stop: - flags |= libembroidery.STOP - - return flags - - -def _string_to_floats(string): - floats = string.split(',') - return [float(num) for num in floats] - - -def get_origin(svg): - # The user can specify the embroidery origin by defining two guides - # named "embroidery origin" that intersect. - - namedview = svg.find(inkex.addNS('namedview', 'sodipodi')) - all_guides = namedview.findall(inkex.addNS('guide', 'sodipodi')) - label_attribute = inkex.addNS('label', 'inkscape') - guides = [guide for guide in all_guides - if guide.get(label_attribute, "").startswith("embroidery origin")] - - # document size used below - doc_size = list(get_doc_size(svg)) - - # convert the size from viewbox-relative to real-world pixels - viewbox_transform = get_viewbox_transform(svg) - simpletransform.applyTransformToPoint(simpletransform.invertTransform(viewbox_transform), doc_size) - - default = [doc_size[0] / 2.0, doc_size[1] / 2.0] - simpletransform.applyTransformToPoint(viewbox_transform, default) - default = Point(*default) - - if len(guides) < 2: - return default - - # Find out where the guides intersect. Only pay attention to the first two. - guides = guides[:2] - - lines = [] - for guide in guides: - # inkscape's Y axis is reversed from SVG's, and the guide is in inkscape coordinates - position = Point(*_string_to_floats(guide.get('position'))) - position.y = doc_size[1] - position.y - - - # This one baffles me. I think inkscape might have gotten the order of - # their vector wrong? - parts = _string_to_floats(guide.get('orientation')) - direction = Point(parts[1], parts[0]) - - # We have a theoretically infinite line defined by a point on the line - # and a vector direction. Shapely can only deal in concrete line - # segments, so we'll pick points really far in either direction on the - # line and call it good enough. - lines.append(shgeo.LineString((position + 100000 * direction, position - 100000 * direction))) - - intersection = lines[0].intersection(lines[1]) - - if isinstance(intersection, shgeo.Point): - origin = [intersection.x, intersection.y] - simpletransform.applyTransformToPoint(viewbox_transform, origin) - return Point(*origin) - else: - # Either the two guides are the same line, or they're parallel. - return default - - -def write_embroidery_file(file_path, stitch_plan, svg): - origin = get_origin(svg) - - pattern = libembroidery.embPattern_create() - - for color_block in stitch_plan: - add_thread(pattern, make_thread(color_block.color)) - - for stitch in color_block: - if stitch.stop and stitch is not color_block.last_stitch: - # A STOP stitch that is not at the end of a color block - # occurs when the user specified "STOP after". "STOP" is the - # same thing as a color change, and the user will assign a - # special color at the machine that tells it to pause after. - # We need to add another copy of the same color here so that - # the stitches after the STOP are still the same color. - add_thread(pattern, make_thread(color_block.color)) - - flags = get_flags(stitch) - libembroidery.embPattern_addStitchAbs(pattern, stitch.x - origin.x, stitch.y - origin.y, flags, 1) - - libembroidery.embPattern_addStitchAbs(pattern, stitch.x - origin.x, stitch.y - origin.y, libembroidery.END, 1) - - # convert from pixels to millimeters - libembroidery.embPattern_scale(pattern, 1/PIXELS_PER_MM) - - # SVG and embroidery disagree on the direction of the Y axis - libembroidery.embPattern_flipVertical(pattern) - - libembroidery.embPattern_write(pattern, file_path) |
