[comp.lang.postscript] concat strings

davis@pacific.mps.ohio-state.edu ("John E. Davis") (11/01/90)

Hi,

   What is the easies way I can concatenate two strings of different fonts to
produce a third string?  I don't care if the two original strings are lost in
the process-- I only need the result.  An example would be greatly appreciated.

--
John

  bitnet: davis@ohstpy
internet: davis@pacific.mps.ohio-state.edu

green@ohrd.uucp (Martin Green KR260_x7060) (11/02/90)

In article <DAVIS.90Oct31164243@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu  (John E. Davis) writes:
>Hi,
>
>   What is the easies way I can concatenate two strings of different fonts to
>produce a third string?  I don't care if the two original strings are lost in
>the process-- I only need the result.  An example would be greatly appreciated.

I have developed a general string handling package.  It may seem like
overkill but it has been fairly widely used around here, especially for
labelling graphs.
_______________________________
%!	text.pro
%	
%	Copyright (C) 1990 Martin A. Green
%
%	Last edited: Fri Nov  2 09:09:22 EST 1990
%	
%	This program is free software; you can redistribute it and/or modify
%	it under the terms of the GNU General Public License as published by
%	the Free Software Foundation; either version 1, or (at your option)
%	any later version.
%	
%	This program is distributed in the hope that it will be useful,
%	but WITHOUT ANY WARRANTY; without even the implied warranty of
%	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%	GNU General Public License for more details.
%	
%	You should have received a copy of the GNU General Public License
%	along with this program; if not, write to the Free Software
%	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%
% ----------------------------------------------------------------------
%	Text manipulation functions including super- and sub-scripts,
%	multiple fonts and sizes, centering and right alignment, and
%	full justification.

%	Functions are also provided to permit printing of characters precisely
%	centred on the current point, such as would be required for marking
%	data points on a plot.

%	[string1 sups [string2 string3 subs string4] font2 string5] display
%		should print string1 with the current font
%		then go into superscript mode for string2 and string3
%		then print string4 as a subscript to string3
%		then return to the original font, followed by a change to font2
%		and finally print string5.
%		The positioning and angle of the printed text are
%		determined by the /textalign and /textangle variables.

%	Font selection
%		To select Times-Roman 12 point font use:	12 TR
%
/TR	{dup /PS exch def 
		/Times-Roman findfont exch scalefont setfont} def
/TB	{dup /PS exch def
		/Times-Bold findfont exch scalefont setfont} def
/TI	{dup /PS exch def
		/Times-Itatic findfont exch scalefont setfont} def
/TBI	{dup /PS exch def
		/Times-BoldItalic findfont exch scalefont setfont} def
/H	{dup /PS exch def
		/Helvetica findfont exch scalefont setfont} def
/HB	{dup /PS exch def
		/Helvetica-Bold findfont exch scalefont setfont} def
/HO	{dup /PS exch def
		/Helvetica-Oblique findfont exch scalefont setfont} def
/HBO	{dup /PS exch def
		/Helvetica-BoldOblique findfont exch scalefont setfont} def
/S	{dup /PS exch def /Symbol findfont exch scalefont setfont} def
/C	{dup /PS exch def /Courier findfont exch scalefont setfont} def

/STRING (a) type cvlit def
/ARRAY [0] type cvlit def
/LEFT -1 def
/CENTRE 0 def
/RIGHT 1 def
/CENTER CENTRE def

/fontstore 5 array def
/vshift 5 array def
/fontlevel 0 def
/pushfont {
	fontstore exch [ exch PS ] fontlevel exch put
	/fontlevel fontlevel 1 add def
} def
/popfont {
	0 vshift fontlevel get neg rmoveto
	vshift fontlevel 0 put
	/fontlevel fontlevel 1 sub def
	fontstore fontlevel get aload pop /PS exch def setfont
} def

/sups {		%	adjust position and reduce font size
	{currentfont dup pushfont .8 scalefont setfont
	vshift fontlevel PS .4 mul put
	0 PS .4 mul rmoveto
	/PS PS .8 mul def}
} def
/subs {		%	adjust position and reduce font size
	{currentfont dup pushfont .8 scalefont setfont
	vshift fontlevel PS -.3 mul put
	0 PS -.3 mul rmoveto
	/PS PS .8 mul def}
} def

/isstring {		%	return true if argument is a string
	type cvlit STRING eq
} def
/isarray {		%	return true if argument is an array
	type cvlit ARRAY eq
} def

/displaywidth {		%	compute width of complex text array
	/textwidth 0 def
	/textheight PS def
	/fontlevel 0 def
	/displevel 0 def
	{		%	step through array elements
		dup isstring {
			stringwidth pop /textwidth exch textwidth add def
			fontlevel displevel sub 1 eq {popfont} if
		} {
		dup xcheck {
			exec
		} {
		dup isarray {
			displaywidth2
			fontlevel displevel sub 1 eq {popfont} if
		} { %	error handler
			pop
		} ifelse } ifelse } ifelse
	} forall
} def

