Hi again, I'm kinda getting to like the deco concept... I remembered an old post by Andre, showing a method (due to Jörg, I think) for laying out text along a curve. I adjusted it to the current API and coded it as a decorator dubbed deco.curvedtext(). I'm attaching a simple example (how to achieve typical line ups) and the code. The code goes into deco.py (current svn). I'm unsure about the following:
a) Is the patch to dvifile.dvifile.putchar appropriate for going into the trunk, or are there side effects (I don't know that module)? b) Is it appropriate to attach eps examples here? c) What's the best format for code suggestions? I'd be happy to send diffs, but the patch mentioned above made it somehow inconvenient here (the "local" patch I'm applying won't be the final form, of course). As for the other text decorators (text as it is or (t)text as suggested by me recently or text rotated parallel to the curve [tangential labels]): I imagine a universal decorator deco.insert() would be best which inserts a given canvas at certain points of the path, with or without a user specified alignment, with or without rotation with respect to the absolute co system or the local path tangent. Then, all text decorators (except for deco.curvedtext) would be simple calls to deco.insert(text.text(...)). But one could also easily decorate with symbols "moving" along the path and such. Please tell me what you think, or else I might start hacking away ;) Cheers, Michael
import os,sys
sys.path.insert(0, os.environ.get("HOME")+"/lib/python/PyX-svn")
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(__file__[:-3],fittosize=1, paperformat=document.paperformat.A4)
textalongpath.eps
Description: PostScript document
import dvifile,type1font
oldputchar = dvifile.dvifile.putchar
def newputchar(self, char, advancepos=1):
oldputchar(self, char, advancepos)
self.flushtext()
dvifile.dvifile.putchar = newputchar
class curvedtext(deco, attr.attr):
"""a text decorator for curved text"""
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()
t = texrunner.text(0, 0, self.text, self.textattrs)
for op in t.items: # copy over attr ops (colour...)
if not isinstance(op, canvas._canvas): # should not occur before
ensuredvicanvas
c.insert(op)
t.ensuredvicanvas()
for op in t.dvicanvas.items:
if isinstance(op, type1font.text_pt):
x = textpos + unit.t_pt*(op.x_pt+op.width_pt/2) # Make sure we
rotate with respect to the middle of the character.
op.x_pt = -op.width_pt/2
c.insert(op, [dp.path.trafo(x)])
else:
c.insert(op)
dp.ornaments.insert(c)
