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)

Attachment: 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)

Reply via email to