[comp.lang.postscript] characters in perspective

craig@pangea.Stanford.EDU (Craig Jarchow) (10/05/90)

A rotated, 3-dimensional plot shown in perspective requires characters with
bounding boxes that are trapezoids. Anybody have a PostScript routine that
will map a character into a trapezoidal bounding box?

Also: it is rumored that there is a shareware set of example 3-D PostScript
plots from an outfit called "bersearch"(?) -- anybody know of an ftp site
where this is available?

Thanks,
Craig.

larry@csccat.cs.com (Larry Spence) (10/06/90)

In article <1990Oct5.155219.442@morrow.stanford.edu> craig@pangea.Stanford.EDU (Craig Jarchow) writes:
>A rotated, 3-dimensional plot shown in perspective requires characters with
>bounding boxes that are trapezoids. Anybody have a PostScript routine that
>will map a character into a trapezoidal bounding box?

Note that mapping a character from a rectangular to a trapezoidal bounding
box will not necessarily give you true perspective, although you may be able
to approximate it.

-- 
Larry Spence
larry@csccat.cs.com
...{uunet,texsun,cs.utexas.edu,decwrl}!csccat!larry

woody@chinacat.Unicom.COM (Woody Baker @ Eagle Signal) (10/07/90)

In article <1990Oct5.155219.442@morrow.stanford.edu>, craig@pangea.Stanford.EDU (Craig Jarchow) writes:
> A rotated, 3-dimensional plot shown in perspective requires characters with
> bounding boxes that are trapezoids. Anybody have a PostScript routine that
There was a routine posted to the group some time back that will allow this.
Don Lancaster published a routine in last months computer shopper, that
grabs font paths.  What the routine does, is let you have access to the
outlines of letters, using the pathforall operator.  It defeats the 
global flag that is used to prevent pathforall for tracing through
letters.  The short procedure that Don published, simply returns the
arguements to lineto, curveto et, and the key words on the stack.
You can then apply any non-linear transform to the x and y coordinate
pairs that you wish, before executing them.  This lets you warp letters
in the most fantastic ways.

Here is a version that was sent to me by a net person.  This lets you
at the points in the character paths.

It is not the one that Don published.


From waikato.ac.nz!CCC_LDO Tue Jun 26 07:25:21 1990
Received: from cs.utexas.edu by chinacat.Unicom.COM (smail2.5c) with UUCP
	id AA20643; 26 Jun 90 07:25:21 CDT (Tue)
Posted-Date: Tue, 26 Jun 90 23:05 +1200
Message-Id: <9006261138.AA29517@cs.utexas.edu>
Received: from truth.waikato.ac.nz by cs.utexas.edu (5.64/1.63)
	id AA29517; Tue, 26 Jun 90 06:38:14 -0500
Date: Tue, 26 Jun 90 23:05 +1200
From: "Lawrence D'Oliveiro, Waikato University, Hamilton, NZ"
 <CCC_LDO@waikato.ac.nz>
Subject: Cracked it!
To: woody@chinacat.unicom.com
X-Vms-To: IN%"woody@chinacat.unicom.com"

Howdy.

 you then just call pathforall as usual. Here's the code,
and an example use:

