|
From: André W. <wo...@us...> - 2011-10-07 21:06:57
|
Hi Michael,
thank you for your patch. Overall I like it very much. I didn't try it yet, just browsed it. In general I'm very happy to accept your patch. However I have one question which I would like to address first. Couldn't be the singlecharmode an option to the text method of the texrunner. Could it be passed to be applied to the single page on the dvifile being created/processed? I didn't try but my impression is that this could be possible. Maybe I don't see the real trouble ahead when trying to do so, but it might be possible without major problems. Could you comment on that?
André
Am 07.10.2011 um 18:14 schrieb Michael J Gruber:
> Implement a decorator curvedtext for setting text along a given path.
> curvedtext switches to singlecharmode, but only while it is needed.
>
> The basic idea has been discussed on the list and goes back to the PyX
> grand masters.
>
> Signed-off-by: Michael J Gruber <mic...@us...>
> ---
> examples/text/INDEX | 1 +
> examples/text/textalongpath.py | 15 ++++++++++
> examples/text/textalongpath.txt | 5 +++
> pyx/deco.py | 59 +++++++++++++++++++++++++++++++++++++++
> pyx/dvi/dvifile.py | 5 ++-
> pyx/text.py | 8 +++--
> 6 files changed, 88 insertions(+), 5 deletions(-)
> create mode 100644 examples/text/textalongpath.py
> create mode 100644 examples/text/textalongpath.txt
>
> diff --git a/examples/text/INDEX b/examples/text/INDEX
> index 04692ae..c982f89 100644
> --- a/examples/text/INDEX
> +++ b/examples/text/INDEX
> @@ -5,3 +5,4 @@ marker
> color
> texrunner
> textbox
> +textalongpath
> diff --git a/examples/text/textalongpath.py b/examples/text/textalongpath.py
> new file mode 100644
> index 0000000..c410aa4
> --- /dev/null
> +++ b/examples/text/textalongpath.py
> @@ -0,0 +1,15 @@
> +from pyx import *
> +
> +c = canvas.canvas()
> +
> +R = 1.3
> +p = path.path(path.arc(0,0, R, 0,270)) + path.line(0,-R, R,-R)
> +label = (r"\PyX{} is fun. " * 4)[:-1] # chop off last space
> +
> +c.draw(p, [deco.stroked([color.rgb.blue]), deco.curvedtext(label)])
> +c.draw(p, [trafo.translate(2.5*R,0), deco.stroked([color.rgb.blue]), deco.curvedtext(label,textattrs=[text.halign.right],relarclenpos=1)])
> +c.draw(p.reversed(), [trafo.translate(0, -2.5*R), deco.stroked([color.rgb.blue]), deco.curvedtext(label,textattrs=[text.halign.right],relarclenpos=1)])
> +c.draw(p.reversed(), [trafo.translate(2.5*R, -2.5*R), deco.stroked([color.rgb.blue]), deco.curvedtext(label)])
> +
> +c.writeEPSfile("textalongpath")
> +c.writePDFfile("textalongpath")
> diff --git a/examples/text/textalongpath.txt b/examples/text/textalongpath.txt
> new file mode 100644
> index 0000000..1737993
> --- /dev/null
> +++ b/examples/text/textalongpath.txt
> @@ -0,0 +1,5 @@
> +Text along path
> +
> +! In order to set text along a given path, you can use the `curvedtext()`
> +decorator. The examples show how you can position the text relative to the
> +path.
> diff --git a/pyx/deco.py b/pyx/deco.py
> index 656845f..a6a3359 100644
> --- a/pyx/deco.py
> +++ b/pyx/deco.py
> @@ -564,6 +564,65 @@ class text(deco, attr.attr):
> t.linealign(self.textdist, math.cos(angle), math.sin(angle))
> dp.ornaments.insert(t)
>
> +class curvedtext(deco, attr.attr):
> + """a text decorator for curved text
> +
> + - text: is typeset along the path to which this decorator is applied
> + - relarclenpos: position for the base point of the text (default: 0)
> + - arlenfrombegin, arclenfromend: alternative ways of specifying the position of the base point;
> + use of relarclenpos, arclenfrombegin and arclenfromend is mutually exclusive
> + - textattrs, texrunner: standard text arguments (defaults: [] resp None)
> +
> + """
> +
> + def __init__(self, text, textattrs=[],
> + relarclenpos=0, arclenfrombegin=None, arclenfromend=None,
> + texrunner=None):
> + if arclenfrombegin is not None and arclenfromend is not None:
> + raise ValueError("either set arclenfrombegin or arclenfromend")
> + self.text = text
> + self.textattrs = textattrs
> + self.relarclenpos = relarclenpos
> + self.arclenfrombegin = arclenfrombegin
> + self.arclenfromend = arclenfromend
> + self.texrunner = texrunner
> +
> + def decorate(self, dp, texrunner):
> + if self.texrunner:
> + texrunner = self.texrunner
> + import text as textmodule
> +
> + dp.ensurenormpath()
> + if self.arclenfrombegin is not None:
> + textpos = dp.path.begin() + self.arclenfrombegin
> + elif self.arclenfromend is not None:
> + textpos = dp.path.end() - self.arclenfromend
> + else:
> + # relarcpos is used if neither arcfrombegin nor arcfromend is given
> + textpos = self.relarclenpos * dp.path.arclen()
> +
> + c = canvas.canvas()
> +
> + singlecharmode=texrunner.singlecharmode # usually 0
> + texrunner.singlecharmode=1
> + t = texrunner.text(0, 0, self.text, self.textattrs)
> +
> + # copy over attr ops (colour...)
> + # isinstance(op, canvas._canvas) should not occur before ensuredvicanvas; should we even care to check?
> + [ c.insert(op) for op in t.items if not isinstance(op, canvas._canvas)]
> +
> + t.ensuredvicanvas()
> + texrunner.singlecharmode=singlecharmode
> +
> + items = t.dvicanvas.items
> + xs = [item.bbox().center()[0] for item in items]
> + trafos = dp.path.trafo([textpos +x for x in xs])
> + for x, op, atrafo in zip(xs, items, trafos):
> + c.insert(op, [trafo.translate(-x, 0), atrafo]) # reversed trafos: fix for change in canvas.py from r2728 to 2730
> +
> + dp.ornaments.insert(c)
> +
> +
>
> class shownormpath(deco, attr.attr):
>
> diff --git a/pyx/dvi/dvifile.py b/pyx/dvi/dvifile.py
> index b1e8123..d65e952 100644
> --- a/pyx/dvi/dvifile.py
> +++ b/pyx/dvi/dvifile.py
> @@ -112,12 +112,13 @@ class _restoretrafo(canvasitem.canvasitem):
>
> class DVIfile:
>
> - def __init__(self, filename, debug=0, debugfile=sys.stdout):
> + def __init__(self, filename, debug=0, debugfile=sys.stdout, singlecharmode=0):
> """ opens the dvi file and reads the preamble """
> self.filename = filename
> self.debug = debug
> self.debugfile = debugfile
> self.debugstack = []
> + self.singlecharmode = singlecharmode
>
> self.fonts = {}
> self.activefont = None
> @@ -197,7 +198,7 @@ class DVIfile:
> self.activetext[2].append(char)
> self.pos[_POS_H] += dx
>
> - if not advancepos:
> + if (not advancepos) or self.singlecharmode:
> self.flushtext(fontmap)
>
> def usefont(self, fontnum, id1234, fontmap):
> diff --git a/pyx/text.py b/pyx/text.py
> index 242a4b9..a7e94ac 100644
> --- a/pyx/text.py
> +++ b/pyx/text.py
> @@ -791,6 +791,7 @@ class texrunner:
> waitfortex=config.getint("text", "waitfortex", 60),
> showwaitfortex=config.getint("text", "showwaitfortex", 5),
> texipc=config.getboolean("text", "texipc", 0),
> + singlecharmode=0,
> texdebug=None,
> dvidebug=0,
> errordebug=1,
> @@ -812,6 +813,7 @@ class texrunner:
> self.waitfortex = waitfortex
> self.showwaitfortex = showwaitfortex
> self.texipc = texipc
> + self.singlecharmode = singlecharmode
> if texdebug is not None:
> if texdebug[-4:] == ".tex":
> self.texdebug = open(texdebug, "w")
> @@ -1031,7 +1033,7 @@ class texrunner:
> self.execute(None, self.defaulttexmessagesend + self.texmessagesend)
> dvifilename = "%s.dvi" % self.texfilename
> if not self.texipc:
> - self.dvifile = dvifile.DVIfile(dvifilename, debug=self.dvidebug)
> + self.dvifile = dvifile.DVIfile(dvifilename, debug=self.dvidebug, singlecharmode=self.singlecharmode)
> page = 1
> for box in self.needdvitextboxes:
> box.setdvicanvas(self.dvifile.readpage([ord("P"), ord("y"), ord("X"), page, 0, 0, 0, 0, 0, 0], fontmap=box.fontmap))
> @@ -1190,7 +1192,7 @@ class texrunner:
> raise e
> if self.texipc:
> if first:
> - self.dvifile = dvifile.DVIfile("%s.dvi" % self.texfilename, debug=self.dvidebug)
> + self.dvifile = dvifile.DVIfile("%s.dvi" % self.texfilename, debug=self.dvidebug, singlecharmode=self.singlecharmode)
> match = self.PyXBoxPattern.search(self.texmessage)
> if not match or int(match.group("page")) != self.page:
> raise TexResultError("box extents not found", self)
> @@ -1252,7 +1254,7 @@ class texrunner:
> "\\vfill\\supereject%%\n" % text, [texmessage.ignore])
> if self.texipc:
> if self.dvifile is None:
> - self.dvifile = dvifile.DVIfile("%s.dvi" % self.texfilename, debug=self.dvidebug)
> + self.dvifile = dvifile.DVIfile("%s.dvi" % self.texfilename, debug=self.dvidebug, singlecharmode=self.singlecharmode)
> else:
> raise RuntimeError("textboxes currently needs texipc")
> lastparnos = parnos
> --
> 1.7.7.602.g8c3f8
>
>
> ------------------------------------------------------------------------------
> All of the data generated in your IT infrastructure is seriously valuable.
> Why? It contains a definitive record of application performance, security
> threats, fraudulent activity, and more. Splunk takes this data and makes
> sense of it. IT sense. And common sense.
> http://p.sf.net/sfu/splunk-d2dcopy2
> _______________________________________________
> PyX-devel mailing list
> PyX...@li...
> https://lists.sourceforge.net/lists/listinfo/pyx-devel
--
by _ _ _ Dr. André Wobst, Amselweg 22, 85716 Unterschleißheim
/ \ \ / ) wo...@us..., http://www.wobsta.de/
/ _ \ \/\/ / PyX - High quality PostScript and PDF figures
(_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/
|