/displaywidth2 {
	/displevel displevel 1 add def
	{		%	step through array elements
		dup isstring {
			stringwidth pop /textwidth exch textwidth add def
			fontlevel displevel sub 1 eq {popfont} if
		} {
		dup xcheck {
			exec
		} {
		dup isarray {
			displaywidth2
			fontlevel displevel sub 1 eq {popfont} if
		} { %	error handler
			pop
		} ifelse } ifelse } ifelse
	} forall
	/displevel displevel 1 sub def
} def

/display {
	currentpoint 3 -1 roll
	/textwidth 0 def
	exactwidth 0 ne textalign LEFT ne or  % compute dimensions if required
		{dup displaywidth} if

	%	adjust starting position and angle
	3 1 roll moveto
	textalign LEFT ne {
		textalign RIGHT eq { textwidth neg 0 rmoveto }
		{ textwidth 2 div neg 0 rmoveto } ifelse
	} if
	%	print text
	/fontlevel 0 def
	/displevel 0 def
	{
		dup isstring {
			show
			fontlevel displevel sub 1 eq {popfont} if
		} {
		dup xcheck {
			exec
		} {
		dup isarray {
			display2
			fontlevel displevel sub 1 eq {popfont} if
		} { %	error handler
			pop
		} ifelse } ifelse } ifelse
	} forall
} def

/display2 {
	/displevel displevel 1 add def
	{	%	step through array elements
		dup isstring {
			show
			fontlevel displevel sub 1 eq {popfont} if
		} {
		dup xcheck {
			exec
		} {
		dup isarray {
			display2
			fontlevel displevel sub 1 eq {popfont} if
		} { %	error handler
			pop
		} ifelse } ifelse } ifelse
	} forall
	/displevel displevel 1 sub def
} def

/xshow {
	dup pointdict exch known {
		pointdict begin load end currentpoint 3 -1 roll
		currentfont exch aload pop
		rmoveto exec show setfont moveto
	} { pop } ifelse
} def