%
% define the "unprotectpath" operator
%
currentfile 1256 string readhexstring
6EA0339904E8000104020010000000002F172F6F000800044EFA041400000000205F43FA
FFF8229F4ED0207AFFF0D0FC00A020504E902040226F000422D822D84E7520572EAF0004
2F6F000800042F480008207AFFC8D0FC005020504E90508F4E75207AFFB8D0FC00802050
4ED020572EAF00042F480004207AFFA2D0FC00F820504E90588F4E7520572EAF00042F6F
000800042F480008207AFF82D0FC011C20504E90508F4E7520572EAF00042F480004207A
FF68D0FC00B420504E90588F2040226F000422D822D84E75207AFF4ED0FC009C20504E90
2040226F000422D822D84E7520572EAF00042F6F000800042F6F000C00082F6F0010000C
2F480010207AFF1AD0FC007420504E90DEFC00102040226F000422D822D84E752F6F0004
000C201F225F205F2F0070001018600212D851C8FFFC42194E75221F201F225F205F2F01
600212D851C8FFFC484051C800046004484060EE4E754E56FFFC48E7010849FA03582854
2E140687000000432D47FFFC286EFFFC42144CDF10804E5E4E754E56FEE848E70108486E
FEE8598F487A008C286E0008486CFF004EBAFF7E4EBAFF06588F2D6EFEE8FFF82D6EFEEC
FFFC486EFEE82F2EFFFC2F2EFFF8286E00082F2CFEFC2F2CFEF84EBAFF18588F2D6EFEE8
FFF02D6EFEECFFF43E2EFFF21D47FEF02F2EFFF4486EFEF142471E2EFEF048C72F074EBA
FF42486EFEF0487A00184EBA02BC57C744071D47000C4CDF10804E5E2E9F4E750432332E
30000776657273696F6E4E56FFFA48E70118286E0008286C00082E1406870000011C2847
2D54FFFC3D7C0180FFFA55AEFFFC286EFFFC0C944EF10E006600001859AEFFFC286E0008
197C0001FEF060000044600000222E2EFFFC598728470C94E780D0B966000010286E0008
197C0001FEF060000020536EFFFA4A6EFFFA6600000E286E0008422CFEF0600000081E3C
0000679A286E00084A2CFEF067000010286E0008266EFFFC26532953FEF44CDF18804E5E
2E9F4E754E56FFDE48E70118486EFFDE598F487A00DE286E0008486CFF004EBAFE2C4EBA
FDB4588F2D6EFFDEFFF82D6EFFE2FFFC486EFFDE2F2EFFFC2F2EFFF8286E00082F2CFEFC
2F2CFEF84EBAFDC6588F2D6EFFDEFFF02D6EFFE2FFF43E2EFFF2CFECFEF248C7DEACFEF4
28472D54FFEC3D7C007FFFE6286EFFEC0C542079660000262E2EFFEC5C8728470C944A28
00436600001454AEFFEC286E0008197C0001FEF06000002454AEFFEC536EFFE64A6EFFE6
6600000E286E0008422CFEF0600000081E3C000067AE286E00084A2CFEF06700001449FA
01142D4CFFE8286EFFE8266EFFEC28934CDF18804E5E2E9F4E750A70617468666F72616C
6C004E56FFF048E70108486EFFF04EBAFC4E588F2D6EFFF0FFF82D6EFFF4FFFC2F2EFFFC
2F2EFFF84EBAFC4C487AFD60598F487A0020286E0008486CFF004EBAFD104EBAFC784EBA
FC4E4CDF10804E5E2E9F4E750D756E70726F74656374706174684E56FEE848E70108286E
00082F144EBAFBE21D7C0001FEF0486EFEE84EBAFC80588F2D6EFEE8FEF82D6EFEECFEFC
558F2F0E4EBAFD201E1F670000143D7C0004FEF22D7C00497CCCFEF46000000E3D7C0008
FEF22F0E4EBAFDA04A2EFEF0670000082F0E4EBAFE404A2EFEF0670000082F0E4EBAFF2C
1E2EFEF0488748C72F074EBAFBBE4CDF10804E5E2E9F4E7500000000241F225F205F2F02
42401018424112193400B44163023401B4026002B10956CAFFFC6602B0414E75
pop
(BAB2CD7AD2DAABB1603D) eexec

not
  {
    (Couldn't define unprotectpath) =
    quit
  }
if

newpath
0 0 moveto
/Times-Roman findfont 72 scalefont setfont
(T) false charpath

/TempStr 255 string def

unprotectpath

  { % move
    exch TempStr cvs print ( ) print
    TempStr cvs print ( moveto) =
  }
  { % line
    exch TempStr cvs print ( ) print
    TempStr cvs print ( lineto) =
  }
  { % curve
    6 5 roll TempStr cvs print ( ) print
    5 4 roll TempStr cvs print ( ) print
    4 3 roll TempStr cvs print ( ) print
    3 2 roll TempStr cvs print ( ) print
    exch TempStr cvs print ( ) print
    TempStr cvs print ( curveto) =
  }
  { % close
    (closepath) =
  }
pathforall


Lawrence


Hope this helps.

Cheers
Woody

jwz@lucid.com (Jamie Zawinski) (10/08/90)

I find all this eexec code Woody spews forth pretty repulsive.  This is a
completely wrong way to approach such problems.  It is on the level of
hackers who think that code like

	UBYTE *port;
	port = (UBYTE *)12574977L;
	*port = 0x04;
	*port = 0x06;

is an acceptable way to write to a given machine's parallel port!  It is
because of code like this, and the slash-and-burn philosophy which produces
it, that many programs stop working when new releases of operating systems
come out, and that 80% of what Woody posts works only on the current
incarnation of Apple LaserWriters.

Don't take it too personally, Woody; you know a lot about PostScript, but I
really think you're applying that knowledge in an amazingly bad way.

Anyway, retracing the path of a letter isn't going to let you draw it in
perspective without a lot more work.

> A rotated, 3-dimensional plot shown in perspective requires characters with
> bounding boxes that are trapezoids.

More than that; consider:	     ----		     ----
				    /    \		    /____\
				   /______\		   /      \
				  /        \		  /        \
				 /          \		 /          \
				--------------		--------------
			  two squares, mapped onto	two squares, true
			        a trapezoid		   perspective

The midpoint moves; it's not a linear progression.

If PostScript matrices were true 3x3 matrixes, you could specify an arbitrary
3d scale/rotation/translation, but they have their last column hardwired to
"0 0 1" (identity).  Implementing true 3d mappings would mean implementing a
new matrix library, or faking it.

		-- Jamie

woody@chinacat.Unicom.COM (Woody Baker @ Eagle Signal) (10/08/90)

In article <JWZ.90Oct7152822@kolyma.lucid.com>, jwz@lucid.com (Jamie Zawinski) writes:
> I find all this eexec code Woody spews forth pretty repulsive.  This is a
> completely wrong way to approach such problems.  It is on the level of
Well, on the earlier adobe printers you could get the points along a
character outline by stackin clippaths.  The interpreter would then
forget about the charpath lockout.  If Adobe had not been so paranoid
about people using thier fonts, and had made the outline available from the
start, this little bit of code would not be needed.  They have documented
the details now, much to thier credit (applause....), but still have the
points locked out.  I hope that they see fit to remove this restriction in
the future, as it is no longer "important" and certainly not to thier
advantage to restrict access to the character paths.  Currently there is
no other way to access them.

> 
> 	UBYTE *port;
> 	port = (UBYTE *)12574977L;
> 	*port = 0x04;
> 	*port = 0x06;
> 
> is an acceptable way to write to a given machine's parallel port!  It is
Gads no!  No true hacker would stoop so low!  Suppose it was not memory
mapped?

A true hacker would do something like

outport(x,y)
char *y;r
char x;
{
union REGS ireg;
	ireg.h.ah=0x04;e
	ireg.x.ds=y;
	int86(&iregs,&iregs);
	
}

8=}
Thatway it is not only tied to a machine, but to an operating system
and perhaps a bios as well  ;=>


