summaryrefslogtreecommitdiff
path: root/lib/extensions/lettering.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/extensions/lettering.py')
-rw-r--r--lib/extensions/lettering.py82
1 files changed, 45 insertions, 37 deletions
diff --git a/lib/extensions/lettering.py b/lib/extensions/lettering.py
index d988778d..ee0dd9a0 100644
--- a/lib/extensions/lettering.py
+++ b/lib/extensions/lettering.py
@@ -1,14 +1,12 @@
-# -*- coding: UTF-8 -*-
-
import json
import os
import sys
-from base64 import b64decode, b64encode
import appdirs
import inkex
import wx
import wx.adv
+from lxml import etree
from ..elements import nodes_to_elements
from ..gui import PresetsPanel, SimulatorPreview, info_dialog
@@ -19,6 +17,7 @@ from ..svg.tags import (INKSCAPE_LABEL, INKSTITCH_LETTERING, SVG_GROUP_TAG,
SVG_PATH_TAG)
from ..utils import DotDict, cache, get_bundled_dir
from .commands import CommandsExtension
+from .lettering_custom_font_dir import get_custom_font_dir
class LetteringFrame(wx.Frame):
@@ -45,6 +44,7 @@ class LetteringFrame(wx.Frame):
# font details
self.font_description = wx.StaticText(self, wx.ID_ANY)
+ self.Bind(wx.EVT_SIZE, self.resize)
# options
self.options_box = wx.StaticBox(self, wx.ID_ANY, label=_("Options"))
@@ -80,7 +80,7 @@ class LetteringFrame(wx.Frame):
"""Load the settings saved into the SVG group element"""
self.settings = DotDict({
- "text": u"",
+ "text": "",
"back_and_forth": False,
"font": None,
"scale": 100
@@ -88,7 +88,7 @@ class LetteringFrame(wx.Frame):
try:
if INKSTITCH_LETTERING in self.group.attrib:
- self.settings.update(json.loads(b64decode(self.group.get(INKSTITCH_LETTERING))))
+ self.settings.update(json.loads(self.group.get(INKSTITCH_LETTERING)))
return
except (TypeError, ValueError):
pass
@@ -103,22 +103,14 @@ class LetteringFrame(wx.Frame):
def save_settings(self):
"""Save the settings into the SVG group element."""
-
- # We base64 encode the string before storing it in an XML attribute.
- # In theory, lxml should properly html-encode the string, using HTML
- # entities like 
 as necessary. However, we've found that Inkscape
- # incorrectly interpolates the HTML entities upon reading the
- # extension's output, rather than leaving them as is.
- #
- # Details:
- # https://bugs.launchpad.net/inkscape/+bug/1804346
- self.group.set(INKSTITCH_LETTERING, b64encode(json.dumps(self.settings)))
+ self.group.set(INKSTITCH_LETTERING, json.dumps(self.settings))
def update_font_list(self):
font_paths = {
get_bundled_dir("fonts"),
os.path.expanduser("~/.inkstitch/fonts"),
os.path.join(appdirs.user_config_dir('inkstitch'), 'fonts'),
+ get_custom_font_dir()
}
self.fonts = {}
@@ -130,13 +122,12 @@ class LetteringFrame(wx.Frame):
except OSError:
continue
- try:
- for font_dir in font_dirs:
- font = Font(os.path.join(font_path, font_dir))
- self.fonts[font.name] = font
- self.fonts_by_id[font.id] = font
- except FontError:
- pass
+ for font_dir in font_dirs:
+ font = Font(os.path.join(font_path, font_dir))
+ if font.name == "" or font.id == "":
+ continue
+ self.fonts[font.name] = font
+ self.fonts_by_id[font.id] = font
if len(self.fonts) == 0:
info_dialog(self, _("Unable to find any fonts! Please try reinstalling Ink/Stitch."))
@@ -165,13 +156,13 @@ class LetteringFrame(wx.Frame):
self.font_chooser.Append(font.name)
def get_font_names(self):
- font_names = [font.name for font in self.fonts.itervalues()]
+ font_names = [font.name for font in self.fonts.values()]
font_names.sort()
return font_names
def get_font_descriptions(self):
- return {font.name: font.description for font in self.fonts.itervalues()}
+ return {font.name: font.description for font in self.fonts.values()}
def set_initial_font(self, font_id):
if font_id:
@@ -191,7 +182,7 @@ class LetteringFrame(wx.Frame):
try:
return self.fonts_by_id[self.DEFAULT_FONT]
except KeyError:
- return self.fonts.values()[0]
+ return list(self.fonts.values())[0]
def on_change(self, attribute, event):
self.settings[attribute] = event.GetEventObject().GetValue()
@@ -202,7 +193,11 @@ class LetteringFrame(wx.Frame):
self.settings.font = font.id
self.scale_spinner.SetRange(int(font.min_scale * 100), int(font.max_scale * 100))
- font_variants = font.has_variants()
+ font_variants = []
+ try:
+ font_variants = font.has_variants()
+ except FontError:
+ pass
# Update font description
color = (0, 0, 0)
@@ -212,7 +207,7 @@ class LetteringFrame(wx.Frame):
description = _('This font has no available font variant. Please update or remove the font.')
self.font_description.SetLabel(description)
self.font_description.SetForegroundColour(color)
- self.font_description.Wrap(self.GetSize().width - 20)
+ self.font_description.Wrap(self.GetSize().width - 35)
if font.reversible:
self.back_and_forth_checkbox.Enable()
@@ -230,18 +225,24 @@ class LetteringFrame(wx.Frame):
self.trim_checkbox.SetValue(False)
self.update_preview()
- self.GetSizer().Layout()
+ self.Layout()
+
+ def resize(self, event=None):
+ description = self.font_description.GetLabel().replace("\n", " ")
+ self.font_description.SetLabel(description)
+ self.font_description.Wrap(self.GetSize().width - 35)
+ self.Layout()
def update_preview(self, event=None):
self.preview.update()
- def update_lettering(self):
+ def update_lettering(self, raise_error=False):
del self.group[:]
if self.settings.scale == 100:
destination_group = self.group
else:
- destination_group = inkex.etree.SubElement(self.group, SVG_GROUP_TAG, {
+ destination_group = etree.SubElement(self.group, SVG_GROUP_TAG, {
# L10N The user has chosen to scale the text by some percentage
# (50%, 200%, etc). If you need to use the percentage symbol,
# make sure to double it (%%).
@@ -249,7 +250,14 @@ class LetteringFrame(wx.Frame):
})
font = self.fonts.get(self.font_chooser.GetValue(), self.default_font)
- font.render_text(self.settings.text, destination_group, back_and_forth=self.settings.back_and_forth, trim=self.settings.trim)
+ try:
+ font.render_text(self.settings.text, destination_group, back_and_forth=self.settings.back_and_forth, trim=self.settings.trim)
+ except FontError as e:
+ if raise_error:
+ inkex.errormsg("Error: Text cannot be applied to the document.\n%s" % e)
+ return
+ else:
+ pass
if self.settings.scale != 100:
destination_group.attrib['transform'] = 'scale(%s)' % (self.settings.scale / 100.0)
@@ -295,7 +303,7 @@ class LetteringFrame(wx.Frame):
def apply(self, event):
self.preview.disable()
- self.update_lettering()
+ self.update_lettering(True)
self.save_settings()
self.close()
@@ -369,10 +377,10 @@ class Lettering(CommandsExtension):
self.cancelled = True
def get_or_create_group(self):
- if self.selected:
+ if self.svg.selected:
groups = set()
- for node in self.selected.itervalues():
+ for node in self.svg.selected.values():
if node.tag == SVG_GROUP_TAG and INKSTITCH_LETTERING in node.attrib:
groups.add(node)
@@ -391,9 +399,9 @@ class Lettering(CommandsExtension):
return list(groups)[0]
else:
self.ensure_current_layer()
- return inkex.etree.SubElement(self.current_layer, SVG_GROUP_TAG, {
+ return etree.SubElement(self.svg.get_current_layer(), SVG_GROUP_TAG, {
INKSCAPE_LABEL: _("Ink/Stitch Lettering"),
- "transform": get_correction_transform(self.current_layer, child=True)
+ "transform": get_correction_transform(self.svg.get_current_layer(), child=True)
})
def effect(self):
@@ -405,7 +413,7 @@ class Lettering(CommandsExtension):
display = wx.Display(current_screen)
display_size = display.GetClientArea()
frame_size = frame.GetSize()
- frame.SetPosition((display_size[0], display_size[3] / 2 - frame_size[1] / 2))
+ frame.SetPosition((int(display_size[0]), int(display_size[3] / 2 - frame_size[1] / 2)))
frame.Show()
app.MainLoop()