137 lines
4.5 KiB
Python
137 lines
4.5 KiB
Python
#!/usr/bin/env python
|
|
# coding=utf-8
|
|
#
|
|
# Copyright (C) 2021 David Burghoff, dburghoff@nd.edu
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
EXTENT = 0.5
|
|
# how far the rectangle should extend from the text, in units of font size
|
|
OPACITY = 0.75
|
|
# how opaque it is (0.0-1.0)
|
|
STDDEV = 0.5
|
|
# standard deviation of the Gaussian blur as fraction of EXTENT
|
|
|
|
import dhelpers as dh
|
|
import inkex
|
|
dispprofile = False
|
|
|
|
|
|
class TextGhoster(inkex.EffectExtension):
|
|
def add_arguments(self, pars):
|
|
pars.add_argument("--tab", help="The selected UI-tab when OK was pressed")
|
|
|
|
def effect(self):
|
|
if dispprofile:
|
|
import cProfile, pstats, io
|
|
from pstats import SortKey
|
|
|
|
pr = cProfile.Profile()
|
|
pr.enable()
|
|
|
|
sel = [self.svg.selection[ii] for ii in range(len(self.svg.selection))]
|
|
# should work with both v1.0 and v1.1
|
|
gs = []
|
|
oldts = dict()
|
|
for el in sel:
|
|
# Add el to a group
|
|
g = inkex.Group()
|
|
gs.append(g)
|
|
# myi=el.getparent().index(el);
|
|
el.getparent().insert(len(el.getparent().getchildren()), g)
|
|
g.insert(0, el)
|
|
# Transfer transform to group
|
|
# g.set("transform", el.get("transform"))
|
|
g.ctransform = el.ctransform
|
|
# el.set("transform", None)
|
|
el.ctransform = None
|
|
# Remove transform
|
|
oldts[g.get_id()] = g.ccomposed_transform
|
|
try:
|
|
dh.global_transform(g, -oldts[g.get_id()])
|
|
except ZeroDivisionError:
|
|
gs.remove(g)
|
|
|
|
# dh.idebug(sel)
|
|
|
|
# dh.idebug(dir(sel[0]))
|
|
bbs = dh.BB2(
|
|
self.svg, sel, forceupdate=True
|
|
) # need to investigate why sel didn't work
|
|
|
|
for g in gs:
|
|
el = g.getchildren()[0]
|
|
f = inkex.Filter()
|
|
el.root.defs.insert(0, f)
|
|
gb = inkex.Filter.GaussianBlur()
|
|
f.insert(0, gb)
|
|
fid = f.get_id()
|
|
|
|
r = inkex.Rectangle()
|
|
g.insert(0, r)
|
|
|
|
bb = bbs[el.get_id()]
|
|
ct = el.ccomposed_transform
|
|
# bb = [v / (self.svg.cscale) for v in bb]
|
|
|
|
fss = []
|
|
for d in el.descendants2():
|
|
sty = d.cspecified_style
|
|
fs = sty.get("font-size")
|
|
if fs is not None:
|
|
fss.append(dh.composed_width(d, "font-size")[0])
|
|
if len(fss) > 0:
|
|
fs = max(fss)
|
|
else:
|
|
fs = dh.ipx("8pt")
|
|
border = fs * EXTENT
|
|
# / (self.svg.cscale)
|
|
|
|
gb.set("stdDeviation", border * STDDEV)
|
|
pts = [
|
|
[bb[0] - border, bb[1] - border],
|
|
[bb[0] + bb[2] + border, bb[1] - border],
|
|
[bb[0] + bb[2] + border, bb[1] + bb[3] + border],
|
|
[bb[0] - border, bb[1] + bb[3] + border],
|
|
[bb[0] - border, bb[1] - border],
|
|
]
|
|
xs = []
|
|
ys = []
|
|
for p in pts:
|
|
p = (-ct).apply_to_point(p)
|
|
xs.append(p.x)
|
|
ys.append(p.y)
|
|
r.set("x", str(min(xs)))
|
|
r.set("y", str(min(ys)))
|
|
r.set("width", str(max(xs) - min(xs)))
|
|
r.set("height", str(max(ys) - min(ys)))
|
|
r.set("rx", str(border))
|
|
# r.set('style','fill:#ffffff;filter:url(#'+fid+')')
|
|
r.cstyle = "fill:#ffffff;stroke:none;filter:url(#{0})".format(fid)
|
|
r.cstyle["opacity"] = str(OPACITY)
|
|
|
|
dh.global_transform(g, oldts[g.get_id()])
|
|
|
|
if dispprofile:
|
|
pr.disable()
|
|
s = io.StringIO()
|
|
sortby = SortKey.CUMULATIVE
|
|
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
|
|
ps.print_stats()
|
|
dh.debug(s.getvalue())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
dh.Run_SI_Extension(TextGhoster(), "Text ghoster")
|