jdaw1 wrote:
> Oh, it's that simple, thank you. So I'm going to use the following,
> not quite fully debugged.
> %!
> /TimesNewRomanPS-BoldMT 15 selectfont
> % - PathBBox llx lly urx ury
> % assesses only parts that will show visibly
> /PathBBox
> {
> 21 dict begin
> /TrivialDistance 0.0001 def % inconveniently in user space
> /MinMaxDefinedX false def
> /MinMaxDefinedY false def
> /x0y0Defined false def
> /MinX /undef def /MaxX /undef def
> /MinY /undef def /MaxY /undef def
> /SetMinMaxX % takes one parameter
> {
> 1 dict begin
> /x exch def
> MinMaxDefinedX
> {MaxX x lt {/MaxX x store} if MinX x gt {/MinX x store} if}
> {/MaxX x store /MinX x store /MinMaxDefinedX true store}
> ifelse
> end
> } def % SetMinMaxX
> /SetMinMaxY % takes one parameter
> {
> 1 dict begin
> /y exch def
> MinMaxDefinedY
> {MaxY y lt {/MaxY y store} if MinY y gt {/MinY y store} if}
> {/MaxY y store /MinY y store /MinMaxDefinedY true store}
> ifelse
> end
> } def % SetMinMaxY
> { % start move
> /y0 exch def /x0 exch def
> /x0y0Defined true def
> } % end of move
> { % start line
> /y1 exch def /x1 exch def
> x0 x1 sub abs TrivialDistance ge y0 y1 sub abs TrivialDistance ge
> or
> {
> x0 SetMinMaxX x1 SetMinMaxX
> y0 SetMinMaxY y1 SetMinMaxY
> } if % non-trivial line segment
> /y0 y1 def /x0 x1 def
> } % end of line
> { % start curve
> /y3 exch def /x3 exch def /y2 exch def /x2 exch def /y1 exch
> def /x1 exch def
> x0 x1 sub abs TrivialDistance ge x0 x2 sub abs TrivialDistance ge
> x0 x3 sub abs TrivialDistance ge or or {true} {
> y0 y1 sub abs TrivialDistance ge y0 y2 sub abs TrivialDistance ge
> y0 y3 sub abs TrivialDistance ge or or} ifelse
> {
> x0 SetMinMaxX x3 SetMinMaxX
> x1 MaxX gt x1 MinX lt x2 MaxX gt x2 MinX lt or or or
> {
> % Cubic: a t^3 + b t^2 + c t + x0
> /a x0 neg x1 3 mul add x2 3 mul sub x3 add def
> /b x0 x1 2 mul sub x2 add 3 mul def
> /c x1 x0 sub 3 mul def
> a abs 0 gt
> {
> % Solve first differential for zero
> /Discriminant 4 b b mul mul 12 a c mul mul sub def
> Discriminant 0 ge
> {
> /Discriminant Discriminant sqrt def
> [ {add} {sub} ]
> {
> /t -2 b mul Discriminant 4 -1 roll exec 6 a mul div
> def
> t 0 gt t 1 lt and {a t mul b add t mul c add t mul x0 add
> SetMinMaxX} if % if turning point between endpoints
> } forall % add, sub
> } if % has turning point
> } if % a abs 0 gt
> } if % x bounds outside MinX to MaxX
> y0 SetMinMaxY y3 SetMinMaxY
> y1 MaxY gt y1 MinY lt y2 MaxY gt y2 MinY lt or or or
> {
> /a y0 neg y1 3 mul add y2 3 mul sub y3 add def
> /b y0 y1 2 mul sub y2 add 3 mul def
> /c y1 y0 sub 3 mul def
> a abs 0 gt
> {
> /Discriminant 4 b b mul mul 12 a c mul mul sub def
> Discriminant 0 ge
> {
> /Discriminant Discriminant sqrt def
> [ {add} {sub} ]
> {
> /t -2 b mul Discriminant 4 -1 roll exec 6 a mul div
> def
> t 0 gt t 1 lt and {a t mul b add t mul c add t mul y0 add
> SetMinMaxY} if % if turning point between endpoints
> } forall % add, sub
> } if % has turning point
> } if % a abs 0 gt
> } if % y bounds outside MinY to MaxY
> } if % non-trivial curve segment
> /y0 y3 def /x0 x3 def
> } % end of curve
> { % start close
> } % end of close
> pathforall
> MinMaxDefinedX MinMaxDefinedY and {MinX MinY MaxX MaxY} {x0y0Defined
> {x0 y0 2 copy} {PathBBoxEmptyPathError} ifelse} ifelse
> end
> } def % PathBBox
> 90 5 div 1 add cvi
> {
> gsave newpath 0 0 moveto
> (ABEGHKLNTVWXZ1fhijklt) true charpath PathBBox 4 1 roll pop pop pop
> =
> grestore
> 5 rotate
> } repeat
> This returns the good enough (but still imperfect)
> 10.125
> 10.1755
> 10.1735
> 10.1672
> 10.1696
> 10.1842
> 10.1932
> 10.1873
> 10.1648
> 10.1867
> 10.1876
> 10.2004
> 10.1733
> 10.1746
> 10.1734
> 10.1774
> 10.1771
> 10.1789
> 10.17