kopia lustrzana https://github.com/inkstitch/inkstitch
rodzic
a010866680
commit
ed33b29c28
|
@ -31,6 +31,7 @@ from .layer_commands import LayerCommands
|
||||||
from .lettering import Lettering
|
from .lettering import Lettering
|
||||||
from .lettering_along_path import LetteringAlongPath
|
from .lettering_along_path import LetteringAlongPath
|
||||||
from .lettering_custom_font_dir import LetteringCustomFontDir
|
from .lettering_custom_font_dir import LetteringCustomFontDir
|
||||||
|
from .lettering_font_sample import LetteringFontSample
|
||||||
from .lettering_force_lock_stitches import LetteringForceLockStitches
|
from .lettering_force_lock_stitches import LetteringForceLockStitches
|
||||||
from .lettering_generate_json import LetteringGenerateJson
|
from .lettering_generate_json import LetteringGenerateJson
|
||||||
from .lettering_remove_kerning import LetteringRemoveKerning
|
from .lettering_remove_kerning import LetteringRemoveKerning
|
||||||
|
@ -90,6 +91,7 @@ __all__ = extensions = [ApplyPalette,
|
||||||
Lettering,
|
Lettering,
|
||||||
LetteringAlongPath,
|
LetteringAlongPath,
|
||||||
LetteringCustomFontDir,
|
LetteringCustomFontDir,
|
||||||
|
LetteringFontSample,
|
||||||
LetteringForceLockStitches,
|
LetteringForceLockStitches,
|
||||||
LetteringGenerateJson,
|
LetteringGenerateJson,
|
||||||
LetteringRemoveKerning,
|
LetteringRemoveKerning,
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Authors: see git history
|
||||||
|
#
|
||||||
|
# Copyright (c) 2010 Authors
|
||||||
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
|
from inkex import Layer
|
||||||
|
|
||||||
|
from ..gui.lettering_font_sample import LetteringFontSampleApp
|
||||||
|
from ..i18n import _
|
||||||
|
from .base import InkstitchExtension
|
||||||
|
from ..svg import get_correction_transform
|
||||||
|
|
||||||
|
|
||||||
|
class LetteringFontSample(InkstitchExtension):
|
||||||
|
'''
|
||||||
|
This extension helps font creators to generate an output of every glyph from a selected font
|
||||||
|
'''
|
||||||
|
def effect(self):
|
||||||
|
layer = Layer()
|
||||||
|
self.svg.add(layer)
|
||||||
|
layer.label = _("Font Sample")
|
||||||
|
transform = get_correction_transform(layer, child=True)
|
||||||
|
layer.transform = transform
|
||||||
|
app = LetteringFontSampleApp(layer=layer)
|
||||||
|
app.MainLoop()
|
||||||
|
if len(layer) == 0:
|
||||||
|
self.svg.remove(layer)
|
|
@ -4,23 +4,20 @@
|
||||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
|
|
||||||
import appdirs
|
|
||||||
import inkex
|
import inkex
|
||||||
import wx
|
import wx
|
||||||
import wx.adv
|
import wx.adv
|
||||||
import wx.lib.agw.floatspin as fs
|
import wx.lib.agw.floatspin as fs
|
||||||
|
|
||||||
from ..elements import nodes_to_elements
|
from ..elements import nodes_to_elements
|
||||||
from ..extensions.lettering_custom_font_dir import get_custom_font_dir
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..lettering import Font, FontError
|
from ..lettering import FontError, get_font_list
|
||||||
from ..lettering.categories import FONT_CATEGORIES, FontCategory
|
from ..lettering.categories import FONT_CATEGORIES, FontCategory
|
||||||
from ..stitch_plan import stitch_groups_to_stitch_plan
|
from ..stitch_plan import stitch_groups_to_stitch_plan
|
||||||
from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_LETTERING, SVG_PATH_TAG
|
from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_LETTERING, SVG_PATH_TAG
|
||||||
from ..utils import DotDict, cache, get_bundled_dir
|
from ..utils import DotDict, cache
|
||||||
from ..utils.threading import ExitThread, check_stop_flag
|
from ..utils.threading import ExitThread, check_stop_flag
|
||||||
from . import PresetsPanel, PreviewRenderer, info_dialog
|
from . import PresetsPanel, PreviewRenderer, info_dialog
|
||||||
|
|
||||||
|
@ -153,26 +150,7 @@ class LetteringPanel(wx.Panel):
|
||||||
@property
|
@property
|
||||||
@cache
|
@cache
|
||||||
def font_list(self):
|
def font_list(self):
|
||||||
fonts = []
|
return get_font_list()
|
||||||
font_paths = {
|
|
||||||
get_bundled_dir("fonts"),
|
|
||||||
os.path.expanduser("~/.inkstitch/fonts"),
|
|
||||||
os.path.join(appdirs.user_config_dir('inkstitch'), 'fonts'),
|
|
||||||
get_custom_font_dir()
|
|
||||||
}
|
|
||||||
|
|
||||||
for font_path in font_paths:
|
|
||||||
try:
|
|
||||||
font_dirs = os.listdir(font_path)
|
|
||||||
except OSError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for font_dir in font_dirs:
|
|
||||||
font = Font(os.path.join(font_path, font_dir))
|
|
||||||
if font.marked_custom_font_name == "" or font.marked_custom_font_id == "":
|
|
||||||
continue
|
|
||||||
fonts.append(font)
|
|
||||||
return fonts
|
|
||||||
|
|
||||||
def update_font_list(self):
|
def update_font_list(self):
|
||||||
self.fonts = {}
|
self.fonts = {}
|
||||||
|
|
|
@ -0,0 +1,187 @@
|
||||||
|
# Authors: see git history
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Authors
|
||||||
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
|
import wx
|
||||||
|
import wx.adv
|
||||||
|
|
||||||
|
from ..i18n import _
|
||||||
|
from ..lettering import get_font_list
|
||||||
|
|
||||||
|
|
||||||
|
class FontSampleFrame(wx.Frame):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.layer = kwargs.pop("layer")
|
||||||
|
wx.Frame.__init__(self, None, wx.ID_ANY, _("Font Sampling"), *args, **kwargs)
|
||||||
|
|
||||||
|
self.SetWindowStyle(wx.FRAME_FLOAT_ON_PARENT | wx.DEFAULT_FRAME_STYLE)
|
||||||
|
|
||||||
|
self.fonts = None
|
||||||
|
|
||||||
|
self.main_panel = wx.Panel(self, wx.ID_ANY)
|
||||||
|
|
||||||
|
notebook_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
self.notebook = wx.Notebook(self.main_panel, wx.ID_ANY)
|
||||||
|
notebook_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
|
||||||
|
|
||||||
|
self.settings = wx.Panel(self.notebook, wx.ID_ANY)
|
||||||
|
self.notebook.AddPage(self.settings, _("Settings"))
|
||||||
|
|
||||||
|
# settings
|
||||||
|
settings_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
|
||||||
|
self.font_chooser = wx.adv.BitmapComboBox(self.settings, wx.ID_ANY, style=wx.CB_READONLY | wx.CB_SORT, size=((800, 20)))
|
||||||
|
self.font_chooser.Bind(wx.EVT_COMBOBOX, self.on_font_changed)
|
||||||
|
|
||||||
|
grid_settings_sizer = wx.FlexGridSizer(6, 2, 5, 5)
|
||||||
|
grid_settings_sizer.AddGrowableCol(1)
|
||||||
|
|
||||||
|
direction_label = wx.StaticText(self.settings, label=_("Stitch direction"))
|
||||||
|
self.direction = wx.ComboBox(self.settings, choices=[], style=wx.CB_READONLY)
|
||||||
|
scale_spinner_label = wx.StaticText(self.settings, label=_("Scale (%)"))
|
||||||
|
self.scale_spinner = wx.SpinCtrl(self.settings, wx.ID_ANY, min=0, max=1000, initial=100)
|
||||||
|
max_line_width_label = wx.StaticText(self.settings, label=_("Max. line width"))
|
||||||
|
self.max_line_width = wx.SpinCtrl(self.settings, wx.ID_ANY, min=0, max=5000, initial=500)
|
||||||
|
|
||||||
|
grid_settings_sizer.Add(direction_label, 0, wx.ALIGN_LEFT, 0)
|
||||||
|
grid_settings_sizer.Add(self.direction, 0, wx.EXPAND, 0)
|
||||||
|
grid_settings_sizer.Add(scale_spinner_label, 0, wx.ALIGN_LEFT, 0)
|
||||||
|
grid_settings_sizer.Add(self.scale_spinner, 0, wx.EXPAND, 0)
|
||||||
|
grid_settings_sizer.Add(max_line_width_label, 0, wx.ALIGN_LEFT, 0)
|
||||||
|
grid_settings_sizer.Add(self.max_line_width, 0, wx.EXPAND, 0)
|
||||||
|
|
||||||
|
apply_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
self.cancel_button = wx.Button(self.settings, label=_("Cancel"))
|
||||||
|
self.cancel_button.Bind(wx.EVT_BUTTON, self.cancel)
|
||||||
|
self.apply_button = wx.Button(self.settings, label=_("Apply"))
|
||||||
|
self.apply_button.Bind(wx.EVT_BUTTON, self.apply)
|
||||||
|
apply_sizer.Add(self.cancel_button, 0, wx.RIGHT | wx.BOTTOM, 5)
|
||||||
|
apply_sizer.Add(self.apply_button, 0, wx.RIGHT | wx.BOTTOM, 10)
|
||||||
|
|
||||||
|
settings_sizer.Add(self.font_chooser, 1, wx.ALL | wx.EXPAND, 10)
|
||||||
|
settings_sizer.Add(grid_settings_sizer, 1, wx.ALL | wx.EXPAND, 10)
|
||||||
|
settings_sizer.Add(apply_sizer, 1, wx.ALIGN_RIGHT | wx.ALL, 10)
|
||||||
|
|
||||||
|
# help
|
||||||
|
self.help = wx.Panel(self.notebook, wx.ID_ANY)
|
||||||
|
self.notebook.AddPage(self.help, _("Help"))
|
||||||
|
|
||||||
|
help_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
|
||||||
|
help_text = wx.StaticText(
|
||||||
|
self.help,
|
||||||
|
wx.ID_ANY,
|
||||||
|
_(" This extension helps font creators to generate an output of every glyph from a selected font."),
|
||||||
|
style=wx.ALIGN_LEFT
|
||||||
|
)
|
||||||
|
help_text.Wrap(500)
|
||||||
|
help_sizer.Add(help_text, 0, wx.ALL, 8)
|
||||||
|
|
||||||
|
help_sizer.Add((20, 20), 0, 0, 0)
|
||||||
|
|
||||||
|
website_info = wx.StaticText(self.help, wx.ID_ANY, _("More information on our website:"))
|
||||||
|
help_sizer.Add(website_info, 0, wx.ALL, 8)
|
||||||
|
|
||||||
|
self.website_link = wx.adv.HyperlinkCtrl(
|
||||||
|
self.help,
|
||||||
|
wx.ID_ANY,
|
||||||
|
_("https://inkstitch.org/docs/font-tools/#font-sampling"),
|
||||||
|
_("https://inkstitch.org/docs/font-tools/#font-sampling")
|
||||||
|
)
|
||||||
|
help_sizer.Add(self.website_link, 0, wx.ALL, 8)
|
||||||
|
|
||||||
|
self.help.SetSizer(help_sizer)
|
||||||
|
self.settings.SetSizer(settings_sizer)
|
||||||
|
self.main_panel.SetSizer(notebook_sizer)
|
||||||
|
|
||||||
|
self.set_font_list()
|
||||||
|
self.font_chooser.SetValue(list(self.fonts.values())[0].marked_custom_font_name)
|
||||||
|
self.on_font_changed()
|
||||||
|
|
||||||
|
self.SetSizeHints(notebook_sizer.CalcMin())
|
||||||
|
|
||||||
|
self.Layout()
|
||||||
|
|
||||||
|
def set_font_list(self):
|
||||||
|
self.fonts = {}
|
||||||
|
font_list = get_font_list()
|
||||||
|
for font in font_list:
|
||||||
|
self.fonts[font.marked_custom_font_name] = font
|
||||||
|
image = font.preview_image
|
||||||
|
if image is not None:
|
||||||
|
image = wx.Image(image)
|
||||||
|
# Windows requires all images to have the exact same size
|
||||||
|
image.Rescale(300, 20, quality=wx.IMAGE_QUALITY_HIGH)
|
||||||
|
self.font_chooser.Append(font.marked_custom_font_name, wx.Bitmap(image))
|
||||||
|
else:
|
||||||
|
self.font_chooser.Append(font.marked_custom_font_name)
|
||||||
|
|
||||||
|
def on_font_changed(self, event=None):
|
||||||
|
font = self.fonts.get(self.font_chooser.GetValue(), list(self.fonts.values())[0].marked_custom_font_name)
|
||||||
|
self.scale_spinner.SetRange(int(font.min_scale * 100), int(font.max_scale * 100))
|
||||||
|
# font._load_variants()
|
||||||
|
self.direction.Clear()
|
||||||
|
for variant in font.has_variants():
|
||||||
|
self.direction.Append(variant)
|
||||||
|
self.direction.SetSelection(0)
|
||||||
|
|
||||||
|
def apply(self, event):
|
||||||
|
# apply scale to layer and extract for later use
|
||||||
|
self.layer.transform.add_scale(self.scale_spinner.GetValue() / 100)
|
||||||
|
scale = self.layer.transform.a
|
||||||
|
|
||||||
|
# set font
|
||||||
|
font = self.fonts.get(self.font_chooser.GetValue())
|
||||||
|
if font is None:
|
||||||
|
self.GetTopLevelParent().Close()
|
||||||
|
return
|
||||||
|
|
||||||
|
# parameters
|
||||||
|
line_width = self.max_line_width.GetValue()
|
||||||
|
font._load_variants()
|
||||||
|
font_variant = font.variants[self.direction.GetValue()]
|
||||||
|
|
||||||
|
# setup lines of text
|
||||||
|
text = ''
|
||||||
|
width = 0
|
||||||
|
last_glyph = None
|
||||||
|
for glyph in font.available_glyphs:
|
||||||
|
glyph_obj = font_variant[glyph]
|
||||||
|
if last_glyph is not None:
|
||||||
|
width_to_add = (glyph_obj.min_x - font.kerning_pairs.get(last_glyph + glyph, 0)) * scale
|
||||||
|
width += width_to_add
|
||||||
|
|
||||||
|
try:
|
||||||
|
width_to_add = (font.horiz_adv_x.get(glyph, font.horiz_adv_x_default) - glyph_obj.min_x) * scale
|
||||||
|
except TypeError:
|
||||||
|
width += glyph_obj.width
|
||||||
|
|
||||||
|
if width + width_to_add > line_width:
|
||||||
|
text += '\n'
|
||||||
|
width = 0
|
||||||
|
last_glyph = None
|
||||||
|
else:
|
||||||
|
last_glyph = glyph
|
||||||
|
text += glyph
|
||||||
|
width += width_to_add
|
||||||
|
|
||||||
|
# render text and close
|
||||||
|
font.render_text(text, self.layer)
|
||||||
|
self.GetTopLevelParent().Close()
|
||||||
|
|
||||||
|
def cancel(self, event):
|
||||||
|
self.GetTopLevelParent().Close()
|
||||||
|
|
||||||
|
|
||||||
|
class LetteringFontSampleApp(wx.App):
|
||||||
|
def __init__(self, layer):
|
||||||
|
self.layer = layer
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def OnInit(self):
|
||||||
|
self.frame = FontSampleFrame(layer=self.layer)
|
||||||
|
self.SetTopWindow(self.frame)
|
||||||
|
self.frame.Show()
|
||||||
|
return True
|
|
@ -4,3 +4,4 @@
|
||||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
from .font import Font, FontError
|
from .font import Font, FontError
|
||||||
|
from .utils import get_font_list
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Authors: see git history
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 Authors
|
||||||
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import appdirs
|
||||||
|
|
||||||
|
from ..extensions.lettering_custom_font_dir import get_custom_font_dir
|
||||||
|
from ..lettering import Font
|
||||||
|
from ..utils import get_bundled_dir
|
||||||
|
|
||||||
|
|
||||||
|
def get_font_list():
|
||||||
|
fonts = []
|
||||||
|
font_paths = {
|
||||||
|
get_bundled_dir("fonts"),
|
||||||
|
os.path.expanduser("~/.inkstitch/fonts"),
|
||||||
|
os.path.join(appdirs.user_config_dir('inkstitch'), 'fonts'),
|
||||||
|
get_custom_font_dir()
|
||||||
|
}
|
||||||
|
|
||||||
|
for font_path in font_paths:
|
||||||
|
try:
|
||||||
|
font_dirs = os.listdir(font_path)
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for font_dir in font_dirs:
|
||||||
|
font = Font(os.path.join(font_path, font_dir))
|
||||||
|
if font.marked_custom_font_name == "" or font.marked_custom_font_id == "":
|
||||||
|
continue
|
||||||
|
fonts.append(font)
|
||||||
|
return fonts
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||||
|
<name>Font Sampling</name>
|
||||||
|
<id>org.{{ id_inkstitch }}.lettering_font_sample</id>
|
||||||
|
<param name="extension" type="string" gui-hidden="true">lettering_font_sample</param>
|
||||||
|
<effect>
|
||||||
|
<object-type>all</object-type>
|
||||||
|
<effects-menu>
|
||||||
|
<submenu name="{{ menu_inkstitch }}" translatable="no">
|
||||||
|
<submenu name="Font Management" />
|
||||||
|
</submenu>
|
||||||
|
</effects-menu>
|
||||||
|
</effect>
|
||||||
|
<script>
|
||||||
|
{{ command_tag | safe }}
|
||||||
|
</script>
|
||||||
|
</inkscape-extension>
|
Ładowanie…
Reference in New Issue