kopia lustrzana https://github.com/inkstitch/inkstitch
Merge branch 'main' of https://github.com/inkstitch/inkstitch into george-steel/expose-trim-after
commit
e52f889bb0
|
@ -52,6 +52,7 @@ jobs:
|
||||||
sudo apt-get install gettext
|
sudo apt-get install gettext
|
||||||
|
|
||||||
# for wxPython
|
# for wxPython
|
||||||
|
sudo apt install libnotify4
|
||||||
sudo apt install glib-networking libsdl2-dev libsdl2-2.0-0
|
sudo apt install glib-networking libsdl2-dev libsdl2-2.0-0
|
||||||
|
|
||||||
# for PyGObject
|
# for PyGObject
|
||||||
|
|
|
@ -48,6 +48,8 @@ from .stitch_plan_preview import StitchPlanPreview
|
||||||
from .stitch_plan_preview_undo import StitchPlanPreviewUndo
|
from .stitch_plan_preview_undo import StitchPlanPreviewUndo
|
||||||
from .zip import Zip
|
from .zip import Zip
|
||||||
|
|
||||||
|
from.lettering_along_path import LetteringAlongPath
|
||||||
|
|
||||||
__all__ = extensions = [StitchPlanPreview,
|
__all__ = extensions = [StitchPlanPreview,
|
||||||
StitchPlanPreviewUndo,
|
StitchPlanPreviewUndo,
|
||||||
DensityMap,
|
DensityMap,
|
||||||
|
@ -75,6 +77,7 @@ __all__ = extensions = [StitchPlanPreview,
|
||||||
LetteringRemoveKerning,
|
LetteringRemoveKerning,
|
||||||
LetteringCustomFontDir,
|
LetteringCustomFontDir,
|
||||||
LetteringForceLockStitches,
|
LetteringForceLockStitches,
|
||||||
|
LetteringAlongPath,
|
||||||
LettersToFont,
|
LettersToFont,
|
||||||
Troubleshoot,
|
Troubleshoot,
|
||||||
RemoveEmbroiderySettings,
|
RemoveEmbroiderySettings,
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
# Authors: see git history
|
||||||
|
#
|
||||||
|
# Copyright (c) 2021 Authors
|
||||||
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from math import atan2, degrees
|
||||||
|
|
||||||
|
from inkex import Boolean, Transform, errormsg
|
||||||
|
from shapely.ops import substring
|
||||||
|
|
||||||
|
from ..elements import Stroke
|
||||||
|
from ..i18n import _
|
||||||
|
from ..svg import get_correction_transform
|
||||||
|
from ..svg.tags import EMBROIDERABLE_TAGS, INKSTITCH_LETTERING, SVG_GROUP_TAG
|
||||||
|
from ..utils import DotDict
|
||||||
|
from ..utils import Point as InkstitchPoint
|
||||||
|
from .base import InkstitchExtension
|
||||||
|
|
||||||
|
|
||||||
|
class LetteringAlongPath(InkstitchExtension):
|
||||||
|
'''
|
||||||
|
This extension aligns an Ink/Stitch Lettering group along a path
|
||||||
|
'''
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
InkstitchExtension.__init__(self, *args, **kwargs)
|
||||||
|
self.arg_parser.add_argument("-o", "--options", type=str, default=None, dest="page_1")
|
||||||
|
self.arg_parser.add_argument("-i", "--info", type=str, default=None, dest="page_2")
|
||||||
|
self.arg_parser.add_argument("-s", "--stretch-spaces", type=Boolean, default=False, dest="stretch_spaces")
|
||||||
|
|
||||||
|
def effect(self):
|
||||||
|
# we ignore everything but the first path/text
|
||||||
|
text, path = self.get_selection()
|
||||||
|
self.load_settings(text)
|
||||||
|
|
||||||
|
glyphs = [glyph for glyph in text.iterdescendants(SVG_GROUP_TAG) if len(glyph.label) == 1]
|
||||||
|
if not glyphs:
|
||||||
|
errormsg(_("The text doesn't contain any glyphs."))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
path = Stroke(path).as_multi_line_string().geoms[0]
|
||||||
|
path_length = path.length
|
||||||
|
|
||||||
|
# overall bounding box - get from direct glyph parent
|
||||||
|
text_bbox = glyphs[0].getparent().bounding_box()
|
||||||
|
text_y = text_bbox.bottom
|
||||||
|
|
||||||
|
if self.options.stretch_spaces:
|
||||||
|
text_content = self.settings["text"]
|
||||||
|
space_indices = [i for i, t in enumerate(text_content) if t == " "]
|
||||||
|
text_width = text_bbox.width
|
||||||
|
|
||||||
|
if len(text_content) - 1 != 0:
|
||||||
|
stretch_space = (path_length - text_width) / (len(text_content) - 1)
|
||||||
|
else:
|
||||||
|
stretch_space = 0
|
||||||
|
else:
|
||||||
|
stretch_space = 0
|
||||||
|
space_indices = []
|
||||||
|
|
||||||
|
self.transform_glyphs(glyphs, path, stretch_space, space_indices, text_y)
|
||||||
|
|
||||||
|
def transform_glyphs(self, glyphs, path, stretch_space, space_indices, text_y):
|
||||||
|
text_scale = Transform(f'scale({self.settings["scale"] / 100})')
|
||||||
|
distance = 0
|
||||||
|
old_bbox = None
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
for glyph in glyphs:
|
||||||
|
# dimensions
|
||||||
|
bbox = glyph.bounding_box()
|
||||||
|
left = bbox.left
|
||||||
|
width = bbox.width
|
||||||
|
|
||||||
|
# adjust position
|
||||||
|
if old_bbox:
|
||||||
|
right = old_bbox.right
|
||||||
|
distance += left - right + stretch_space
|
||||||
|
|
||||||
|
if self.options.stretch_spaces and i in space_indices:
|
||||||
|
distance += stretch_space
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
new_distance = distance + width
|
||||||
|
|
||||||
|
# calculate and apply transform
|
||||||
|
first = substring(path, distance, distance)
|
||||||
|
last = substring(path, new_distance, new_distance)
|
||||||
|
|
||||||
|
angle = degrees(atan2(last.y - first.y, last.x - first.x)) % 360
|
||||||
|
translate = InkstitchPoint(first.x, first.y) - InkstitchPoint(left, text_y)
|
||||||
|
|
||||||
|
transform = Transform(f"rotate({angle}, {first.x}, {first.y}) translate({translate.x} {translate.y})")
|
||||||
|
correction_transform = Transform(get_correction_transform(glyph))
|
||||||
|
glyph.transform = correction_transform @ transform @ glyph.transform @ text_scale
|
||||||
|
|
||||||
|
# set values for next iteration
|
||||||
|
distance = new_distance
|
||||||
|
old_bbox = bbox
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
def load_settings(self, text):
|
||||||
|
"""Load the settings saved into the text element"""
|
||||||
|
|
||||||
|
self.settings = DotDict({
|
||||||
|
"text": "",
|
||||||
|
"back_and_forth": False,
|
||||||
|
"font": None,
|
||||||
|
"scale": 100,
|
||||||
|
"trim_option": 0
|
||||||
|
})
|
||||||
|
|
||||||
|
if INKSTITCH_LETTERING in text.attrib:
|
||||||
|
try:
|
||||||
|
self.settings.update(json.loads(text.get(INKSTITCH_LETTERING)))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_selection(self):
|
||||||
|
groups = list()
|
||||||
|
paths = list()
|
||||||
|
|
||||||
|
for node in self.svg.selection:
|
||||||
|
lettering = False
|
||||||
|
if node.tag == SVG_GROUP_TAG and INKSTITCH_LETTERING in node.attrib:
|
||||||
|
groups.append(node)
|
||||||
|
lettering = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
for group in node.iterancestors(SVG_GROUP_TAG):
|
||||||
|
if INKSTITCH_LETTERING in group.attrib:
|
||||||
|
groups.append(group)
|
||||||
|
lettering = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not lettering and node.tag in EMBROIDERABLE_TAGS:
|
||||||
|
paths.append(node)
|
||||||
|
|
||||||
|
if not groups or not paths:
|
||||||
|
errormsg(_("Please select one path and one Ink/Stitch lettering group."))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return [groups[0], paths[0]]
|
|
@ -1,7 +1,7 @@
|
||||||
./pyembroidery
|
./pyembroidery
|
||||||
|
|
||||||
# inkex is not currently uploaded to pypi, the version there is extremely out of date
|
# inkex is not currently uploaded to pypi, the version there is extremely out of date
|
||||||
inkex @ git+https://gitlab.com/inkscape/extensions.git@EXTENSIONS_AT_INKSCAPE_1.2.1
|
inkex @ git+https://gitlab.com/inkscape/extensions.git@EXTENSIONS_AT_INKSCAPE_1.2.2
|
||||||
|
|
||||||
# lower bound to allow for the use of system packages on Debian and distros that have updated to 4.2
|
# lower bound to allow for the use of system packages on Debian and distros that have updated to 4.2
|
||||||
# CI adds an == 4.1.1 constraint for prebuilt packages
|
# CI adds an == 4.1.1 constraint for prebuilt packages
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||||
|
<name>Lettering along path</name>
|
||||||
|
<id>org.inkstitch.lettering_along_path</id>
|
||||||
|
<param name="extension" type="string" gui-hidden="true">lettering_along_path</param>
|
||||||
|
<effect needs-live-preview="false">
|
||||||
|
<object-type>all</object-type>
|
||||||
|
<effects-menu>
|
||||||
|
<submenu name="Ink/Stitch" translatable="no" />
|
||||||
|
</effects-menu>
|
||||||
|
</effect>
|
||||||
|
<param name="options" type="notebook">
|
||||||
|
<page name="options" gui-text="Options">
|
||||||
|
<param name="stretch-spaces" type="bool" gui-text="Stretch"
|
||||||
|
gui-description="Expand glyph and word spacing to stretch lettering over the entire path">false</param>
|
||||||
|
</page>
|
||||||
|
<page name="info" gui-text="Help">
|
||||||
|
<label appearance="header">This extension bends an Ink/Stitch text to a path.</label>
|
||||||
|
<label>Select Ink/Stitch text and a path before running this extension.</label>
|
||||||
|
<spacer />
|
||||||
|
<label>The text needs to meet these conditions:</label>
|
||||||
|
<label indent="1">* The text consists of only one line of text</label>
|
||||||
|
<label indent="1">* The text should not be too large for the given path</label>
|
||||||
|
<label indent="1">* Text text should not contain trim symbols</label>
|
||||||
|
<spacer />
|
||||||
|
<label>The stretch option defines whether the spaces between glyphs should be expanded so that the text stretches over the entire path.</label>
|
||||||
|
</page>
|
||||||
|
</param>
|
||||||
|
<script>
|
||||||
|
{{ command_tag | safe }}
|
||||||
|
</script>
|
||||||
|
</inkscape-extension>
|
Ładowanie…
Reference in New Issue