diff options
| -rw-r--r-- | fonts/malika/←.svg | 46 | ||||
| -rw-r--r-- | lib/extensions/lettering_edit_json.py | 2 | ||||
| -rw-r--r-- | lib/gui/lettering/main_panel.py | 9 | ||||
| -rw-r--r-- | lib/gui/lettering_font_sample.py | 63 | ||||
| -rw-r--r-- | lib/lettering/font.py | 5 | ||||
| -rw-r--r-- | lib/lettering/font_variant.py | 7 |
6 files changed, 72 insertions, 60 deletions
diff --git a/fonts/malika/←.svg b/fonts/malika/←.svg index f8f3b30f..fdbbb4ff 100644 --- a/fonts/malika/←.svg +++ b/fonts/malika/←.svg @@ -4,7 +4,7 @@ id="svg7746" sodipodi:docname="←.svg" width="128" - inkscape:version="1.4-rc1 (61ec3f24, 2024-09-26)" + inkscape:version="1.4.2 (ebf0e940, 2025-05-08)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" @@ -19,13 +19,18 @@ inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" - inkscape:zoom="0.40290143" - inkscape:cx="438.07241" - inkscape:cy="173.73977" - inkscape:current-layer="layer3" + inkscape:zoom="5.3235418" + inkscape:cx="28.834187" + inkscape:cy="87.535707" + inkscape:current-layer="svg7746" showgrid="false" inkscape:lockguides="false" - showguides="true"> + showguides="true" + inkscape:window-width="1264" + inkscape:window-height="787" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="0"> <sodipodi:guide position="66.713521,25.414675" orientation="0.00014569138,0.99999999" @@ -48985,7 +48990,7 @@ Copyright 2010-2022 The Amiri Project Authors (https://github.com/aliftype/amiri <g inkscape:groupmode="layer" inkscape:label="GlyphLayer-ج.isol" - style="display:inline;fill:#ed171f" + style="display:none;fill:#ed171f" id="g8783-0"> <path d="m 35,120 q -12,7 -17,17 -5,10 -3,19 3,19 26,23 19,4 50,0 5,-1 6,2 0,2 -6,3 -5,2 -10,6 -5,4 -6,4 -1,1 -3,1 -38,5 -53,-8 -12,-10 -11,-30 2,-33 27,-48 -12,-2 -19,2 -1,1 -3,0 -1,-1 0,-3 0,-15 16,-15 1,0 4.5,0.5 Q 37,94 42,94 50,95 58.5,95.5 67,96 76,95 q 7,-1 5,3 l -4,8 q -1,3 -3,3 -23,2 -39,11 z m 12,20 q 1,-1 2,0 3,1 5.5,2 2.5,1 4.5,3 1,1 0,2 l -6,10 q -1,1 -2,0 -1,-1 -10,-5 -1,-1 0,-3 z" @@ -52284,11 +52289,7 @@ Copyright 2010-2022 The Amiri Project Authors (https://github.com/aliftype/amiri id="g1891-8-2" transform="translate(0.865931,-32.3281)"> <path - d="M 1,77 Q 1,71 4,68.5 7,66 13,67 l 8,2 q 3,1 4.5,1 H 28 q 3,0 4.5,-1 1.5,-1 2.5,-5 l 7,4 Q 39,81 28,81 h -4 q 0,0 -5,-1 l -9,-2 v 4 H 1 Z" - id="path168-5" - style="display:none;fill:#ed171f;fill-opacity:0.476351;stroke:none" /> - <path - style="display:none;fill:#ed171f;fill-rule:evenodd;stroke:none;stroke-width:1.00001;stroke-dasharray:2, 1;-inkscape-stroke:none" + style="display:inline;fill:none;fill-rule:evenodd;stroke:#ed171f;stroke-width:1.00001;stroke-dasharray:2, 1;-inkscape-stroke:none" d="M 20.854169,18.883582 46.265896,15.381301" id="path310-2" sodipodi:nodetypes="cc" @@ -52320,34 +52321,27 @@ Copyright 2010-2022 The Amiri Project Authors (https://github.com/aliftype/amiri inkscape:groupmode="layer" inkscape:label="GlyphLayer-؍" id="g1266" - style="font-variation-settings:normal;display:none;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ed171f;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"> - <path - d="m 36,70 -2,4 q -2,4 -5,4 -2,0 -3,-1 -2,-1 -6,3 Q 16,84 10,93 7,97 5,96 2,94 4,89 6,85 8.5,80.5 11,76 15,71 24,58 33,60 q 7,1 3,10 z" - id="path1266" - style="font-variation-settings:normal;display:inline;vector-effect:none;fill:none;fill-opacity:1;stroke:#ed171f;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" /> + style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ed171f;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:black;stop-opacity:1"> <path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ed171f;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2, 0.999999;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none" - d="M 32.596738,96.969487 C 33.364569,104.179 27.130173,49.731212 25.146336,56.482119" + d="M 6.9841716,91.868912 C 10.603937,87.067392 28.117381,67.391268 32.221328,65.860596" id="path484" sodipodi:nodetypes="cc" inkstitch:running_stitch_length_mm="2.5" inkstitch:min_stitch_length_mm=".50" inkstitch:min_jump_stitch_length_mm="3.00" /> <path - d="m 21.62354,34.258679 -2.395197,2.282997 c -2.210997,4.668594 -3.873495,9.620288 -5.785493,14.432482 -1.449598,3.189896 0.4218,6.509892 1.921198,9.299888 5.997292,10.895987 10.108587,22.815972 12.097984,35.093956 1.294199,7.344988 1.520399,14.806978 1.786498,22.241968 M 24.123537,36.172777 c 4.364294,9.670687 7.45489,19.862275 9.647788,30.232262 1.335798,6.180992 2.761896,12.363984 3.600195,18.634976 1.040899,9.690988 1.401998,19.794975 -1.784098,29.140965 -1.475298,2.16 -1.315098,6.60299 -4.463894,6.61699 m 2.109797,-79.6664 C 25.289435,40.989671 17.345645,40.847871 9.4017552,40.705971 M 42.595713,53.473055 C 28.977731,53.898054 15.359648,54.324054 1.7416649,54.749053 M 41.744614,72.198031 c -7.94389,0.992999 -15.88768,1.985998 -23.831569,2.978997 m 21.278173,40.002952 c -5.248594,-1.419 -10.497287,-2.837 -15.74588,-4.256" - style="display:inline;fill:none;stroke:#ed171f;stroke-width:0.999999" + id="path1266" + style="font-variation-settings:normal;display:inline;vector-effect:none;fill:none;fill-opacity:1;stroke:#ed171f;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:black;stop-opacity:1" + d="M 35.8125,61 C 35.104167,60.5 34.166667,60.166667 33,60 27,58.666667 21,62.333333 15,71 12.333333,74.333333 10.166667,77.5 8.5,80.5 6.8333333,83.5 5.3333333,86.333333 4,89 2.6666667,92.333333 3,94.666667 5,96 M 37.25,63 c 0.25,0.833333 0.270833,1.833333 0.0625,3 -0.208333,1.166667 -0.645833,2.5 -1.3125,4 l -2,4 c -1.333333,2.666667 -3,4 -5,4 -1.333333,0 -2.333333,-0.333333 -3,-1 -1.333333,-0.666667 -3.333333,0.333333 -6,3 -2.666667,2.666667 -6,7 -10,13 -2,2.666667 -3.6666667,3.666667 -5,3 m -2.7513593,-8.358647 9.2139423,7.294372 m 3.455229,-28.793571 7.294371,15.246881 m 6.745922,-23.857529 10.201151,11.133513" + inkscape:label="satin" inkstitch:satin_column="True" inkstitch:zigzag_underlay="True" inkstitch:pull_compensation_mm="0.20" - inkscape:label="Colonne satin 0" - id="path165-0" + inkstitch:max_stitch_length_mm="8" inkstitch:min_stitch_length_mm=".50" inkstitch:min_jump_stitch_length_mm="3.0" - inkstitch:max_stitch_length_mm="8" - inkstitch:split_method="staggered" - inkstitch:reverse_rails="none" inkstitch:zigzag_underlay_max_stitch_length_mm="5" - sodipodi:nodetypes="ccccccccccccccccccc" inkstitch:zigzag_underlay_inset_mm=".1" inkstitch:zigzag_underlay_spacing_mm="2.5" /> </g> diff --git a/lib/extensions/lettering_edit_json.py b/lib/extensions/lettering_edit_json.py index b86c4fcb..3c5aa3f4 100644 --- a/lib/extensions/lettering_edit_json.py +++ b/lib/extensions/lettering_edit_json.py @@ -16,7 +16,7 @@ from .base import InkstitchExtension class LetteringEditJson(InkstitchExtension): ''' - This extension helps font creators to generate an output of every glyph from a selected font + This extension helps font creators modify the JSON file of a lettering font. ''' def effect(self): layer = Layer() diff --git a/lib/gui/lettering/main_panel.py b/lib/gui/lettering/main_panel.py index f0532560..fc6d16ad 100644 --- a/lib/gui/lettering/main_panel.py +++ b/lib/gui/lettering/main_panel.py @@ -5,7 +5,6 @@ import json from base64 import b64decode -import unicodedata import inkex import wx @@ -123,12 +122,16 @@ class LetteringPanel(wx.Panel): self.fonts_by_id = {} # font size filter value + filter_size = self.options_panel.font_size_filter.GetValue() filter_glyph = self.options_panel.font_glyph_filter.GetValue() filter_category = self.options_panel.font_category_filter.GetSelection() - 1 # Set of all glyphs in input string (except whitespace characters), normalized in the same way that we normalize font glyphs - glyphs = set(*unicodedata.normalize("NFC", self.options_panel.text_editor.GetValue().replace(r"\s", ""))) + # do not normalize the glyphs yet, available_glyphs are not normalized in the font json file + # glyphs = set(l for l in unicodedata.normalize("NFC", self.options_panel.text_editor.GetValue().replace(r"\s", ""))) + + glyphs = set(letter for letter in self.options_panel.text_editor.GetValue().replace(r"\s", "")) for font in self.font_list: if filter_glyph and glyphs and not glyphs.issubset(font.available_glyphs): @@ -319,7 +322,7 @@ class LetteringPanel(wx.Panel): else: pass - # the text scaling group label is dependend on the user language, so it would break in international file exchange if we used it + # the text scaling group label is dependent on the user language, so it would break in international file exchange if we used it # scaling (correction transform) on the parent group is already applied, so let's use that for recognition if destination_group.get('transform', None) is None: destination_group.attrib['transform'] = 'scale(%s)' % (self.settings.scale / 100.0) diff --git a/lib/gui/lettering_font_sample.py b/lib/gui/lettering_font_sample.py index e19544dc..9f42a755 100644 --- a/lib/gui/lettering_font_sample.py +++ b/lib/gui/lettering_font_sample.py @@ -8,6 +8,7 @@ from copy import deepcopy import wx import wx.adv from inkex import Group, errormsg +import unicodedata from ..commands import ensure_command_symbols from ..i18n import _ @@ -178,29 +179,14 @@ class FontSampleFrame(wx.Frame): text = '' width = 0 last_glyph = None - printed_warning = False - update_glyphlist_warning = _( - "The glyphlist for this font seems to be outdated.\n\n" - "Please update the glyph list for {font_name}:\n" - "* Open Extensions > Ink/Stitch > Font Management > Edit JSON\n" - "* Select this font and apply." - ).format(font_name=self.font.marked_custom_font_name) - - self.duplicate_warning() - - # font variant glyph list length falls short if a single quote sign is available - # let's add it in the length comparison - if len(set(self.font.available_glyphs)) != len(self.font_variant.glyphs): - errormsg(update_glyphlist_warning) - printed_warning = True + outdated = False for glyph in self.font.available_glyphs: glyph_obj = self.font_variant[glyph] if glyph_obj is None: - if not printed_warning: - errormsg(update_glyphlist_warning) - printed_warning = True + outdated = True continue + if last_glyph is not None: width_to_add = (glyph_obj.min_x - self.font.kerning_pairs.get(f'{last_glyph} {glyph}', 0)) * scale width += width_to_add @@ -219,8 +205,8 @@ class FontSampleFrame(wx.Frame): text += glyph width += width_to_add + self.out_dated_warning(outdated) self._render_text(text) - self.GetTopLevelParent().Close() def sortable(self): @@ -229,20 +215,40 @@ class FontSampleFrame(wx.Frame): color_sort = False return color_sort - def duplicate_warning(self): - # warn about duplicated glyphs + def out_dated_warning(self, outdated=False): + # called with outdated == True when some glyphs present in the font.json glyph list are not present in the svg font file + + update_glyphlist_warning = _( + "The glyphlist for this font seems to be outdated.\n\n" + "Please update the glyph list for {font_name}:\n" + "* Open Extensions > Ink/Stitch > Font Management > Edit JSON\n" + "* Select this font and apply." + ).format(font_name=self.font.marked_custom_font_name) + + # warning in case of duplicates in the glyph list of the font.json file if len(set(self.font.available_glyphs)) != len(self.font.available_glyphs): - duplicated_glyphs = " ".join( - [glyph for glyph in set(self.font.available_glyphs) if self.font.available_glyphs.count(glyph) > 1] - ) - errormsg(_("Found duplicated glyphs in font file: {duplicated_glyphs}").format(duplicated_glyphs=duplicated_glyphs)) + outdated = True + + # this will cause a warning if some glyphs of the svg font are not present in the font.json glyph list + if len(set(self.font.available_glyphs)) != len(self.font_variant.glyphs): + outdated = True + + if outdated: + errormsg(update_glyphlist_warning) def _render_text(self, text): lines = text.splitlines() position = {'x': 0, 'y': 0} for line in lines: group = Group() - group.label = line + label = "" + # make the label of the group line clearly show the non spacing marks + for character in line: + if unicodedata.category(character) != 'Mn': + label += character + else: + label += ' ' + character + group.label = label group.set("inkstitch:letter-group", "line") glyphs = [] skip = [] @@ -297,7 +303,12 @@ class FontSampleFrame(wx.Frame): # because this is not unique it will be overwritten by inkscape when inserted into the document node.set("id", "glyph") node.set("inkstitch:letter-group", "glyph") + # force inkscape to show a label when the glyph is only a non spacing mark + if len(node.label) == 1 and unicodedata.category(node.label) == 'Mn': + node.label = ' ' + node.label + group.add(node) + return position def cancel(self, event): diff --git a/lib/lettering/font.py b/lib/lettering/font.py index 5ae6743a..1d9f8b40 100644 --- a/lib/lettering/font.py +++ b/lib/lettering/font.py @@ -452,7 +452,10 @@ class Font(object): # because this is not unique it will be overwritten by inkscape when inserted into the document node.set("id", "glyph") node.set("inkstitch:letter-group", "glyph") - + # force inkscape to show a label when the glyph is only a non-spacing mark + if len(node.label) == 1 and unicodedata.category(node.label) == 'Mn': + # force inkscape to show a label when the glyph is only a non-spacing mark + node.label = ' ' + node.label return node def _update_commands(self, node, glyph, id_extension=""): diff --git a/lib/lettering/font_variant.py b/lib/lettering/font_variant.py index 80d9d3e6..0e4836e8 100644 --- a/lib/lettering/font_variant.py +++ b/lib/lettering/font_variant.py @@ -198,7 +198,7 @@ class FontVariant(object): shape = 'fina' else: shape = 'isol' - # in the middle of the actual word, the shape of a glyph is medi if previous glyph is bendinng, init otherwise + # in the middle of the actual word, the shape of a glyph is medi if previous glyph is binding, init otherwise elif previous_is_binding: shape = 'medi' else: @@ -207,9 +207,10 @@ class FontVariant(object): return shape def get_next_glyph(self, word, i, previous_is_binding): - # search for the glyph of word that starts at i,taking into acount the previous glyph binding status + # word[:i] has been processed, this function returns the glyph starting at word[i] + # taking into acount the previous glyph binding status - # find all the glyphs in tthe font that start with first letter of the glyph + # find all the glyphs in the font that start with first letter of the glyph glyph_selection = self.glyphs_start_with(word[i]) # find the longest glyph that match |
