[comp.lang.postscript] Specifying bboxes for text

Andrew.Mickish@cs.cmu.edu (05/30/91)

I'm trying to specify a bounding box in postscript that I want to put
text
into.  The problem is, I can't seem to scale the font properly to fit
inside
the bounding box that I define.  I think I have the horizontal scaling
working correctly -- I find the difference between the length of the
string
that postscript will generate and the length of the bounding box, and
then
use ASHOW to change the width of the characters.

However, getting the text to fit vertically is a pain.  According to the
picture on page 95 of the red PS reference manual, postscript is supposed
to print the tails of lower-case letters below the y-coordinate requested
by the user.  That is, if I say  20 20 moveto  /  (bug) show,  then the
bottom of the "g" will appear at about 17 vertically.

I have been trying the method suggested on page 96 which requires writing
the string twice:  once without stroking to figure out its bounding box,
and then once again at the actual position that I just calculated. 
However,
this seems inefficient and does not work with all fonts -- CHARPATH
crashes with a stack overflow error when it is given a
Courier-BoldOblique font, for example).

I would imagine that this problem has been encountered before.  Does
anyone know how I can solve this easily?

Thanks for looking at this.

--Andrew Mickish
  amickish@spice.cs.cmu.edu


P.S.  Here is an example program where I define some bounding boxes and
try to fit some text inside them.  This displays correctly on the gnu
previewer called 'gs' at CMU.



%!PS-Adobe-2.0


/FillShape
   {	% stack: fill-halftone
        % Use -1 to mean NIL
	% if fill-halftone >= 0, then fill the shape
	dup 0 ge
	  {gsave setgray fill grestore} {pop} ifelse
   } def

/StrokeShape
   {	% stack: line-thickness line-halftone
	% If no line is desired, pass -1 for line-thickness
	setgray	
	% if line-thickness >= 0, then draw the outline
	dup 0 ge
	 {setlinewidth stroke} {pop newpath} ifelse
   } def

/DrawRectangle
   {	% stack: left, top, width, height,
	%        line-thickness, line-halftone, fill-halftone
	/fill-halftone exch def
	/line-halftone exch def
	/line-thickness exch def
	/height exch def
	/width exch def
        newpath
	 moveto			% Go to the left,top corner
	 width 0 rlineto	% top side
	 0 height neg rlineto	% right side
	 width neg 0 rlineto	% bottom side
	 closepath		% left side
	 fill-halftone FillShape
	 line-thickness line-halftone StrokeShape
   } def


%%
%%  Functions for centering the text inside the bounding box
%%

/GetOffset
   {    % stack: bottom string
	gsave
           newpath
	   0 0 moveto
	   true charpath flattenpath pathbbox
 	   pop pop exch pop                     % Leave Ly on stack
	   sub
	grestore
   } def

/DrawText
   {	% stack: left bottom opal-width string size font-name
	findfont /font exch def
	/size exch def
	/string exch def
	font size scalefont setfont
	/x-dist			% Distance to add between each character
	   exch
	   string stringwidth pop sub	% Difference of opal - ps widths
	   string length
	   div			% Difference/number of characters
	   def
        string GetOffset	% New bottom = old bottom + offset
	moveto
	x-dist 0 string ashow
        stroke
   } def


180 218 94 ([48] bug) 24 /Helvetica-BoldOblique DrawText
180 242 94 24 1 0 -1 DrawRectangle

180 245 88 ([47] bug) 24 /Helvetica-Oblique DrawText
180 269 88 24 1 0 -1 DrawRectangle

180 272 90 ([46] bug) 24 /Helvetica-Bold DrawText
180 296 90 24 1 0 -1 DrawRectangle

180 299 84 ([45] bug) 24 /Helvetica DrawText
180 323 84 24 1 0 -1 DrawRectangle

180 326 87 ([44] bug) 24 /Times-BoldItalic DrawText
180 348 87 22 1 0 -1 DrawRectangle

180 351 84 ([43] bug) 24 /Times-Italic DrawText
180 374 84 23 1 0 -1 DrawRectangle

180 377 82 ([42] bug) 24 /Times-Bold DrawText
180 399 82 22 1 0 -1 DrawRectangle

180 402 81 ([41] bug) 24 /Times-Roman DrawText
180 424 81 22 1 0 -1 DrawRectangle

180 427 116 ([40] bug) 24 /Courier-BoldOblique DrawText
180 448 116 21 1 0 -1 DrawRectangle

180 451 113 ([39] bug) 24 /Courier-Oblique DrawText
180 472 113 21 1 0 -1 DrawRectangle

180 475 113 ([38] bug) 24 /Courier-Bold DrawText
180 496 113 21 1 0 -1 DrawRectangle

180 499 112 ([37] bug) 24 /Courier DrawText
180 520 112 21 1 0 -1 DrawRectangle