/xsetup {
	%	/name (string) {nn FF} xsetup
	pointdict begin
	3 -1 roll [ 4 2 roll		% /name [ ( ) { }
	dup exec 1 index		% /name [ ( ) { } ( )   -- font set
	newpath 0 0 moveto false charpath flattenpath pathbbox
	4 2 roll 2 copy 6 -2 roll
	3 -1 roll sub -.5 mul 3 1 roll sub .5 mul 	% /name [ ( ) { } dy dx
	4 -1 roll sub 3 1 roll exch sub
	] def		% /name [ ( ) { } dx dy ] def
	end
} def

/pointdict 50 dict def
/. (\264) {12 TR} xsetup
/a (a) {8 H} xsetup
/b (b) {8 H} xsetup
/c (c) {8 H} xsetup
/d (d) {8 H} xsetup
/e (e) {8 H} xsetup
/f (f) {8 H} xsetup
/*1 (1) {8 H} xsetup
/*2 (2) {8 H} xsetup
/*3 (3) {8 H} xsetup
/*4 (4) {8 H} xsetup
/*5 (5) {8 H} xsetup
/*6 (6) {8 H} xsetup
/*7 (7) {8 H} xsetup
/*8 (8) {8 H} xsetup
/*9 (9) {8 H} xsetup
/x (x) {8 H} xsetup
/o (o) {8 H} xsetup
/O (O) {8 H} xsetup
/+ (+) {10 H} xsetup
/- (-) {10 S} xsetup
/* (*) {10 S} xsetup
/| (|) {8 H} xsetup
/de (o) {5 H} xsetup
/cix (\250) {8 H} xsetup
/*D (D) {8 S} xsetup
/diamond (\250) {8 S} xsetup
/mu (\264) {8 S} xsetup
/bu (\267) {8 S} xsetup
/xci (\304) {8 S} xsetup
/+ci (\305) {8 S} xsetup
/opendiamond (\340) {8 S} xsetup

/exactwidth 0 def
/textalign CENTRE def

/i {72 mul} def
4.25 i 6 i moveto
12 TR
%[(test) subs [(double) subs (sub)] sups (sup) ( test2)] display
%4.25 i 2 i moveto 0 2 i rlineto
%3.25 i 3 i moveto 2 i 0 rlineto stroke
%4.25 i 3 i moveto /x xshow
%4.75 i 3.5 i moveto /. xshow

/showx { isarray {
	st 1 blank putinterval
	currentpoint 3 -1 roll dup xshow 3 1 roll
	2 copy exch 36 add exch 3 sub moveto 12 H 3 -1 roll
	(                 ) cvs st exch 1 exch putinterval st show
	13 sub moveto
	} {pop} ifelse
} def

/showmarkers {
	/st 18 string def st 0 (/) putinterval
	/blank (                 ) def
	pointdict {showx} forall
} def

/markerpage {
	erasepage
	4.25 i 10 i moveto
	16 HB [(Data Markers For PSplot)] display
	/textalign LEFT def
	1 i 9 i moveto 13 H
	(To print marker at current point use, for example:  /+ci xshow) show
	1 i 8.5 i moveto
	showmarkers
	showpage
} def
--------------------------------
Martin Green                        UUCP     :  ..!torsqnt!ohrd!green
Ontario Hydro Research Division     Telephone:  (416)231-4111 Ext7060
800 Kipling Ave
Toronto, Ontario, CANADA, M8Z5S4
-- 
Martin Green                        UUCP     :  ..!torsqnt!ohrd!green
Ontario Hydro Research Division     Telephone:  (416)231-4111 Ext7060
800 Kipling Ave
Toronto, Ontario, CANADA, M8Z5S4

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

In article <DAVIS.90Oct31164243@pacific.mps.ohio-state.edu> davis@pacific.mps.ohio-state.edu  (John E. Davis) writes:
>Hi,
>
>   What is the easies way I can concatenate two strings of different fonts to
>produce a third string?  I don't care if the two original strings are lost in
>the process-- I only need the result.  An example would be greatly appreciated.

Here's an example string-concatenating procedure that is in my new book,
"Thinking in PostScript" (which I just saw lots of copies of in our local
bookstore!); I'll leave out the error checking code that raises a typecheck
if it isn't passed two strings.

There are lots of ways to do it, naturally, but here's one approach:

/concatenate
{ %def
	dup length 2 index length add string
	dup 0 4 index putinterval
	dup 4 -1 roll length 4 -1 roll putinterval
} bind def


% Glenn

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

stanley@phoenix.com (John Stanley) (11/06/90)

glenn@heaven.woodside.ca.us (Glenn Reid) writes:
> In article <DAVIS.90Oct31164243@pacific.mps.ohio-state.edu> davis@pacific.mps
> >Hi,
> >
> >   What is the easies way I can concatenate two strings of different fonts t
> >produce a third string?  I don't care if the two original strings are lost i
> >the process-- I only need the result.  An example would be greatly appreciat
> 
> Here's an example string-concatenating procedure that is in my new book,
> "Thinking in PostScript" (which I just saw lots of copies of in our local
> bookstore!); I'll leave out the error checking code that raises a typecheck
> if it isn't passed two strings.

   Is the font information stored with a string, or does the font
information come into play only at the time the string is converted to a
drawable form? (Either a show or charpath or like operation.)

   If the font information is not carried with the string, then
concatenating two strings will mean any drawing/pathing operators that
follow will produce the one resultant string in one font. In other words,
you could NOT concatenate two strings of two different fonts to produce
one string of two fonts. 

   The original post seemed to stress the two fonts combined on one
string. Is this really what the poster requested, or did I misread this?





<> "Aneth!  That's a charming place!" "You've been to Aneth?" 
<> "Yes, but not yet." -- The Doctor and Seth, "The Horns of Nimon".
><
<> "Sanity check!" "Sorry, we can't accept it, it's from out of state." - me

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

In article <F2s7R1w163w@phoenix.com> stanley@phoenix.com (John Stanley) writes:
>
>glenn@heaven.woodside.ca.us (Glenn Reid) writes:
>> In article <DAVIS.90Oct31164243@pacific.mps.ohio-state.edu> davis@pacific.mps
>> >   What is the easies way I can concatenate two strings of different fonts t
>> >produce a third string?

>   Is the font information stored with a string, or does the font
>information come into play only at the time the string is converted to a
>drawable form? (Either a show or charpath or like operation.)

>   The original post seemed to stress the two fonts combined on one
>string. Is this really what the poster requested, or did I misread this?

Gulp.  I didn't see the "...of different fonts..." in the original posting.

You're right; a string does not have any font information associated with
it.  It's just an ASCII string (usually, barring Kanji or something).

There's no way to concatenate two strings in different fonts.  In fact,
the question makes little sense.  A string is a string.  If you have two
strings and you want one, you can tack them together.  But if each string
needs to be printed in a separate font, you have to keep them separate.

Perhaps this is a better answer to the original question:  if you have
two strings that must be printed in two different fonts, simply "show"
one of them, change the font, and "show" the next one.  The current point
will be left at the end of the first string, and the second string will
begin where the first one left off.

Sorry about the confusion.  Maybe the original poster could clarify a bit?

-- 
 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/08/90)

In article <F2s7R1w163w@phoenix.com>, stanley@phoenix.com (John Stanley) writes:
> 
> glenn@heaven.woodside.ca.us (Glenn Reid) writes:
> > In article <DAVIS.90Oct31164243@pacific.mps.ohio-state.edu> davis@pacific.mps
>    Is the font information stored with a string, or does the font

No it is not carried with the strings.
> 
> follow will produce the one resultant string in one font. In other words,
> you could NOT concatenate two strings of two different fonts to produce
> one string of two fonts. 

This is correct.  You would have to create a partial path in 1 font, and
append it to a partial path in the second font.
A somewhat simpler way, is to create a procedure that takes a string,
and looks for some escape sequence in the string.  If it is found,
then isolate a command code, and execute a procedure to change the
fonts.  This is the way most printer emulators written in postscript
would work.  It is a bit slower, but allows you to mix fonts freely.


Cheers
Woody