[reportlab-users] hard text clipping

Paul McNett p at ulmcnett.com
Wed Feb 16 00:21:51 EST 2005


rptl at s.rhythm.cx wrote:
> Hi. I have another question about something I'm not quite sure how to
> implement. I'm trying to draw some arbitrary text on the page which will be
> clipped to a certain rectangle. Nothing fancy - no wrapping, just draw what
> will fit and forget the rest.
> 
> I started by writing something like this:
> 
> 	# This draws a string of text on the specified canvas at position
> 	# posx,posy.  If the text is bigger than the passed size, it will
> 	# just be hard clipped.
> 	def block_text(canvas,text,posx,posy,sizex,sizey):
> 	        p = canvas.beginPath()
> 	        p.moveTo(posx,posy)
> 		p.lineTo(posx+sizex,posy)
> 		p.lineTo(posx+sizex,posy+sizey)
> 		p.lineTo(posx,posy+sizey)
> 		p.close()
> 		canvas.clipPath(p,stroke=0)
> 		canvas.drawString(posx,posy,text)
> 
> The first call to this function works as expected. The problem here is that
> subsequent calls to this function won't work - the prior clipping rectangle
> is still in effect. All new text draw outside of the last call's rectangle
> will be invisible.
> 
> Is there any way to "reset" the canvas's clipping region established by a
> clipPath call? Or, is there a better way to do what I'm trying to do? I
> looked at the Paragraph Flowable, but that seems overkill and as far as I
> can tell it doesn't want to do hard clipping.
> 
> I also looked at textobjects, but I didn't see any way to have those clipped
> to a particular size aside from the same way as above.

Hi, this is my first post to the list and I think I can actually answer 
the question so here goes. Someone with more experience will jump in if 
I give misdirected advice, I trust.

First, you should wrap your canvas operations in 
saveState()/restoreState() calls which make it easy to do an action and 
then revert the state of the canvas back to the way it was before, 
without having to know anything about how it was before.

Second, why make a path of lines when you can use a rectangle instead?

Here is my modification to your code which should work:

  	def block_text(canvas,text,posx,posy,sizex,sizey):
                 canvas.saveState()
  	        p = canvas.beginPath()
                 p.rect(posx,posy,sizex,sizey)
  		canvas.clipPath(p,stroke=0)
  		canvas.drawString(posx,posy,text)
                 canvas.restoreState()

I hope it helps. Your post helped me, actually: I had no idea there was 
even a path object, nor how to use it to clip text, which was something 
on my list of things to learn how to do. I was able to take your code, 
modify it to my needs, and drop it into my project and verify that it 
works, so thank you! :)

-- 
pkm ~ http://paulmcnett.com


More information about the reportlab-users mailing list