10 298 71 ([36] bug) 18 /Helvetica-BoldOblique DrawText
10 316 71 18 1 0 -1 DrawRectangle

10 319 67 ([35] bug) 18 /Helvetica-Oblique DrawText
10 337 67 18 1 0 -1 DrawRectangle

10 340 70 ([34] bug) 18 /Helvetica-Bold DrawText
10 358 70 18 1 0 -1 DrawRectangle

10 361 65 ([33] bug) 18 /Helvetica DrawText
10 379 65 18 1 0 -1 DrawRectangle

10 382 63 ([32] bug) 18 /Times-BoldItalic DrawText
10 399 63 17 1 0 -1 DrawRectangle

10 402 62 ([31] bug) 18 /Times-Italic DrawText
10 419 62 17 1 0 -1 DrawRectangle

10 422 62 ([30] bug) 18 /Times-Bold DrawText
10 439 62 17 1 0 -1 DrawRectangle

10 442 58 ([29] bug) 18 /Times-Roman DrawText
10 459 58 17 1 0 -1 DrawRectangle

10 462 86 ([28] bug) 18 /Courier-BoldOblique DrawText
10 478 86 16 1 0 -1 DrawRectangle

10 481 84 ([27] bug) 18 /Courier-Oblique DrawText
10 497 84 16 1 0 -1 DrawRectangle

10 500 83 ([26] bug) 18 /Courier-Bold DrawText
10 516 83 16 1 0 -1 DrawRectangle

10 519 82 ([25] bug) 18 /Courier DrawText
10 535 82 16 1 0 -1 DrawRectangle

180 538 49 ([24] bug) 12 /Helvetica-BoldOblique DrawText
180 550 49 12 1 0 -1 DrawRectangle

180 553 48 ([23] bug) 12 /Helvetica-Oblique DrawText
180 565 48 12 1 0 -1 DrawRectangle

180 568 45 ([22] bug) 12 /Helvetica-Bold DrawText
180 580 45 12 1 0 -1 DrawRectangle

180 583 43 ([21] bug) 12 /Helvetica DrawText
180 595 43 12 1 0 -1 DrawRectangle

180 598 47 ([20] bug) 12 /Times-BoldItalic DrawText
180 610 47 12 1 0 -1 DrawRectangle

180 613 43 ([19] bug) 12 /Times-Italic DrawText
180 625 43 12 1 0 -1 DrawRectangle

180 628 41 ([18] bug) 12 /Times-Bold DrawText
180 640 41 12 1 0 -1 DrawRectangle

180 643 42 ([17] bug) 12 /Times-Roman DrawText
180 655 42 12 1 0 -1 DrawRectangle

180 658 56 ([16] bug) 12 /Courier-BoldOblique DrawText
180 670 56 12 1 0 -1 DrawRectangle

180 673 55 ([15] bug) 12 /Courier-Oblique DrawText
180 685 55 12 1 0 -1 DrawRectangle

180 688 55 ([14] bug) 12 /Courier-Bold DrawText
180 700 55 12 1 0 -1 DrawRectangle

180 703 53 ([13] bug) 12 /Courier DrawText
180 715 53 12 1 0 -1 DrawRectangle

10 567 42 ([12] bug) 10 /Helvetica-BoldOblique DrawText
10 577 42 10 1 0 -1 DrawRectangle

10 580 39 ([11] bug) 10 /Helvetica-Oblique DrawText
10 590 39 10 1 0 -1 DrawRectangle

10 593 40 ([10] bug) 10 /Helvetica-Bold DrawText
10 603 40 10 1 0 -1 DrawRectangle

10 606 30 ([9] bug) 10 /Helvetica DrawText
10 616 30 10 1 0 -1 DrawRectangle

10 619 32 ([8] bug) 10 /Times-BoldItalic DrawText
10 629 32 10 1 0 -1 DrawRectangle

10 632 29 ([7] bug) 10 /Times-Italic DrawText
10 642 29 10 1 0 -1 DrawRectangle

10 645 30 ([6] bug) 10 /Times-Bold DrawText
10 655 30 10 1 0 -1 DrawRectangle

10 658 27 ([5] bug) 10 /Times-Roman DrawText
10 667 27 9 1 0 -1 DrawRectangle

10 670 42 ([4] bug) 10 /Courier-BoldOblique DrawText
10 679 42 9 1 0 -1 DrawRectangle

10 682 41 ([3] bug) 10 /Courier-Oblique DrawText
10 691 41 9 1 0 -1 DrawRectangle

10 694 41 ([2] bug) 10 /Courier-Bold DrawText
10 703 41 9 1 0 -1 DrawRectangle

10 706 40 ([1] bug) 10 /Courier DrawText
10 715 40 9 1 0 -1 DrawRectangle



showpage