[comp.lang.postscript] limitcheck in flattenpath

jmd@franklin.ee.umr.edu (Jim Dumser) (11/13/90)

I've been trying to hand code some figures in postscript, but I keep getting
limitcheck errors in flattenpath when trying to center text.  It doesn't
happen for all strings; only for longer strings.  Basically, my routine to
center text calls 'hiwi':

/hiwi {gsave newpath 0 0 moveto true charpath flattenpath pathbbox 4 2 roll
pop pop grestore} def

which returns dx dy on the stack.  When I call it as

(Non-inverting Op Amp Circuit) hiwi

I get a limitcheck.  Removing ' Circuit' from the string, it runs fine.
(I'm using 15 pt Times-Roman, but point size is irrelevant.)  Both work fine
when fed to ralpage.  The printer is a LaserWriter.

Anyone see something wrong with my code?  A workaround perhaps (other than
printing 2 strings :-) ?

Jim

+-------------------------------------------------------+
|  The fear of the Lord is the beginning of knowledge,  |
| but fools despise wisdom and discipline. Proverbs 1:7 |
|-------------------------------------------------------|
|    Internet: jmd@ee.umr.edu     |  M S - D O S . . .  |
|    UUCP: ...uunet!umree!jmd     |    Just say "NO!"   |
+-------------------------------------------------------+

rberlin@birdland.sun.com (Rich Berlin) (11/13/90)

I've experienced the same problem.  Basically, there's a limit to the
number of segments that the path can contain, and charpath eats LOTS of
them.  See the footnote on charpath, Red Book page 89.  It says, in
part, "if possible, it is best to deal with only one character's path
at a time."

Based on this, I suggest the following workaround.  (But first I
should ask something: the code you've written calculates the bounding
box of the string.  Are you really centering in both dimensions?  If
not, I think the stringwidth operator should give you what you want,
much more cheaply.)

/max where {
    pop
}{
    /max {2 copy lt {exch pop} {pop} ifelse} bind def
} ifelse

/hiwi {
    0 0 3 -1 roll
    { % forall--loop over all characters in string.
	gsave
	    % Put the char into a string
	    1 string dup 0 4 -1 roll put

	    % Get the height and width of the single char
	    newpath 0 0 moveto
	    true charpath flattenpath pathbbox 4 2 roll pop pop

            % Now cumulate the result.  The following line
            % assumes a horizontal writing direction.  If the writing
            % direction is vertical, interchange `add' and `max'.
            exch 4 -1 roll add 3 1 roll max
	grestore
    } forall
} bind def

-- Rich

glenn@heaven.woodside.ca.us (Glenn Reid) (11/13/90)

In article <1642@umriscc.isc.umr.edu> jmd@ee.umr.edu (Jim Dumser) writes:
>I've been trying to hand code some figures in postscript, but I keep getting
>limitcheck errors in flattenpath when trying to center text.  It doesn't
>happen for all strings; only for longer strings.  Basically, my routine to
>center text calls 'hiwi':
>
>/hiwi {gsave newpath 0 0 moveto true charpath flattenpath pathbbox 4 2 roll
>pop pop grestore} def

Your code is fine; you're just hitting an implementation limit (the number
of path elements allowed in the current path).  The only workaround is to
have fewer elements in the path.  There are a couple of ways to do this.
One is to use "forall" to do "flattenpath pathbbox" on each element of the
string and then to accumulate the bounding box for the whole string.  A bit
of work, fairly messy, but it should work for arbitrarily long strings.

There are two other possibilities, assuming you're just centering text and
can tolerate slight errors in the bounding boxes (there are probably slight
errors anyway).  One is to omit the "flattenpath" altogether.  This will mean
that some of the control points on the bezier curves get included in the
bounding box, but it should still center things quite reasonably.  The
other possibility is to increase the flatness parameter before you call
flattenpath, like this:

/hiwi { %def
    gsave
	newpath 0 0 moveto false charpath	% you should use "false"
	5 setflat flattenpath pathbbox		% note "5 setflat"
	4 2 roll pop pop			% otherwise the same
    grestore
} bind def


% Glenn

-- 
 Glenn Reid				RightBrain Software
 glenn@heaven.woodside.ca.us		PostScript/NeXT developers
 ..{adobe,next}!heaven!glenn		415-851-1785

woody@chinacat.Unicom.COM (Woody Baker @ Eagle Signal) (11/13/90)

In article <1642@umriscc.isc.umr.edu>, jmd@franklin.ee.umr.edu (Jim Dumser) writes:
> limitcheck errors in flattenpath when trying to center text.  It doesn't
The problem is totaly implementation limited.  There is nothing that you can
do about it, except do things diffrently.  I certainly would not do charpath
flattenpath to center text.  Try (string ) stringwidth.  This will give
you the width of the string.  From there, it is fairly trivial to center the
text horizontaly.  To center the text verticaly, however, is something else.
What I'd do is to get the bounding box for the FONT from the font
directory.  This will allow you to determine the total height for the
hightest character at your font size.  Divide it by 2 and use that as 
a fixed dy value.  Actually, something other than 2 looks better.
> 
> which returns dx dy on the stack.  When I call it as
> 

Cheers
Woody

shiva@well.sf.ca.us (Kenneth Porter) (11/21/90)

There seems to be some confusion about the desired result of
the char-fitting code. The idea was to, given a box, fit a
character so that it *exactly* fit the box. The box could be as
big as a page.
 
stringwidth won't work here because it gives the change in the
current point. The character origin is not co-incident with the
bounding box origin, and the character width (returned by
stringwidth) is not the same as the right-most edge of the
bounding box, nor is it the same as the width of the bounding
box. A character can bulge outside of its origin, width and
baseline, or may not reach all the way to any of these
dimensions.
 
The only way to know for sure is to use the character bounding
box calculated at the desired size (to compensate for hinting).
 
The font bbox will give an even worse value for this purpose
than stringwidth.
 
Ken (shiva@well.sf.ca.us)