kopia lustrzana https://github.com/inkstitch/inkstitch
v1.9.1: bug fixes
Lots of bug fixes: * properly handle case where stroke width is not set (defaults to 1 per SVG spec) * properly handle case where <svg> width and height not set (defaults to viewbox) * properly handle case where fill is not set (defaults to "black" rather than "none") * show error message (rather than crashing) if satin column set for a path with only one subpath * don't leave the simulate window around after "use last settings" * show a useful error message in Params if the user hasn't selected anything embroiderablepull/210/head v1.9.1
commit
28e8efebf2
|
@ -135,10 +135,10 @@ class EmbroideryElement(object):
|
|||
self.node.set("embroider_%s" % name, str(value))
|
||||
|
||||
@cache
|
||||
def get_style(self, style_name):
|
||||
def get_style(self, style_name, default=None):
|
||||
style = simplestyle.parseStyle(self.node.get("style"))
|
||||
if (style_name not in style):
|
||||
return None
|
||||
return default
|
||||
value = style[style_name]
|
||||
if value == 'none':
|
||||
return None
|
||||
|
@ -161,7 +161,7 @@ class EmbroideryElement(object):
|
|||
@property
|
||||
@cache
|
||||
def stroke_width(self):
|
||||
width = self.get_style("stroke-width")
|
||||
width = self.get_style("stroke-width", "1")
|
||||
|
||||
if width is None:
|
||||
return 1.0
|
||||
|
|
|
@ -27,7 +27,8 @@ class Fill(EmbroideryElement):
|
|||
|
||||
@property
|
||||
def color(self):
|
||||
return self.get_style("fill")
|
||||
# SVG spec says the default fill is black
|
||||
return self.get_style("fill", "#000000")
|
||||
|
||||
@property
|
||||
@param('flip', _('Flip fill (start right-to-left)'), type='boolean', default=False)
|
||||
|
|
|
@ -97,6 +97,8 @@ class SatinColumn(EmbroideryElement):
|
|||
def flattened_beziers(self):
|
||||
if len(self.csp) == 2:
|
||||
return self.simple_flatten_beziers()
|
||||
elif len(self.csp) < 2:
|
||||
self.fatal(_("satin column: %(id)s: at least two subpaths required (%(num)d found)") % dict(num=len(self.csp), id=self.node.get('id')))
|
||||
else:
|
||||
return self.flatten_beziers_with_rungs()
|
||||
|
||||
|
|
|
@ -57,10 +57,7 @@ class Stroke(EmbroideryElement):
|
|||
def is_running_stitch(self):
|
||||
# using stroke width <= 0.5 pixels to indicate running stitch is deprecated in favor of dashed lines
|
||||
|
||||
try:
|
||||
stroke_width = float(self.get_style("stroke-width"))
|
||||
except ValueError:
|
||||
stroke_width = 1
|
||||
stroke_width = float(self.get_style("stroke-width", 1))
|
||||
|
||||
if self.dashed:
|
||||
return True
|
||||
|
|
|
@ -111,7 +111,7 @@ class InkstitchExtension(inkex.Effect):
|
|||
inkex.errormsg(_("No embroiderable paths selected."))
|
||||
else:
|
||||
inkex.errormsg(_("No embroiderable paths found in document."))
|
||||
inkex.errormsg(_("Tip: use Path -> Object to Path to convert non-paths before embroidering."))
|
||||
inkex.errormsg(_("Tip: use Path -> Object to Path to convert non-paths."))
|
||||
|
||||
def descendants(self, node):
|
||||
nodes = []
|
||||
|
@ -158,7 +158,7 @@ class InkstitchExtension(inkex.Effect):
|
|||
else:
|
||||
classes = []
|
||||
|
||||
if element.get_style("fill"):
|
||||
if element.get_style("fill", "black"):
|
||||
if element.get_boolean_param("auto_fill", True):
|
||||
classes.append(AutoFill)
|
||||
else:
|
||||
|
|
|
@ -354,6 +354,9 @@ class SettingsFrame(wx.Frame):
|
|||
self.simulate_thread = None
|
||||
self.simulate_refresh_needed = Event()
|
||||
|
||||
# used when closing to avoid having the window reopen at the last second
|
||||
self.disable_simulate_window = False
|
||||
|
||||
wx.CallLater(1000, self.update_simulator)
|
||||
|
||||
self.presets_box = wx.StaticBox(self, wx.ID_ANY, label=_("Presets"))
|
||||
|
@ -392,6 +395,9 @@ class SettingsFrame(wx.Frame):
|
|||
self.simulate_window.stop()
|
||||
self.simulate_window.clear()
|
||||
|
||||
if self.disable_simulate_window:
|
||||
return
|
||||
|
||||
if not self.simulate_thread or not self.simulate_thread.is_alive():
|
||||
self.simulate_thread = Thread(target=self.simulate_worker)
|
||||
self.simulate_thread.daemon = True
|
||||
|
@ -586,6 +592,7 @@ class SettingsFrame(wx.Frame):
|
|||
self.close()
|
||||
|
||||
def use_last(self, event):
|
||||
self.disable_simulate_window = True
|
||||
self._load_preset("__LAST__")
|
||||
self.apply(event)
|
||||
|
||||
|
@ -632,6 +639,9 @@ class SettingsFrame(wx.Frame):
|
|||
self.Layout()
|
||||
# end wxGlade
|
||||
|
||||
class NoValidObjects(Exception):
|
||||
pass
|
||||
|
||||
class Params(InkstitchExtension):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.cancelled = False
|
||||
|
@ -689,6 +699,11 @@ class Params(InkstitchExtension):
|
|||
|
||||
def create_tabs(self, parent):
|
||||
tabs = []
|
||||
nodes_by_class = self.get_nodes_by_class()
|
||||
|
||||
if not nodes_by_class:
|
||||
raise NoValidObjects()
|
||||
|
||||
for cls, nodes in self.get_nodes_by_class():
|
||||
params = cls.get_params()
|
||||
|
||||
|
@ -745,12 +760,15 @@ class Params(InkstitchExtension):
|
|||
self.cancelled = True
|
||||
|
||||
def effect(self):
|
||||
app = wx.App()
|
||||
frame = SettingsFrame(tabs_factory=self.create_tabs, on_cancel=self.cancel)
|
||||
frame.Show()
|
||||
app.MainLoop()
|
||||
try:
|
||||
app = wx.App()
|
||||
frame = SettingsFrame(tabs_factory=self.create_tabs, on_cancel=self.cancel)
|
||||
frame.Show()
|
||||
app.MainLoop()
|
||||
|
||||
if self.cancelled:
|
||||
# This prevents the superclass from outputting the SVG, because we
|
||||
# may have modified the DOM.
|
||||
sys.exit(0)
|
||||
if self.cancelled:
|
||||
# This prevents the superclass from outputting the SVG, because we
|
||||
# may have modified the DOM.
|
||||
sys.exit(0)
|
||||
except NoValidObjects:
|
||||
self.no_elements_error()
|
||||
|
|
|
@ -75,11 +75,24 @@ def convert_length(length):
|
|||
|
||||
raise ValueError(_("Unknown unit: %s") % units)
|
||||
|
||||
@cache
|
||||
def get_viewbox(svg):
|
||||
return svg.get('viewBox').strip().replace(',', ' ').split()
|
||||
|
||||
|
||||
@cache
|
||||
def get_doc_size(svg):
|
||||
doc_width = convert_length(svg.get('width'))
|
||||
doc_height = convert_length(svg.get('height'))
|
||||
width = svg.get('width')
|
||||
height = svg.get('height')
|
||||
|
||||
if width is None or height is None:
|
||||
# fall back to the dimensions from the viewBox
|
||||
viewbox = get_viewbox(svg)
|
||||
width = viewbox[2]
|
||||
height = viewbox[3]
|
||||
|
||||
doc_width = convert_length(width)
|
||||
doc_height = convert_length(height)
|
||||
|
||||
return doc_width, doc_height
|
||||
|
||||
|
@ -88,7 +101,7 @@ 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()
|
||||
viewbox = get_viewbox(node)
|
||||
|
||||
dx = -float(viewbox[0])
|
||||
dy = -float(viewbox[1])
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2018-06-01 20:34-0400\n"
|
||||
"POT-Creation-Date: 2018-06-12 20:18-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -124,6 +124,10 @@ msgstr ""
|
|||
msgid "Inset amount (default: half of contour underlay inset)"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "satin column: %(id)s: at least two subpaths required (%(num)d found)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"One or more rails crosses itself, and this is not allowed. Please split "
|
||||
"into multiple satin columns."
|
||||
|
@ -181,7 +185,7 @@ msgstr ""
|
|||
msgid "No embroiderable paths found in document."
|
||||
msgstr ""
|
||||
|
||||
msgid "Tip: use Path -> Object to Path to convert non-paths before embroidering."
|
||||
msgid "Tip: use Path -> Object to Path to convert non-paths."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
|
|
Ładowanie…
Reference in New Issue