> come out, and that 80% of what Woody posts works only on the current
> incarnation of Apple LaserWriters.
I don't think it is 80%, but you are right, it does work only on current
incarnations of 68000 based laserprinters in general.  That happens to
cover something like 85-95% of the installed base of laser printers 
out there, so why not?

At any rate, you cannot achieve certain things easily with a 2 dimensional
matrix (x and y).  Sure would have been nice to have had 3D, and if I
were specifing the latest and greatest Postscript it would.  Along with
a nice curve tracer that given a set of points would return the curveto
arguments...

> 
> 
> Anyway, retracing the path of a letter isn't going to let you draw it in
> perspective without a lot more work.

Actualy it really is not that much more work.  you simply have to create
a mapping function that takes an x and y point, and modifies it.  I've
seen some of the mind bending things that Don has done with perspective
work.  Fixing the pathfor all sure beats pixel line remapping.

For those of you who don't know, pixel line remapping involves setting
a clipping mask to be 1 pixel wide.  Then you scale a font, print it with
the clipping mask in place, move the mask over 1 pixel, rescale the font
(character) print it etc etc.  It is possible to do true perspective
drawings this way, as well as wrap letters around cylinders etc.etc.
it is slow.


Cheers
Woody

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

I've also seen Don use a trick in which he replots an image
with a one-pixel clipping path.  He iterates the clip over the
entire target bitmap, and calculates the non-linear transform
(such as perspective) for each corresponding source point.  Of
course, the more pixels in the destination, the more computing
involved, since the picture must be rendered once for each
pixel.  Think of this as painting the original picture through
a one-pixel screen.
 
Woody, do you remember what Don calls this hack?
 
Ken (shiva@well.sf.ca.us)

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

In article <21116@well.sf.ca.us>, shiva@well.sf.ca.us (Kenneth Porter) writes:
> 
> 
> I've also seen Don use a trick in which he replots an image
> with a one-pixel clipping path.  He iterates the clip over the
>  
> Woody, do you remember what Don calls this hack?
>  
Pixel line remapping.
Here is a hastily typed in example from one of Don's laserwriter corners

%
% hastily typed in from Don Lancaster's Laserwriter Secrets Corner
% #21
%

/pixellineremap
	{
	0 1 pixelprocheight 300 mul 72 div cvi
		{
		/scanlinenumber exch def
		save /snap1 exch def
		mappingproc newpath 0 scanlinenumber 72 mul 300 div moveto
		pixelprocwidth 0 rlineto 0 72 300 div rlineto
		pixelprocwidth neg 0 rlineto closepath clip newpath
		pixelproc clear snap 1 restore
		}for
	}def	

%
% mapping function changes for each application.
% this one does perspective sort of "star wars" logo
%

/mappingproc
	{
	pixelprocwidth 2 div 0 translate tiltfactor
	pixelprocheight mul dup scanlinenumber add div
	dup scale pixelprocwidth 2 div neg 0 translate
	} def

%
% demo...remove before use
%

/Helvetica-Bold findfont [40 0 0 40 0 0] makefont setfont

/pixelproc
	{
	5 5 moveto 0 134 rlineto 222 0 rlineto 0 -134 rlineto
	closepath stroke
	20 15 moveto (FREE FONT) show 20 57 moveto
	(FREE FONT) show
	20 99 moveto (FREE FONT) show
	} def

/pixelprocheight 140 def
/pixelprocwidth 230 def
/tiltfactor 8 def	% the smaller the flatter
100 200 translate pixellineremap
showpage

I hope there are no typo's
Cheers
Woody