[comp.sources.d] Apollo Driver for PostScript Interpreter

tullemns@nvpna1.UUCP ( Henk Tullemans 43761) (06/01/88)

The following archive contains an Apollo driver for the PostScript Interpreter
written by Crispin Goswell, Rutherford Appleton Laboratory. The Apollo driver
can be found in the file hard.c.

Writing an Apollo driver for this PostScript Interpreter consists of writing 11
routines contained in the file hard.c. One routine i.e. StringFromHardware is
not written, maybe someone else will find some time to implement this routine.
The implementation of the other routines is maybe not the best one but it works.
I think it will be a good start for those who want to write a better
Apollo driver.

The archive contains also some modified source files to fix some "bugs"
The bug fixes are surrounded by the following line:

/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */

The most important modifications were made in source lines with the
following construction (or simular):

 	 	(*(*s & MOVETO ? MoveTo : LineTo))
 	  		(p, ExtToInt (po));        

These lines were substituted by the following lines (or simular):

		if (*s & MOVETO)
			MoveTo (p, ExtToInt (po));        
	        else
			LineTo (p, ExtToInt (po));        

If these modifications are not made some strange effects occur when
a string or a circle (or part of a circle) is displayed on the screen.
A line will be painted before each element of a string or (part of)
a circle. Executing "(I) show" will show the above described effect.
(PS. open first a window with the command "A4-x")

Beside hard.c and some source files the archive contains also a makefile
for compilation of an Apollo version of PS.

Some final remarks about the Apollo driver:
- only tested in the program PS (not in postscript or viewer).
- tested under SR 9.6 and 9.7.
- be aware of printer specific commands in postscript files
  (this is the most frequent error)
- most used window commands: A4-x --- reduced A4 screen fits on 1024*800 screen
                             A4   --- normal A4 screen fits on 1280*1024 screen
                             L4   --- landscape A4 screen fits on all screens

Enjoy ..... (especially raygun)

----------------------------------- cut here -----------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  font.c hard.c image.c path.c protocol.c stroke.c makefile
# Wrapped by tullemns@nvpna1 on Tue May 31 22:32:47 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'font.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'font.c'\"
else
echo shar: Extracting \"'font.c'\" \(16804 characters\)
sed "s/^X//" >'font.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X#include "main.h"
X#include "graphics.h"
X
X#define MOVETO	0x80
X#define BYTE	0xFF
X
X#define FONT_USER	3
X
static struct show_context show_stack [MAXGSAVES];
X 
int MoveTo (), LineTo ();
X
static int PCurrentFont ();
static int PDefineFont ();
static int PFindFont ();
static int PScaleFont ();
static int PMakeFont ();
static int PSetFont ();
X
static int BuildHershey ();
static int PShow ();
static int PWidthShow ();
static int PAShow ();
static int PAWidthShow ();
static int PStringWidth ();
static int PAdjust ();
X
static Vector GetMetrics ();
X
static int ShowString ();
static int ShowStop ();
static int ShowStopped ();
X
Object Fid, FD, FontMatrix, FontType, Encoding, FontBBox, OpShowStop, OpShowString, OpStopped;
Object UserShow, CharStrings, Metrics, BuildChar, FontName;
X
static last_fid = 0;
X
static int Update ();
X
static Point zeroPoint;
static HardPoint zeroHardPoint;
X
extern HardPoint NewHardPoint (), ExtToInt ();
extern Matrix HardPointTranslate ();
X
InitFont ()
X {
X 	Fid 		= NameFrom ("FID");
X 	FontMatrix 	= NameFrom ("FontMatrix");
X 	FontType	= NameFrom ("FontType");
X 	Encoding	= NameFrom ("Encoding");
X 	FontBBox 	= NameFrom ("FontBBox");
X 	UserShow 	= NameFrom (".show");
X 	CharStrings	= NameFrom ("CharStrings");
X 	Metrics		= NameFrom ("Metrics");
X 	BuildChar	= NameFrom ("BuildChar");
X 	FontName	= NameFrom ("FontName");
X 	
X 	OpShowStop = MakeOp ("(showstop)",	ShowStop,	1, 0, 0, 0, Boolean);
X 	OpShowString = MakeOp ("(showstring)",	ShowString,	1, 0, 0, 0, String);
X 	OpStopped = MakeOp ("(showstopped)",	ShowStopped,0, 1, 1, 0);
X 		
X 	InstallOp ("currentfont",	PCurrentFont,	0, 1, 0, 0);
X 	InstallOp ("definefont",	PDefineFont,	2, 1, 0, 0, Poly, Dictionary);
X 	InstallOp ("findfont",		PFindFont,	1, 1, 0, 0, Poly);
X 	InstallOp ("scalefont",		PScaleFont,	2, 1, 0, 0, Dictionary, Float);
X 	InstallOp ("makefont",		PMakeFont,	2, 1, 0, 0, Dictionary, Array);
X 	InstallOp ("setfont",		PSetFont,	1, 0, 0, 0, Dictionary);
X
X	InstallOp ("show",		PShow,		1, 0, 0, 0, String);
X	InstallOp ("widthshow",		PWidthShow,	4, 0, 0, 0, Float, Float, Integer, String);
X 	InstallOp ("ashow",		PAShow,		3, 0, 0, 0, Float, Float, String);
X 	InstallOp ("awidthshow",	PAWidthShow,	6, 0, 0, 0, Float, Float, Integer, Float, Float, String);
X	InstallOp ("stringwidth",	PStringWidth,	1, 2, 0, 0, String);
X	InstallOp (".adjust",		PAdjust,	1, 0, 0, 0, Integer);
X	InstallOp ("buildhershey",	BuildHershey,	2, 0, 0, 0, Dictionary, Integer);
X	InstallOp ("update",		Update,		1, 0, 0, 0, Boolean);
X 	
X 	Install ("FontDirectory",	FD = MakeDict (20));
X 	
X 	zeroPoint = NewPoint (0.0, 0.0);
X 	zeroHardPoint = NewHardPoint (0.0, 0.0);
X }
X
HardPoint DExtToInt (p) Point p;
X {
X 	Matrix m;
X 	HardPoint res;
X 	
X 	m = gstate->CTM;
X 	res.hx = p.x * m.A + p.y * m.C;
X 	res.hy = p.x * m.B + p.y * m.D;
X 	
X 	return res;
X }
X
static int update_state = TRUE;
X
static int Update (bool) Object bool;
X {
X 	int new = BodyBoolean (bool);
X 	
X 	if (new != update_state)
X 		UpdateControl (gstate->device->dev, update_state = new);
X 	return TRUE;
X }
X
InitShowContext ()
X {
X 	gstate->show = show_stack;
X }
X
HardPoint Adjust (basic, code) HardPoint basic; char code;
X {
X 	if (code == gstate->show->space)
X 		return MoveHardPoint (MoveHardPoint (gstate->show->shim, gstate->show->space_shim), basic);
X 	else
X 		return MoveHardPoint (gstate->show->shim, basic);
X }
X
static int PAdjust (code) Object code;
X {
X	gstate->CTM = HardPointTranslate (gstate->CTM, Adjust (ExtToInt (NewPoint (0.0, 0.0)), BodyInteger (code)));
X	
X 	return TRUE;
X }
X
static int PCurrentFont ()
X {
X 	return Push (OpStack, gstate->font);
X }
X
static int PFindFont (key) Object key;
X {
X 	Object res;
X 	
X 	res = DictLoad (FD, key);
X 	if (TypeOf (res) == Condition)
X 		return Error (PInvFont);
X 	return Push (OpStack, res);
X }
X
static Object *encodingCache = NULL;
static Matrix fontmatrixCache;
static int fonttypeCache;
int fidCache;
float fontbboxCache[4];
X
static int PSetFont (font) Object font;
X {
X 	if (!CheckFont (font))
X 		return Error (PInvFont);
X 	gstate->font = font;
X	ExtractMatrix (&fontmatrixCache, DictLoad (font, FontMatrix));
X 	encodingCache = BodyArray (DictLoad (font, Encoding));
X 	fonttypeCache = BodyInteger (DictLoad (font, FontType));
X 	fidCache = BodyFontID (DictLoad (font, Fid));
X 	ExtractBBox (fontbboxCache, DictLoad (font, FontBBox));
X 	return TRUE;
X }
X
int CheckFont (font) Object font;
X {
X 	Object mat, bbox, enc, fonttype;
X 	Matrix dummy;
X 	float bboxdummy[4];
X 	
X 	mat = DictLoad (font, FontMatrix);
X  	if (TypeOf (mat) == Condition || !ExtractMatrix (&dummy, mat))
X 		return FALSE;
X 	fonttype = DictLoad (font, FontType);
X 	if (TypeOf (fonttype) != Integer)
X 		return FALSE;
X	bbox = DictLoad (font, FontBBox);
X 	if (TypeOf (bbox) != Array || lengthArray (bbox) != 4 || !ExtractBBox (bboxdummy, bbox))
X 		return FALSE;
X 	enc = DictLoad (font, Encoding);
X 	if (TypeOf (enc) != Array || lengthArray (enc) != 256)
X 		return FALSE;
X	
X	switch (BodyInteger (fonttype))
X	 {
X	 	case FONT_USER: return TRUE;
X	 	
X	 	default: return TRUE;
X	 }
X }
X
int CheckHershey (font, encoding) Object font, *encoding;
X {
X 	Object cs, metrics;
X  	int i;
X	cs = DictLoad (font, CharStrings);
X	if (TypeOf (cs) != Dictionary)
X		return FALSE;
X	metrics = DictLoad (font, Metrics);
X	if (TypeOf (metrics) != Dictionary)
X		return FALSE;
X	
X	for (i = 0; i < 256; i++)
X	 {
X	 	Object met;
X	 	
X		met = DictLoad (metrics, encoding[i]);
X		if (TypeOf (met) == Array)
X	 	 {
X	 	 	Object *m = BodyArray (met);
X	 	 	int j, l = lengthArray (met);
X	 	 	
X	 	 	if (l != 1 && l != 2 && l != 4)
X	 			return FALSE;
X	 		
X	 		for (j = 0; j < l; j++)
X	 			if (TypeOf (m[j]) != Integer && TypeOf (m[j]) != Real)
X	 				return FALSE;
X	 	 }
X	 	else if (TypeOf (metrics) != Integer && TypeOf (metrics) != Real)
X	 		return FALSE;
X	 }
X	return TRUE;
X }
X
int ExtractBBox (bbox, array) float *bbox; Object array;
X {
X 	Object num;
X 	int i;
X 	
X 	if (lengthArray (array) != 4)
X 		return FALSE;
X 	for (i = 0; i < 4; i++)
X 	 {
X 	 	num = getArray (array, i);
X 	 	
X 		if (TypeOf (num) == Integer)
X 			bbox [i] = BodyInteger (num);
X 		else if (TypeOf (num) == Real)
X 			bbox [i] = BodyReal (num);
X 		else
X 			return FALSE;
X 	 }
X 	return TRUE;
X }
X
static Object MakeFontID ()
X {
X 	Object res;
X 	
X 	res = MakeObject (FontID);
X 	res.u.Font = last_fid++; /* just for uniqueness */
X 	
X 	return res;
X }
X
int BodyFontID (fid) Object fid;
X {
X 	return fid.u.Font;
X }
X
static int PDefineFont (key, dict) Object key, dict;
X {
X 	if (maxDict (dict) == lengthDict (dict) || maxDict (FD) == lengthDict (FD))
X 		return Error (PDictFull);
X 	
X	if (!CheckFont (dict))
X		return Error (PInvFont);
X	
X 	DictStore (FD, key, ReadOnly (dict));
X 	DictStore (dict, Fid, MakeFontID ());
X 	return Push (OpStack, ReadOnly (dict));
X }
X
struct font_entry
X {
X 	Object font;
X 	Matrix mat;
X 	int fid;
X 	struct font_entry *font_next;
X } *font_list = NULL;
X
Object LookupFont (font, matrix) Object font; Matrix matrix;
X {
X 	Object res, mat, new;
X 	Matrix m, n;
X 	struct font_entry *p, *fe;
X 	int fid = BodyFontID (DictLoad (font, Fid));
X 	
X 	mat = DictLoad (font, FontMatrix);
X 	ExtractMatrix (&m, mat);
X 	n = MatMult (matrix, m);
X 	
X	for (p = font_list; p != NULL; p = p->font_next)
X 		if (p->fid == fid && EqFont (p->mat, n))
X 		 {
X 		 	Message ("font matched");
X 			return p->font;
X 		 }
X 	Message ("building a font dict");
X 	
X  	copyDict (font, res = MakeDict (maxDict (font)));
X 	new = MakeArray ((Object *) Malloc ((unsigned) 6 * sizeof (Object)), 6);
X 	VOID AssignMatrix (new, n);
X 	DictStore (res, FontMatrix, new);
X 	
X 	res = ReadOnly (res);
X	
X	fe = (struct font_entry *) Malloc (sizeof (struct font_entry));
X	fe->mat = n;
X	fe->font = res;
X	fe->font_next = font_list;
X	fe->fid = fid;
X	font_list = fe;
X	
X	return res;
X }
X
static int PScaleFont (font, scale) Object font, scale;
X {
X 	Object res;
X 	float s = BodyReal (scale);
X 	
X 	if (!CheckFont (font))
X 		return Error (PInvFont);
X 	res = LookupFont (font, NewMatrix (s, 0.0, 0.0, s, 0.0, 0.0));
X	
X 	return Push (OpStack, res);
X }
X
static int PMakeFont (font, matrix) Object font, matrix;
X {
X 	Object res;
X 	Matrix m;
X 	
X 	if (!CheckFont (font))
X 		return Error (PInvFont);
X 	ExtractMatrix (&m, matrix);
X 	res = LookupFont (font, m);
X	
X 	return Push (OpStack, res);
X }
X
static Vector GetMetrics (ob) Object ob;
X {
X 	if (TypeOf (ob) == Integer || TypeOf (ob) == Real)
X 	 	return NewVector (BodyFloat (ob), 0.0, 0.0);
X 	else if (TypeOf (ob) != Array)
X 		return NewVector (0.0, 0.0, 1.0);
X 	else if (lengthArray (ob) == 2)
X 		return NewVector (BodyFloat (getArray (ob, 1)), 0.0, 0.0);
X 	else if (lengthArray (ob) == 4)
X 		return NewVector (BodyFloat (getArray (ob, 2)), BodyFloat (getArray (ob, 3)), 0.0);
X 	else
X 		return NewVector (0.0, 0.0, 1.0);
X }
X
static int BuildHershey (font, code) Object font, code;
X {
X	Vector met;
X	Object *bbox, string, nm;
X 	unsigned char *s;
X 	Path p;
X 	int i, l;
X 	
X	bbox 	= BodyArray (DictLoad (font, FontBBox));
X	nm 	= BodyArray (DictLoad (font, Encoding)) [BodyInteger (code)];
X	met 	= GetMetrics (DictLoad (DictLoad (font, Metrics), nm));
X	met.vx -= 2; /* hershey bodge - they look better closer */
X	string 	= DictLoad (DictLoad (font, CharStrings), nm);
X	
X	SetCacheDevice (nm, NewPoint (met.vx, met.vy),
X		BodyReal (bbox[0]), BodyReal (bbox[1]),
X		BodyReal (bbox[2]), BodyReal (bbox[3]));
X	
X	if (TypeOf (string) != String)
X		return TRUE;
X	gstate->line_width = 1.5;
X	gstate->line_join = 2;
X	gstate->line_cap = 0;
X	gstate->dash_length = 0;
X	
X 	s = BodyString (string);
X 	l = lengthString (string) / 2;
X 	p = gstate->path;
X 	
X	VOID PNewPath ();
X 	for (i = 0; i < l; i++, s++, s++)
X 	 {
X 	 	Point po;
X 	 	/* SUN2 FLOATING POINT BUG: (float) (int) is necessary, where (float) should be sufficient */
X 	 	po = NewPoint ((float) (int) ((*s & ~MOVETO) - 64), (float) (int) ((s[1] & ~MOVETO) - 73));
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X/* 	 	(*(*s & MOVETO ? MoveTo : LineTo))
X 	  		(p, ExtToInt (po));        
X*/
X		if (*s & MOVETO)
X			MoveTo (p, ExtToInt (po));        
X	        else
X			LineTo (p, ExtToInt (po));        
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X 	 }
X 	return Push (ExecStack, Cvx (NameFrom ("stroke")));
X }
X
X/*
X	Persistent state important across a BuildChar call-back
X		InShow 		- the fact that we're in a call back
X		gstate 		- graphics state
X		ccache 		- the current cache device
X		gstate->device 	- whether a cache device has been set or not.
X				  The old device if a cache device is installed.
X				  The old CTM.
X		Width 		- current width information - used for moving cp
X		awx, awy	- shim adjustment parameters
X		scode,
X		axcode, aycode	- spacing adjustment parameters
X	
X	XXXXXXX         XXXXXX         XXXXXXXXXX         XXXXXXXXX
X	XXXXXXX         XXXXXX         XXXXXXXXXX         XXXXXXXXX
X	XXXXXXX         XXXXXX         XXXXXXXXXX         XXXXXXXXX
X	XXXXXXX         XXXXXX         XXXXXXXXXX         XXXXXXXXX
X	XXXXXXX         XXXXXX         XXXXXXXXXX         XXXXXXXXX
X	       |_______|      |_______|          |_______|
X		   |
X		ashow/widthshow width vector
X	
X	ShowUser shows the first character (to avoid a leading gap).
X			It may have to call buildchar if the character is not cached.
X	ShowString finishes off a BuildChar (if necessary)
X			then shows gaps and characters until it encounters
X			one which is not cached.
X		It then stacks:
X			a stopped context to reset things if an error occurs.
X			another ShowString to continue output.
X			A buildchar to build a character
X*/
X
static int Show (string, space, shim, space_shim)
X		Object string; char space; HardPoint shim, space_shim;
X {
X	if (!gstate->cp_defined)
X		return Error (PNoCurrentPoint);
X	
X	switch (fonttypeCache)
X	 {
X		case FONT_USER:
X			return ShowUser (string, fontmatrixCache, space, shim, space_shim);
X		
X		default:
X			return Error (PInvFont);		
X	 }
X }
X
static int ShowStopped ()
X {
X	VOID Pop (ExecStack);
X	VOID Push (OpStack, False);
X	return TRUE;
X }
X
X#define lengthString(s) ((s).Length)
X
X#define BodyString(s)	((s).u.String)
X
int ShowUser (string, m, space, shim, space_shim)
X		Object string; Matrix m; char space; HardPoint shim, space_shim;
X {
X 	unsigned char *s = BodyString (string);
X 	int l = lengthString (string);
X 	
X 	if (l == 0)
X 		return TRUE;
X 	
X	/* GSave (); */
X	
X	++gstate->show;
X	gstate->show->InShow = TRUE;
X	gstate->show->shim = shim;
X	gstate->show->space_shim = space_shim;
X	gstate->show->space = space;
X	gstate->show->mat = gstate->CTM;
X	
X	gstate->CTM.tx = gstate->cp.hx;
X	gstate->CTM.ty = gstate->cp.hy;
X	
X  	gstate->CTM = MatMult (m, gstate->CTM);
X	FindCache ();
X	
X	UpdateControl (gstate->device->dev, FALSE);
X	
X	gstate->cp.hx = gstate->CTM.tx;
X	gstate->cp.hy = gstate->CTM.ty;
X	if (CacheShow (encodingCache [*s], gstate->cp))
X		return ShowStringAux (string, s, l, gstate->show->Width);
X	
X	UpdateControl (gstate->device->dev, TRUE);
X	
X	GSave ();
X	VOID Push (ExecStack, OpShowStop);
X	PStopped (OpShowString);
X	VOID Push (OpStack, string);
X	VOID Push (OpStack, gstate->font);
X	VOID Push (OpStack, MakeInteger (*s));
X	VOID Push (ExecStack, DictLoad (gstate->font, BuildChar));
X	return TRUE;
X }
X
static int ShowString (string) Object string;
X {
X 	int l = lengthString (string);
X 	unsigned char *st = BodyString (string);
X 	Point last_width;
X 	
X 	Pop (ExecStack);
X  	Pop (ExecStack);
X  	Pop (ExecStack);
X	GRestore ();
X	
X	UpdateControl (gstate->device->dev, FALSE);
X	
X	last_width = gstate->show->Width;
X 	CacheShow (encodingCache [*st], gstate->cp);
X 	
X 	return ShowStringAux (string, st, l, last_width);
X }
X
ShowStringAux (string, st, l, last_width) Object string; unsigned char *st; int l; Point last_width;
X {
X 	unsigned char *s = st;
X 	HardPoint loc;
X 	
X 	loc.hx = gstate->CTM.tx; loc.hy = gstate->CTM.ty;
X 	for (;;)
X	 {
X	 	int code = *++s;
X	 	HardPoint offset, cp;
X	 	
X	 	offset = Adjust (DExtToInt (last_width), code);
X		loc.hx += offset.hx;
X		loc.hy += offset.hy;
X 		if (--l == 0)
X 	 		break;
X		if (!CacheShow (encodingCache [code], loc))
X 		 {
X			gstate->cp = loc;
X			gstate->CTM.tx = loc.hx; gstate->CTM.ty = loc.hy;
X			
X			VOID Push (ExecStack, OpShowStop);
X			PStopped (OpShowString);
X	
X		 	VOID Push (OpStack, getIString (string, s - st, l));
X 			
X			VOID Push (OpStack, gstate->font);
X			VOID Push (OpStack, MakeInteger (*s));
X			VOID Push (ExecStack, DictLoad (gstate->font, BuildChar));
X 			UpdateControl (gstate->device->dev, TRUE);
X 	
X 			GSave ();
X	
X			return TRUE;
X 		 }
X 		last_width = gstate->show->Width;
X 	 }
X 	gstate->CTM.tx = loc.hx; gstate->CTM.ty = loc.hy;
X	UpdateControl (gstate->device->dev, TRUE);
X 	
X	return ShowStopAux ();
X }
X
static int ShowStop (st) Object st;
X {
X	GRestore ();
X	ShowStopAux ();
X	if (BodyBoolean (st))
X		return PStop ();
X	return TRUE;
X }
X
ShowStopAux ()
X {
X 	HardPoint cp;
X 	
X	cp.hx = gstate->CTM.tx;
X	cp.hy = gstate->CTM.ty;
X	/* GRestore (); */
X	gstate->CTM = gstate->show->mat;
X	--gstate->show;
X	gstate->cp = cp;
X	
X 	return TRUE;
X }
X
static int PShow (string) Object string;
X {
X 	return Show (string, 0, zeroHardPoint, zeroHardPoint);
X }
X
static int PWidthShow (x, y, code, string) Object x, y, code, string;
X {
X	return Show (string, BodyInteger (code), zeroHardPoint, DExtToInt (NewPoint (BodyReal (x), BodyReal (y))));
X }
X
static int PAShow (ax, ay, string) Object ax, ay, string;
X {
X	return Show (string, 0, DExtToInt (NewPoint (BodyReal (ax), BodyReal (ay))), zeroHardPoint);
X }
X
static int PAWidthShow (x, y, code, ax, ay, string) Object x, y, code, ax, ay, string;
X {
X	return Show (string,
X		BodyInteger (code),
X		DExtToInt (NewPoint (BodyReal (x), BodyReal (y))),
X		DExtToInt (NewPoint (BodyReal (ax), BodyReal (ay))));
X }
X
static int PStringWidth (string) Object string;
X {
X 	Matrix m;
X 	Vector v;
X 	Object *enc, met;
X 	int i, l = lengthString (string);
X 	unsigned char *s = BodyString (string);
X 	float x = 0, y = 0;
X 	
X 	if (!CheckFont (gstate->font))
X 		return Error (PInvFont);
X 	if (BodyInteger (DictLoad (gstate->font, FontType)) == 3)
X 	 {
X 	 	VOID Push (OpStack, string);
X 	 	VOID Push (ExecStack, Cvx (NameFrom (".stringwidth")));
X 	 	return TRUE;
X 	 }
X 	enc = BodyArray (DictLoad (gstate->font, Encoding));
X 	met = DictLoad (gstate->font, Metrics);
X 	for (i = 0; i < l; i++)
X 	 {
X 	 	v = GetMetrics (DictLoad (met, enc[s[i]]));
X 		x += v.vx;
X 		y += v.vy;
X 	 }
X 	ExtractMatrix (&m, DictLoad (gstate->font, FontMatrix));
X 	v = Transform (NewVector (x, y, 0.0), m);
X 	return Push (OpStack, MakeReal (v.vx)), Push (OpStack, MakeReal (v.vy));
X }
END_OF_FILE
if test 16804 -ne `wc -c <'font.c'`; then
    echo shar: \"'font.c'\" unpacked with wrong size!
fi
# end of 'font.c'
fi
if test -f 'hard.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hard.c'\"
else
echo shar: Extracting \"'hard.c'\" \(20529 characters\)
sed "s/^X//" >'hard.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X
X/*
X   Apollo driver created by Henk Tullemans
X   Philips Research Laboratories
X   Eindhoven, The Netherlands
X   tullemans@apolloway.prl.philips.nl
X*/
X
X#include "main.h"
X#include "graphics.h"
X#include "canon.h"
X
X#include "/sys/ins/base.ins.c"
X#include "/sys/ins/gpr.ins.c"
X#include "/sys/ins/error.ins.c"
X#include "/sys/ins/pad.ins.c"
X#include "/sys/ins/streams.ins.c"
X
X#define HIGHEST_PLANE 0
X
X#define DeviceBitmap(h) (((struct pixrect *)((h)->hard.handle))->ident)
X
typedef struct pixrect
X{
X	int	ident;
X} pixrect;
X
static  struct hardware *NewHardware ();
X
static struct pixrect *screen;
X
static gpr_$bitmap_desc_t orig_bitmap;
X
extern	void	Message ();
X
struct hardware *NewHardware (bm, extent, flags)
struct pixrect *bm;
DevicePoint extent; int flags;
X {
X 	struct hardware *d;
X
X	d = (struct hardware *) Malloc (sizeof (struct hardware));
X 	
X 	d->flags = flags;
X 	d->hard.addr = (char *) bm;
X 	d->aux = d->clip = NULL;
X 	d->extent = extent;
X 	return d;
X }
X
X/*
X *	This file describes the interface that PostScript requires to the graphics system at Version 1.4.
X *	
X *	''Hardware'' in this context refers to a pointer to windows and/or bitmaps and is the lowest level
X *	of access that PostScript is interested in. Any Hardware parameter may be expected to be NULL.
X */
X
X/*********************************** CREATION OF WINDOWS AND BITMAPS *******************/
X
struct hardware *InitHardware () 
X{
X/*
X *	InitHardware () returns a default device which PostScript may use immediately (or NULL if not appropriate).
X *	Its size and shape are not defined. Most typically the user will want to start up another device
X *	before it is used anyway. No attempt will be made by PostScript to Destroy the resulting
X *	device.
X */
X	gpr_$offset_t		display_size;
X	gpr_$plane_t          	hi_plane_id;
X/*	gpr_$bitmap_desc_t	orig_bitmap;*/
X	pad_$window_desc_t	window;
X	stream_$id_t		stream;
X	status_$t		status;
X
X	Message ("InitHardware");
X
X	InitTransfer (72);
X
X	pad_$inq_full_window (stream_$stdout, (short) 1, window, status);
X	check_status (status);
X
X	pad_$create ("",
X		    (short) 0,
X		    pad_$transcript,
X		    stream_$stdout,
X		    pad_$top,
X		    (short) 0,
X		    (short) 1,
X		    stream,
X		    status);
X
X	display_size.x_size = 1024;
X	display_size.y_size = 1024;
X	hi_plane_id = HIGHEST_PLANE;
X
X	gpr_$init (gpr_$direct, stream, display_size, hi_plane_id, orig_bitmap, status);
X	check_status (status);
X
X	gpr_$set_cursor_active (true, status);
X	check_status (status);
X
X	return NULL;
X}
struct hardware *NewBitmapHardware (width, height)
int width, height;
X{
X/*
X *	NewBitmapHardware () is expected to create a new bitmap. Only one plane will be needed.
X */
X 	DevicePoint 		real_extent;
X 	struct pixrect 		*bm;
X	gpr_$plane_t    	hi_plane_id;
X	gpr_$offset_t		size;
X	gpr_$bitmap_desc_t	bitmap_desc;
X	gpr_$attribute_desc_t	attribs_desc;
X	status_$t		status;
X	
X	Message ("NewBitmapHardware");
X
X	gpr_$allocate_attribute_block (attribs_desc, status);
X	check_status (status);
X
X	size.x_size = (short) width;
X	size.y_size = (short) height;
X	hi_plane_id = HIGHEST_PLANE;
X
X	gpr_$allocate_bitmap (size, hi_plane_id, attribs_desc, bitmap_desc, status);
X	check_status (status);
X
X/*	gpr_$set_bitmap (bitmap_desc, status);
X	check_status (status);
X*/
X 	real_extent = NewDevicePoint (width, height);
X
X	bm = (struct pixrect *) Malloc (sizeof (struct pixrect));
X	bm->ident = (int)bitmap_desc;
X
X	return NewHardware (bm, real_extent, 0);
X}
X
struct hardware *NewWindowHardware (width, height)
int width, height;
X{
X/*
X *	NewWindowHardware () is expected to create a window on the screen. On a colour system this will
X *	be expected to support full colour.
X */
X 	DevicePoint		real_extent;
X 	struct pixrect 		*w;
X	name_$pname_t		graphics_window;
X	gpr_$offset_t		display_size;
X	gpr_$plane_t          	hi_plane_id;
X	gpr_$bitmap_desc_t    	init_bitmap;
X	status_$t               status;
X	pad_$window_desc_t	window;
X	stream_$id_t		stream_win;
X	gpr_$attribute_desc_t	attribs_desc;
X
X	Message ("NewWindowHardware");
X
X	strcpy (graphics_window, "postscript_graphics");
X	
X	window.top    = 0;
X	window.left   = 0;
X	window.width  = width;
X	window.height = height;
X 
X	pad_$create_window ("",
X			    (short) 0,
X			    pad_$transcript,
X			    (short)1,
X			    window,
X			    stream_win,
X			    status);
X	check_status (status);
X
X	pad_$set_auto_close (stream_win, (short) 1, true, status);
X	check_status (status);
X                              
X	display_size.x_size = width;
X	display_size.y_size = height;
X	hi_plane_id = HIGHEST_PLANE;
X
X	gpr_$init (gpr_$direct, stream_win, display_size, hi_plane_id, init_bitmap, status);
X	check_status (status);
X
X	gpr_$set_bitmap (init_bitmap, status);
X	check_status (status);
X/*
X	gpr_$set_fill_background_value ((int) 0, status);
X	check_status (status);
X*/
X	gpr_$set_draw_value ((int) 0, status);
X	check_status (status);
X
X	gpr_$set_auto_refresh (true, status);
X	check_status (status);
X
X	gpr_$set_obscured_opt (gpr_$pop_if_obs, status);
X	check_status (status);
X
X	gpr_$set_cursor_active (true, status);
X	check_status (status);
X
X 	real_extent = NewDevicePoint (width, height);
X 
X	w = (struct pixrect *) Malloc (sizeof (struct pixrect));
X	w->ident = (int)init_bitmap;
X
X	return NewHardware (w, real_extent, ISWIN);
X}
X
X
static void DestroyHard (h) struct hardware *h;
X{
X	gpr_$attribute_desc_t	attribs_desc;
X	status_$t		status;
X
X
X	if (h->flags != ISWIN)
X	{
X		Message ("DestroyHard: Bitmap destroyed");
X		attribs_desc = gpr_$attribute_block ((gpr_$bitmap_desc_t)DeviceBitmap(h), status);
X		check_status (status);
X		gpr_$deallocate_bitmap ((gpr_$bitmap_desc_t)DeviceBitmap(h), status);
X		check_status (status);
X		gpr_$deallocate_attribute_block (attribs_desc, status);
X		check_status (status);
X	}
X	else
X	{ 
X		Message ("DestroyHard: Window destroyed");
X/*
X		stream_$delete ((stream_$id_t)DeviceBitmap(h), status);
X		check_status (status);
X*/
X	}
X}
X
void DestroyHardware (h)
struct hardware *h;
X{
X/*	
X *	DestroyHardware () should release the resources required by the hardware, bitmap or window.
X *	This should cause a window device to vanish. NULL is not an error (does nothing).
X */
X
X	status_$t	status;
X	boolean		delete_display;
X
X	if (h == (struct hardware *)NULL)
X		return;
X 	DestroyHard (h);
X 	if (h->aux)
X 		DestroyHardware (h->aux);
X}
X
X/******************************************* OUTPUT PRIMITIVES ******************************/	
X
void BitBlt (from, to, fromPoint, toPoint, extent, rop)
X	struct hardware *from, *to;
X	DevicePoint toPoint, fromPoint, extent;
X	int rop;
X{
X/*	
X *	BitBlt () is a full function RasterOp. The 'rop' argument
X *	will have values as described in the header file hard.h. If the from argument is NULL it is taken to be
X *	a bitmap full of ones the shape of the fromPoint and extent. If the to argument is NULL, this is a no-op.
X */
X
X	gpr_$bitmap_desc_t	from_desc, to_desc;
X	gpr_$window_t		from_window;
X	short			from_plane, to_plane;
X	gpr_$position_t		to_origin;
X	status_$t               status;
X	boolean			unobscured;
X	struct hardware		*from_tmp;
X
X	Message ("BitBlt");
X
X	if (from == NULL)
X	{
X		from_desc = NULL;
X		rop = single_rop[rop];
X	}
X	else
X		from_desc = (gpr_$bitmap_desc_t)DeviceBitmap(from);
X
X	if (to == NULL)
X		to_desc = NULL;
X	else
X		to_desc = (gpr_$bitmap_desc_t)DeviceBitmap(to);
X
X	if (to_desc == NULL || extent.dx == 0 || extent.dy == 0)
X		return;
X
X	if (from_desc == NULL)
X	{
X		gpr_$set_draw_value ((int) 0, status);
X		check_status (status);
X
X		from_tmp = NewBitmapHardware (extent.dx, extent.dy);
X		from_desc = (gpr_$bitmap_desc_t)DeviceBitmap(from_tmp);
X
X		gpr_$set_bitmap (from_desc, status);
X		check_status (status);
X
X		from_window.window_base.x_coord = (short)0;
X		from_window.window_base.y_coord = (short)0;
X		from_window.window_size.x_size = (short)extent.dx;
X		from_window.window_size.y_size = (short)extent.dy;
X
X                gpr_$rectangle (from_window, status);
X		check_status (status);
X	}
X	else
X	{
X		from_window.window_base.x_coord = (short)fromPoint.dx;
X		from_window.window_base.y_coord = (short)fromPoint.dy;
X		from_window.window_size.x_size = (short)extent.dx;
X		from_window.window_size.y_size = (short)extent.dy;
X	}
X
X	gpr_$set_bitmap (to_desc, status);
X	check_status (status);
X
X	gpr_$set_plane_mask ((short)1, status);
X	check_status (status);
X
X	gpr_$set_raster_op ((short)0, (short)rop, status);
X	check_status (status);
X
X	from_plane = (short)0;
X	to_plane = (short)0;
X	to_origin.x_coord = (short)toPoint.dx;	
X	to_origin.y_coord = (short)toPoint.dy;	
X
X	gpr_$bit_blt (from_desc, from_window, from_plane, to_origin, to_plane, status);
X	check_status (status);
X
X	if (from == NULL)
X		DestroyHardware (from_tmp);
X}
X
void BitBltLine (h, fromPoint, toPoint, rop)
X	struct hardware *h;
X	DevicePoint fromPoint, toPoint;
X	int rop;
X{
X/*	
X *	BitBltLine () is expected to draw a line between the given points
X *	with the given RasterOp and colour masking.
X *	The line should be one pixel wide and half-open.
X *	[Thicker lines are done with BitBlt.]
X */
X	gpr_$bitmap_desc_t	to_desc;
X	boolean			unobscured;
X	status_$t               status;
X	int			new_rop;
X
X	Message ("BitBltLine");
X
X	if (h == NULL)
X		to_desc = NULL;
X	else
X		to_desc = (gpr_$bitmap_desc_t)DeviceBitmap(h);
X
X	if (to_desc == NULL)
X		return;
X
X 	switch (single_rop[rop])
X 	 {
X 	 	case ROP_DEST: 		return;
X
X 	 	case ROP_NOTDEST: 	new_rop = ROP_NOTSOURCE; break;
X
X		default:		new_rop = rop;
X 	 }
X
X	gpr_$set_bitmap (to_desc, status);
X	check_status (status);
X
X	gpr_$set_plane_mask ((short)1, status);
X	check_status (status);
X
X	gpr_$set_raster_op ((short)0, (short)new_rop, status);
X	check_status (status);
X
X	gpr_$set_draw_value ((int) 0, status);
X	check_status (status);
X
X	gpr_$move ((short)fromPoint.dx, (short)fromPoint.dy, status);
X	check_status (status);
X
X	gpr_$line ((short)toPoint.dx, (short)toPoint.dy, status);
X	check_status (status);
X}
X
void BitBltBlob (to, top, height, left, right, rop)
X	struct hardware *to;
X	int top, height, *left, *right, rop;
X{
X /*
X  *	BitBltBlob () takes a set of pixel coordinates and fills the trapezon figure
X  *	half open.
X  */
X	gpr_$bitmap_desc_t	to_desc;
X	boolean			unobscured;
X	status_$t               status;
X	int			new_rop;
X
X	int			i, offset = top;
X	gpr_$window_t		rectangle;
X
X	Message ("BitBltBlob");
X
X	height = height + top;
X
X 	switch (rop)
X 	 {
X 	 	case ROP_DEST: 		return;
X
X 	 	case ROP_NOTDEST: 	new_rop = ROP_NOTSOURCE; break;
X
X		default:		new_rop = rop;
X 	 }
X
X	to_desc = (gpr_$bitmap_desc_t)DeviceBitmap(to);
X
X	gpr_$set_bitmap (to_desc, status);
X	check_status (status);
X
X	gpr_$set_raster_op ((short)0, (short)new_rop, status);
X	check_status (status);
X
X	gpr_$set_plane_mask ((short)1, status);
X	check_status (status);
X
X 	for (i = top; i < height; i++)
X	{
X		rectangle.window_base.x_coord = (short)left [i-offset];
X		rectangle.window_base.y_coord = (short)i;
X		rectangle.window_size.x_size = (short)(right[i-offset]-left[i-offset]);
X		rectangle.window_size.y_size = (short)1;
X
X		gpr_$rectangle (rectangle, status);
X		check_status (status);
X	}
X
X}
X
X
void RasterTile (from, to, toPoint, extent, rop)
X	struct hardware *from, *to;
X	DevicePoint toPoint, extent;
X	int rop;
X{
X/*
X *	RasterTile () replicates the whole of ``from'' over ``to'', but clipped by the
X *	rectangle bounded by ``toPoint'' and ``extent''.
X */
X	struct hardware		*from_tmp, *pattern;
X	gpr_$bitmap_desc_t	from_desc, to_desc, from_tmp_desc, pattern_desc;
X	gpr_$offset_t		from_size, to_size;
X	gpr_$plane_t          	hi_plane_id;
X	gpr_$window_t		to_window, from_window, clip_window;
X	short			from_plane, to_plane;
X	gpr_$position_t		to_origin;
X	boolean			unobscured;
X	status_$t               status;
X	int			nx, ny, i, j;
X	int			pixel_array[16];
X
X	Message ("RasterTile");
X
X	if (from == NULL)
X		from_desc = NULL;
X	else
X		from_desc = (gpr_$bitmap_desc_t)DeviceBitmap(from);
X
X	if (to == NULL)
X		to_desc = NULL;
X	else
X		to_desc = (gpr_$bitmap_desc_t)DeviceBitmap(to);
X
X	if (to_desc == NULL || extent.dx == 0 || extent.dy == 0)
X		return;
X
X	if (from_desc == NULL)
X	{
X/*		gpr_$set_draw_value ((int) 0, status);
X		check_status (status);
X
X		from_desc = to_desc;
X*/
X		Message ("RasterTile: from = nill-pointer");
X		return;
X	}
X
X/*
X   Inquire 'from' and 'to' bitmap dimensions
X*/
X	gpr_$inq_bitmap_dimensions (from_desc, from_size, hi_plane_id, status);
X	check_status (status);
X
X	from_window.window_base.x_coord = (short)0;
X	from_window.window_base.y_coord = (short)0;
X	from_window.window_size.x_size = (short)from_size.x_size;
X	from_window.window_size.y_size = (short)from_size.y_size;
X
X	gpr_$inq_bitmap_dimensions (to_desc, to_size, hi_plane_id, status);
X	check_status (status);
X
X	to_window.window_base.x_coord = (short)0;
X	to_window.window_base.y_coord = (short)0;
X	to_window.window_size.x_size = (short)to_size.x_size;
X	to_window.window_size.y_size = (short)to_size.y_size;
X
X	from_plane = (short)0;
X	to_plane = (short)0;
X
X/*
X	Create a (32x32) bitmap for the pattern in 'from'
X	See GPR Call "gpr_$set_fill_pattern" for restrictions
X*/
X
X	pattern = NewBitmapHardware (32, 32);
X	pattern_desc = (gpr_$bitmap_desc_t)DeviceBitmap(pattern);
X
X	nx = 32 / from_size.x_size; /* nx = 8 from_size.x_size = 4 i.e. int(72/20+.5) */
X	ny = 32 / from_size.y_size; /* ny = 8 from_size.x_size = 4 i.e. int(72/20+.5) */
X
X	gpr_$set_bitmap (pattern_desc, status);
X	check_status (status);
X
X	to_origin.x_coord = (short)0;
X	to_origin.y_coord = (short)0;
X
X	for (i = 0; i < ny; i++)
X	{
X		for (j = 0; j < nx; j++)
X		{
X			gpr_$bit_blt (from_desc, from_window, from_plane, to_origin, to_plane, status);
X			check_status (status);
X
X			to_origin.x_coord = (short)(to_origin.x_coord + from_size.x_size);
X		} 
X
X		to_origin.x_coord = (short)0;
X		to_origin.y_coord = (short)(to_origin.y_coord + from_size.y_size);
X	}
X
X/*
X	Create a temporary bitmap with the dimensions of 'to' and filled with all ones
X	Set for this temporary bitmap the fill pattern as created above 
X*/
X
X	from_tmp = NewBitmapHardware (to_size.x_size, to_size.y_size);
X	from_tmp_desc = (gpr_$bitmap_desc_t)DeviceBitmap(from_tmp);
X
X	gpr_$set_bitmap (from_tmp_desc, status);
X	check_status (status);
X
X	gpr_$set_fill_pattern (pattern_desc, (short)1, status);
X	check_status (status);
X
X	gpr_$rectangle (to_window, status);
X	check_status (status);
X
X/*
X	BitBlt of 'from_tmp' to 'to'
X*/
X	gpr_$set_bitmap (to_desc, status);
X	check_status (status);
X
X	to_origin.x_coord = (short)0;
X	to_origin.y_coord = (short)0;
X
X	gpr_$set_plane_mask ((short)1, status);
X	check_status (status);
X
X	gpr_$set_raster_op ((short)0, (short)rop, status);
X	check_status (status);
X
X	clip_window.window_base.x_coord = (short)toPoint.dx;
X	clip_window.window_base.y_coord = (short)toPoint.dy;
X	clip_window.window_size.x_size = (short)extent.dx;
X	clip_window.window_size.y_size = (short)extent.dy;
X
X	gpr_$set_clip_window (clip_window, status);
X	check_status (status);
X
X	gpr_$set_clipping_active (true, status);
X	check_status (status);
X
X	gpr_$bit_blt (from_tmp_desc, to_window, from_plane, to_origin, to_plane, status);
X	check_status (status);
X
X	gpr_$set_clipping_active (false, status);
X	check_status (status);
X
X	DestroyHardware (from_tmp);
X	DestroyHardware (pattern);
X}
X
X/********************************** BITMAP CONVERSION ********************************/
X
char *StringFromHardware (h) struct hardware *h;
X{
X/*	
X *	StringFromHardware () produces a string from its argument which describes the bitmap.
X *	The bitmap is returned in row-major order with the leftmost bit of each byte in the most significant
X *	position. Rows are padded to byte boundaries. Only single plane bitmaps are used.
X */
X/*
X	int words = (h->extent.dx + 15) / 16;
X	char *string = malloc ((h->extent.dx + 7) / 8 * h->extent.dy), *s = string;
X	int i, j, odd = ((h->extent.dx + 7) / 8) & 1;
X	short *d = mpr_d (DeviceBitmap (h))->md_image;
X*/
X	Message ("StringFromHardware");
X/*
X	for (i = 0; i < h->extent.dy; i++)
X	 {
X		for (j = 0; j < words - odd; j++)
X		 {
X			short word = *d++;
X
X			*s++ = (word >> 8) & 0xFF;
X			*s++ = word & 0xFF;
X		 }
X		if (odd)
X			*s++ = (*d++ >> 8) & 0xFF;
X	 }
X	return string;
X*/
X}
X
struct hardware *HardwareFromString (s, width, height) unsigned char *s; int width, height;
X{
X/*
X *	
X *	HardwareFromString () performs the inverse mapping, generating a bitmap from a set of bits, given
X *	a width and height. Only single plane bitmaps are used.
X */
X
X 	DevicePoint 			real_extent;
X	gpr_$display_mode_t     	mode;
X	gpr_$plane_t          		hi_plane_id;
X	gpr_$offset_t			size;
X	gpr_$attribute_desc_t		attribs_desc;
X	gpr_$bitmap_desc_t		desc;
X	gpr_$window_t			window;
X/*	static gpr_$pixel_array_t	pixel_array;*/
X	static int			pixel_array[300000];
X	int				array_index;
X	short				line_width;
X	unsigned short			word;
X	struct pixrect			*bm;
X	status_$t			status;
X	int words = (width + 15) / 16;
X	int odd = ((width + 7) / 8) & 1;
X	int i, j, k;
X
X	Message ("HardwareFromString");
X
X	gpr_$allocate_attribute_block (attribs_desc, status);
X	check_status (status);
X
X	size.x_size = (short)width;
X	size.y_size = (short)height;
X	hi_plane_id = HIGHEST_PLANE;
X
X	gpr_$allocate_bitmap (size, hi_plane_id, attribs_desc, desc, status);
X	check_status (status);
X
X	gpr_$set_bitmap (desc, status);
X	check_status (status);
X
X 	real_extent = NewDevicePoint (width, height);
X
X	window.window_base.x_coord = (short)0;
X	window.window_base.y_coord = (short)0;
X	window.window_size.x_size = (short)width;
X	window.window_size.y_size = (short)height;
X
X	array_index = 0;
X	for (i = 0; i < height; i++)
X	 {
X		for (j = 0; j < words - odd; j++)
X		{
X			word = *s++ & 0x00FF;
X			word = (word << 8) & 0xFF00;
X			word = word | (*s++ & 0x00FF);
X
X			for (k=0; k<16; k++)
X			{
X				pixel_array[array_index++] = (word >> (16-k-1)) & 0x0001 ;
X			}
X		}
X		if (odd)
X		{
X			word = *s++ & 0x00FF;
X			word = (word << 8) & 0xFF00;
X			word = word | (*s++ & 0x00FF);
X
X			for (k=0; k<16; k++)
X			{
X				pixel_array[array_index++] = (word >> (16-k-1)) & 0x0001;
X			}
X		}
X	 }
X
X	gpr_$write_pixels (pixel_array, window, status);
X	check_status (status);
X
X	bm = (struct pixrect *) Malloc (sizeof (struct pixrect));
X	bm->ident = (int)desc;
X
X	return (struct hardware *) NewHardware (bm, real_extent, 0);
X}
X
X/**************************************** UPDATE CONTROLS ******************************************/
X
void UpdateControl (h, on) struct hardware *h; int on;
X{
X/*
X * 	This call can be used to enable batching of output operations. UpdateControl (h, FALSE) means ``start of
X *	batching'' UpdateControl (h, TRUE) means ``end of batching''. It is used to improve performance on machines
X *	where screen updates have a high locking overhead. It may be a no-op.
X *	The operation should nest if batching is already in progress: FALSE increments a counter,
X *	TRUE decrements a counter. Display changes are allowed when the counter is non-zero.
X */
X
X	boolean			unobscured;
X	status_$t               status;
X
X	Message ("UpdateControl");
X
X	if (on)
X	{
X		gpr_$release_display (status);
X		check_status (status);
X	}
X	else
X	{
X		unobscured = gpr_$acquire_display (status);
X		check_status (status);
X	}
X
X}
X/********************************** CANONICAL IMPLEMENTATION LIBRARY ******************************/
X
X/*
X *	Some parts of the above interface can be supported by a canonical library.
X *	This library contains:
X
SetClipHardware
HardUpdate
IsWindowHardware
HardwareExtent
X
PaintTrapezoid
BitBltTrapezoid
X
Paint
PaintLine
X
DeviceMatrix
InitTransfer
TransferSize
SetTransfer
ScreenSize
BuildScreen
SetScreen
X
X *
X *	As the driver matures, the user may provide his own versions of the canonical routines.
X *	This leaves the following for implementation by the user.
X *
X
InitHardware
NewBitmapHardware
NewWindowHardware
DestroyHardware
HardwareFromString
StringFromHardware
UpdateControl
RasterTile
BitBlt
BitBltLine
BitBltBlob
X
X *	There is a pedagogical implementation in null.c
X *	
X *	There are a number of interface issues concerning the canonical driver.
X *	Firstly, a canonical struct hardware is defined, which contains a union of
X *	a char * and an int handle. The remainder are expected to use this to store
X *	device specific information.
X *
X *	InitTransfer() should be called during InitHardware with the number of pixels
X *	per inch on the display as an argument.
X */
X
check_status (status)
status_$t	status;
X{
X	if (status.all != status_$ok)
X	{
X		error_$print (status);
X		exit (1);
X	}
X}
END_OF_FILE
if test 20529 -ne `wc -c <'hard.c'`; then
    echo shar: \"'hard.c'\" unpacked with wrong size!
fi
# end of 'hard.c'
fi
if test -f 'image.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'image.c'\"
else
echo shar: Extracting \"'image.c'\" \(12073 characters\)
sed "s/^X//" >'image.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X#include "main.h"
X#include "graphics.h"
X
static int RealImage ();
static int RealImageMask ();
X
struct hardware *ScaleBitmap ();
X
InitImage ()
X {
X 	InstallOp ("realimage",		RealImage,	5, 0, 0, 0, Integer, Integer, Integer, Array, String);
X 	InstallOp ("realimagemask",	RealImageMask,	5, 0, 0, 0, Integer, Integer, Boolean, Array, String);
X }
X
static int RealImageMask (width, height, invert, mat, string) Object width, height, invert, mat, string;
X {
X 	Matrix m, m2;
X 	Vector origin, right, bottom;
X 	int w = BodyInteger (width), h = BodyInteger (height);
X 	int inv = BodyBoolean (invert), l = lengthString (string);
X 	int dwidth, dheight;
X 	unsigned char *s = BodyString (string);
X 	struct hardware *from, *to;
X 	
X  	VOID GSave ();
X	if (!ExtractMatrix (&m, mat))
X 		return Error (PTypeCheck);
X 	if (l != (w + 7) / 8 * h || w < 0 || h < 0)
X 		return Error (PRangeCheck);
X 	if (w == 0 || h == 0)
X 		return TRUE;
X 	m = MatInvert (m);
X 	gstate->CTM = m2 = MatMult (m, gstate->CTM);
X 	origin = Transform (NewVector (0.0, 0.0, 1.0), m2);
X 	right  = Transform (NewVector ((float) w, 0.0, 1.0), m2);
X 	bottom = Transform (NewVector (0.0, (float) h, 1.0), m2);
X 	/* fprintf (stderr, "origin = (%g, %g), right = (%g, %g), bottom = (%g, %g)\n", origin.vx, origin.vy, right.vx, right.vy, bottom.vx, bottom.vy);
X 	fprintf (stderr, "matrix == [%g %g %g %g %g %g]\n", m2.A, m2.B, m2.C, m2.D, m2.tx, m2.ty);*/
X 	
X 	dwidth = right.vx - origin.vx; dheight = bottom.vy - origin.vy;
X 	
X 	if (origin.vx == bottom.vx && origin.vy == right.vy &&
X 			dwidth > 0 && dheight > 0/* && dwidth >= w && dheight >= h*/)
X 	 {		/* simple orientation */
X 	 	
X 	 	from = HardwareFromString (s, w, h);
X 	 	if (!inv)
X 	 		BitBlt (from, from,
X 	 			NewDevicePoint (0, 0), NewDevicePoint (0, 0),
X 	 			HardwareExtent (from), ROP_NOTSOURCE);
X 		if (dwidth != w || dheight != h)
X 		 {
X 	 		to = ScaleBitmap (from, (float) dwidth / w, (float) dheight / h);
X 	 		DestroyHardware (from);
X 	 	 }
X 	 	else
X 	 		to = from;
X 	 	
X 	 	Paint (to, gstate->device->dev,
X 	 		NewDevicePoint (0, 0),
X 	 		NewDevicePoint ((int) origin.vx, (int) origin.vy),
X 	 		NewDevicePoint (dwidth, dheight),
X 	 		gstate->colour);
X 	 	DestroyHardware (to);
X 	 }
X 	else
X 		DrawBitmap (s, w, h, inv);
X	VOID GRestore ();
X	
X	return TRUE;
X }
X
DrawBitmap (s, width, height, inv) unsigned char *s; int width, height, inv;
X {
X 	int w, h;
X 	
X 	VOID PNewPath ();
X 	
X 	for (h = 0; h < height; h++)
X 		for (w = 0; w < width; w++)
X 		 	if (((s [h * (width >> 3) + (w >> 3)] & (1 << (7 - (w & 0x7)))) != 0) == inv)
X  		 	 	FillUnitBox (w, h);
X }
X
void Tile (t, h) struct hardware *t, *h;
X {
X 	DevicePoint xt, xh;
X 	int i, sw, sh;
X 	
X 	xt = HardwareExtent (t);
X 	xh = HardwareExtent (h);
X 	
X  	BitBlt (t, h, NewDevicePoint (0, 0), NewDevicePoint (0, 0), xt, ROP_SOURCE);
X 	
X 	sw = xt.dx;
X	for (i = sw;;)
X 	 {
X 		BitBlt (h, h, NewDevicePoint (0, 0), NewDevicePoint (i, 0), NewDevicePoint (sw, xt.dy), ROP_SOURCE);
X 		if (i >= xh.dx)
X 			break;
X 		i += sw;
X 		sw <<= 1;
X 	 }
X 	
X 	sh = xt.dy;
X	for (i = sh;;)
X 	 {
X 		BitBlt (h, h, NewDevicePoint (0, 0), NewDevicePoint (0, i), NewDevicePoint (xh.dx, sh), ROP_SOURCE);
X 		if (i >= xh.dy)
X 			break;
X 		i += sh;
X 		sh <<= 1;
X 	 }
X }
X
void FillMask (h, mask, width) struct hardware *h; char mask; int width;
X {
X 	struct hardware *m;
X 	
X 	mask <<= 8 - width;
X 	
X 	m = HardwareFromString (&mask, width, 1);
X 	
X 	Tile (m, h);
X 	
X 	DestroyHardware (m);
X }
X
struct hardware *UnpaddedHardwareFromString (s, w, h) unsigned char *s; int w, h;
X {
X 	struct hardware *thin;
X 	struct hardware *res;
X 	int i;
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X/* 	
X 	if (w & 7 == 0)
X 		return HardwareFromString (s, w, h);
X*/
X 	if ((w & 7) == 0)
X 		return HardwareFromString (s, w, h);
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X 	
X 	thin = HardwareFromString (s, w * h, 1);
X 	res = NewBitmapHardware (w, h);
X 	
X 	for (i = 0; i < h; i++)
X 		BitBlt (thin, res, NewDevicePoint (i * w, 0), NewDevicePoint (0, i), NewDevicePoint (w, 1), ROP_SOURCE);
X 	
X 	DestroyHardware (thin);
X 	return res;
X }
X
static void VerticalReverseImage (h) struct hardware *h;
X {
X 	DevicePoint ex;
X 	int i, n;
X 	
X 	ex = HardwareExtent (h);
X 	
X 	n = ex.dy;
X 	
X 	for (i = 0; i < n / 2; i++)
X 		BitBlt (h, h, NewDevicePoint (0, i), NewDevicePoint (0, n - i - 1), NewDevicePoint (ex.dx, 1), ROP_XOR),
X 		BitBlt (h, h, NewDevicePoint (0, n - i - 1), NewDevicePoint (0, i), NewDevicePoint (ex.dx, 1), ROP_XOR),
X 		BitBlt (h, h, NewDevicePoint (0, i), NewDevicePoint (0, n - i - 1), NewDevicePoint (ex.dx, 1), ROP_XOR);
X }
X
static int RealImage (width, height, depth, mat, string) Object width, height, depth, mat, string;
X {
X 	Matrix m, m2;
X 	Vector origin, right, bottom;
X 	int w = BodyInteger (width), h = BodyInteger (height);
X 	int vrev = 0, dep = BodyInteger (depth), l = lengthString (string);
X 	int dwidth, dheight;
X 	unsigned char *s = BodyString (string);
X 	
X   	VOID GSave ();
X	if (!ExtractMatrix (&m, mat))
X 		return Error (PTypeCheck);
X 	if (l != (w * dep + 7) / 8 * h || w < 0 || h < 0)
X 		return Error (PRangeCheck);
X 	if (w == 0 || h == 0)
X 		return TRUE;
X  	m = MatInvert (m);
X 	gstate->CTM = m2 = MatMult (m, gstate->CTM);
X 	origin = Transform (NewVector (0.0, 0.0, 1.0), m2);
X 	right  = Transform (NewVector ((float) w, 0.0, 1.0), m2);
X 	bottom = Transform (NewVector (0.0, (float) h, 1.0), m2);
X 	
X	dwidth = right.vx - origin.vx; dheight = bottom.vy - origin.vy;
X	
X	if (dheight < 0)
X		origin.vy += dheight, right.vy += dheight, ++vrev, dheight = -dheight;
X	
X	/* fprintf (stderr, "origin.vx = %g, origin.vy = %g, bottom.vx = %g, right.vy = %g, dwidth = %d, dheight = %d, w = %d, h = %d\n",
X			origin.vx, origin.vy, bottom.vx, right.vy, dwidth, dheight, w, h); */
X 	
X 	if (dep != 16 && (int) origin.vx == (int) bottom.vx && (int) origin.vy == (int) right.vy &&
X 			dwidth > 0 && dheight > 0/* && dwidth >= w && dheight >= h */)
X 	 {		/* simple orientation */
X	 	struct hardware *from, *to;
X
X 	 	if (dep == 1)
X 	 	 {
X 	 		from = HardwareFromString (s, w, h);
X 	 		if (vrev)
X 	 			VerticalReverseImage (from);
X 			if (dwidth != w || dheight != h)
X 			 {
X 	 			to = ScaleBitmap (from, (float) dwidth / w, (float) dheight / h);
X 	 			DestroyHardware (from);
X 	 		 }
X 	 		else
X 	 			to = from;
X 	 		
X			Paint (to, gstate->device->dev,
X				NewDevicePoint (0, 0), NewDevicePoint ((int) origin.vx, (int) origin.vy),
X				NewDevicePoint (dwidth, dheight),
X				NewGray (1.0));
X			BitBlt (to, to,
X				NewDevicePoint (0, 0), NewDevicePoint (0, 0),
X				NewDevicePoint (dwidth, dheight),
X				ROP_NOTSOURCE);
X			Paint (to, gstate->device->dev,
X				NewDevicePoint (0, 0), NewDevicePoint ((int) origin.vx, (int) origin.vy),
X				NewDevicePoint (dwidth, dheight),
X				NewGray (0.0));
X 	 		DestroyHardware (to);
X 	 	 }
X 	 	else
X 	 	 {
X 	 		struct hardware *mask, *new, *temp;
X 	 	 	int i, j;
X
X 	 	 	from = HardwareFromString (s, w * dep, h);
X  	 		if (vrev)
X 	 			VerticalReverseImage (from);
X 	 	 	new = HardwareFromString (s, w, h);
X	 	 	mask = NewBitmapHardware (w * dep, h);
X 	 	 	temp = NewBitmapHardware (w * dep, h);
X 	 	 	
X 	 	 	for (i = 0; i < (1<<dep); i++)
X 	 	 	 {
X 	 	 	 	FillMask (mask, i, dep);
X	 	 	 	
X	 	 	 	BitBlt (from, mask, NewDevicePoint (0, 0), NewDevicePoint (0, 0), HardwareExtent (from), ROP_NXOR);
X	 	 	 	BitBlt (NULL, temp, NewDevicePoint (0, 0), NewDevicePoint (0, 0), HardwareExtent (temp), ROP_TRUE);
X 	 	 	 	for (j = 0; j < dep; j++)
X 	 	 	 		BitBlt (mask, temp, NewDevicePoint (j, 0), NewDevicePoint (0, 0), HardwareExtent (mask), ROP_AND);
X 	 	 	 	for (j = 0; j < w; j++)
X 	 	 	 		BitBlt (temp, new, NewDevicePoint (j * dep, 0), NewDevicePoint (j, 0), NewDevicePoint (1, h), ROP_SOURCE);
X 	 	 	 	to = ScaleBitmap (new, (float) dwidth / w, (float) dheight / h);
X		  	 	Paint (to, gstate->device->dev,
X		 	 		NewDevicePoint (0, 0),
X		 	 		NewDevicePoint ((int) origin.vx, (int) origin.vy),
X		 	 		NewDevicePoint (dwidth, dheight),
X		 	 		NewGray ((float) i / ((1 << dep) - 1)));
X		 	 	DestroyHardware (to);
X	 	 	 }
X 	 		DestroyHardware (from);
X 	 		DestroyHardware (mask);
X 	 		DestroyHardware (temp);
X 	 		DestroyHardware (new);
X 	 	 }
X 	 }
X 	else
X 	 {
X 	 	if (vrev)
X 	 		origin.vy += dheight, right.vy += dheight, dheight = -dheight;
X 		DrawColourBitmap (s, w, h, dep);
X 	 }
X	VOID GRestore ();
X	
X	return TRUE;
X }
X
static log2[] = { 0, 0, 1, 0, 2, 0, 0, 0, 3 };
static mask[] = { 0, 0x80, 0xc0, 0, 0xf0, 0, 0, 0, 0xff };
X
DrawColourBitmap (s, width, height, depth) unsigned char *s; int width, height, depth;
X {
X 	int w, h, c;
X 	
X 	VOID PNewPath ();
X 	
X 	if (depth == 16)
X 		for (h = 0; h < height; h++)
X 			for (w = 0; w < width; w++)
X 		 	 {
X 		 	 	gstate->colour = NewColour (0.0, 0.0, (float) ((s [h * (width << 1) + (w << 1)] << 8) |
X 		 	 						s [h * (width << 1) + (w << 1) + 1]) / (1 << 16));
X 		 	 	FillUnitBox (w, h);
X 		 	 }
X 	else
X 		for (c = 0; c < 1 << depth; c++)
X 		 {
X  		 	gstate->colour = NewColour (0.0, 0.0, (float) c / ((1 << depth) - 1));
X			for (h = 0; h < height; h++)
X 				for (w = 0; w < width; w++)
X 				 {
X 			 		int foo = 3 - log2 [depth];
X 			 		int byte = s [h * (width >> foo) + (w >> foo)];
X 			 		int shift = (w & ((1 << foo) - 1)) * depth;
X 			 		if (c == ((byte & (mask [depth] >> shift)) >> (8 - (shift + depth))))
X 		 	 			FillUnitBox (w, h);
X 		 		 }
X 		  }
X }
X
XFillUnitBox (w, h) int w, h;
X {
X 	VOID MoveTo (gstate->path, ExtToInt (NewPoint ((float ) w, (float ) h)));
X	VOID LineTo (gstate->path, ExtToInt (NewPoint ((float ) w+1, (float ) h)));
X	VOID LineTo (gstate->path, ExtToInt (NewPoint ((float ) w+1, (float ) h+1)));
X	VOID LineTo (gstate->path, ExtToInt (NewPoint ((float ) w, (float ) h+1)));
X	VOID ClosePath (gstate->path);
X	VOID Fill ();
X  }
X
struct hardware *ScaleBitmap (from, xscale, yscale) struct hardware *from; float xscale, yscale;
X {	 	 	
X	struct hardware *middle, *middle2, *high, *high2;
X	int i, w, h, dwidth, dheight, ixscale, iyscale;
X	DevicePoint extent;
X	
X	extent = HardwareExtent (from);
X	w = extent.dx; h = extent.dy;
X	dwidth = w * xscale + 0.5; dheight = h * yscale + 0.5;
X	
X	if (dwidth > w)
X	 {
X		middle = NewBitmapHardware (dwidth, h);
X		for (i = 0; i < w; i++)
X			BitBlt (from, 	middle,
X				NewDevicePoint (i, 0), NewDevicePoint ((int) (i*xscale), 0),
X				NewDevicePoint (1, h),
X				ROP_OR);
X		middle2 = NewBitmapHardware (dwidth, h);
X		ixscale = (int) ((float) dwidth / w + 0.5); 
X		for (i = 0; i < ixscale + 1; i++)
X			BitBlt (middle, middle2,
X				NewDevicePoint (0, 0), NewDevicePoint (i, 0),
X				NewDevicePoint (dwidth - ixscale + 1, h),
X				ROP_OR);
X		DestroyHardware (middle);
X	 }
X	else
X	 {
X	 	middle2 = NewBitmapHardware (dwidth, h);
X		for (i = 0; i < dwidth; i++)
X			BitBlt (from, 	middle2,
X				NewDevicePoint ((int) (i/xscale), 0), NewDevicePoint (i, 0),
X				NewDevicePoint (1, h),
X				ROP_OR);
X	 }
X	
X	if (dheight > h)
X	 {
X		high = NewBitmapHardware (dwidth, dheight);
X		for (i = 0; i < h; i++)
X			BitBlt (middle2, high,
X				NewDevicePoint (0, i), NewDevicePoint (0, (int) (i*yscale)),
X				NewDevicePoint (dwidth, 1),
X				ROP_OR);
X		DestroyHardware (middle2);
X		
X		high2 = NewBitmapHardware (dwidth, dheight);
X		iyscale = (int) ((float) dheight / h + 0.5);
X		for (i = 0; i < iyscale + 1; i++)
X			BitBlt (high, 	high2, 
X				NewDevicePoint (0, 0), NewDevicePoint (0, i),
X				NewDevicePoint (dwidth, dheight - iyscale + 1),
X				ROP_OR);
X		DestroyHardware (high);
X	 }
X	else
X	 {
X		high2 = NewBitmapHardware (dwidth, dheight);
X		for (i = 0; i < dheight; i++)
X			BitBlt (middle2, high2,
X				NewDevicePoint (0, (int) (i/yscale)), NewDevicePoint (0, i),
X				NewDevicePoint (dwidth, 1),
X				ROP_OR);
X	 }
X 	return high2;
X }
END_OF_FILE
if test 12073 -ne `wc -c <'image.c'`; then
    echo shar: \"'image.c'\" unpacked with wrong size!
fi
# end of 'image.c'
fi
if test -f 'path.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'path.c'\"
else
echo shar: Extracting \"'path.c'\" \(11290 characters\)
sed "s/^X//" >'path.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X#include "main.h"
X
X#include "graphics.h"
X
X#define PATHFORALLDEPTH 500
X	
static int PCurrentPoint ();
static int PMoveTo ();
static int PRMoveTo ();
static int PLineTo ();
static int PRLineTo ();
static int PArc ();
static int PArcN ();
static int PArcTo ();
static int PCurveTo ();
static int PRCurveTo ();
static int PClosePath ();
static int PPathBBox ();
static int PReversePath ();
static int PPathForAll ();
X
static int PathForAll ();
static int PPathProc ();
X
int PFlattenPath ();
X
Object OpPathForAll;
X
InitPath ()
X {
X 	OpPathForAll = MakeOp ("(oppathforall)", PathForAll, 0, 6, 7, 7);
X 	
X 	InstallOp ("newpath",		PNewPath,	0, 0, 0, 0);
X 	InstallOp ("currentpoint",	PCurrentPoint,	0, 2, 0, 0);
X  	InstallOp ("moveto",		PMoveTo,	2, 0, 0, 0, Float, Float);
X	InstallOp ("rmoveto",		PRMoveTo,	2, 0, 0, 0, Float, Float);
X 	InstallOp ("lineto",		PLineTo,	2, 0, 0, 0, Float, Float);
X 	InstallOp ("rlineto",		PRLineTo,	2, 0, 0, 0, Float, Float);
X 	InstallOp ("arc",		PArc,		5, 0, 0, 0, Float, Float, Float, Float, Float);
X 	InstallOp ("arcn",		PArcN,		5, 0, 0, 0, Float, Float, Float, Float, Float);
X 	InstallOp ("arcto",		PArcTo,		5, 4, 0, 0, Float, Float, Float, Float, Float);
X 	InstallOp ("curveto",		PCurveTo,	6, 0, 0, 0, Float, Float, Float, Float, Float, Float);
X 	InstallOp ("rcurveto",		PRCurveTo,	6, 0, 0, 0, Float, Float, Float, Float, Float, Float);
X 	InstallOp ("closepath",		PClosePath,	0, 0, 0, 0);
X 	InstallOp ("pathbbox",		PPathBBox,	0, 4, 0, 0);
X 	InstallOp ("flattenpath",	PFlattenPath,	0, 0, 0, 0);
X 	InstallOp ("reversepath",	PReversePath,	0, 0, 0, 0);
X 	InstallOp ("pathforall",	PPathForAll,	4, 0, 0, 6, Array, Array, Array, Array);
X 	InstallOp ("pathproc",		PPathProc,	0, 1, 0, 0);
X	gstate->path = NewPath ();
X	gstate->clip = NewPath ();
X }
X
int PNewPath ()
X {
X 	gstate->cp_defined = FALSE;
X 	PathFree (gstate->path);
X 	gstate->path = NewPath ();
X 	return TRUE;
X }
X
static int PCurrentPoint ()
X {
X 	Point cp;
X 	
X	if (!gstate->cp_defined)
X 		return Error (PNoCurrentPoint);
X 	cp = IntToExt (gstate->cp);
X 	VOID Push (OpStack, MakeReal (PointX (cp)));
X 	VOID Push (OpStack, MakeReal (PointY (cp)));
X 	return TRUE;
X }
X
static int PMoveTo (x, y) Object x, y;
X {
X 	return MoveTo (gstate->path, ExtToInt (NewPoint (BodyReal (x), BodyReal (y))));
X }
X
static int PRMoveTo (x, y) Object x, y;
X {
X	if (!gstate->cp_defined)
X 		return Error (PNoCurrentPoint);
X 	return MoveTo (gstate->path, ExtToInt (MovePoint (NewPoint (BodyReal (x), BodyReal (y)), IntToExt (gstate->cp))));
X }
X
static int PLineTo (x, y) Object x, y;
X {
X	if (!gstate->cp_defined)
X 		return Error (PNoCurrentPoint);
X	return LineTo (gstate->path, ExtToInt (NewPoint (BodyReal (x), BodyReal (y))));
X }
X
X
static int PRLineTo (x, y) Object x, y;
X {
X	if (!gstate->cp_defined)
X 		return Error (PNoCurrentPoint);
X 	return LineTo (gstate->path, ExtToInt (MovePoint (NewPoint (BodyReal (x), BodyReal (y)), IntToExt (gstate->cp))));
X }
X
static int PArc (x, y, rad, ang1, ang2) Object x, y, rad, ang1, ang2;
X {
X 	Point centre, start;
X 	float a1 = Rad (BodyReal (ang1)), a2 = Rad (BodyReal (ang2));
X 	float r = BodyReal (rad);
X
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X 	int status;
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X
X 	start = NewPoint (cos (a1) * r, sin (a1) * r);
X 	centre = NewPoint (BodyReal (x), BodyReal (y));
X
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X/*
X 	if (!(*(EmptyPath (gstate->path) ? MoveTo : LineTo)) (gstate->path, ExtToInt (MovePoint (centre, start))))
X		return FALSE;
X*/
X 	if (EmptyPath (gstate->path))
X		status = MoveTo (gstate->path, ExtToInt (MovePoint (centre, start)));
X	else
X		status = LineTo (gstate->path, ExtToInt (MovePoint (centre, start)));
X	
X        if (!status)
X		return FALSE;
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X
X 	return Arc (gstate->path, 1, centre, r, a1, a2);
X }
X
static int PArcN (x, y, rad, ang1, ang2) Object x, y, rad, ang1, ang2;
X {
X 	Point centre, start;
X 	float a1 = Rad (BodyReal (ang1)), a2 = Rad (BodyReal (ang2));
X 	float r = BodyReal (rad);
X
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X 	int status;
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X 	
X 	start = NewPoint (cos (a1) * r, sin (a1) * r);
X 	centre = NewPoint (BodyReal (x), BodyReal (y));
X
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X/*
X 	if (!(*(EmptyPath (gstate->path) ? MoveTo : LineTo)) (gstate->path, ExtToInt (MovePoint (centre, start))))
X		return FALSE;
X*/
X
X 	if (EmptyPath (gstate->path))
X		status = MoveTo (gstate->path, ExtToInt (MovePoint (centre, start)));
X	else
X		status = LineTo (gstate->path, ExtToInt (MovePoint (centre, start)));
X	
X        if (!status)
X		return FALSE;
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X
X 	return Arc (gstate->path, -1, centre, r, a1, a2);
X }
X
static int PArcTo (X1, Y1, X2, Y2, rad) Object X1, Y1, X2, Y2, rad;
X {
X 	float xt1, xt2, yt1, yt2;
X 	if (!gstate->cp_defined)
X 		return Error (PNoCurrentPoint);
X 	
X	return ArcTo (gstate->path, gstate->cp,
X			BodyReal (X1), BodyReal (Y1), BodyReal (X2), BodyReal (Y2), BodyReal (rad),
X 			&xt1, &yt1, &xt2,  &yt2) &&
X 		Push (OpStack, MakeReal (xt1)) &&
X		Push (OpStack, MakeReal (yt1)) &&
X		Push (OpStack, MakeReal (xt2)) &&
X		Push (OpStack, MakeReal (yt2));
X }
X
static int PCurveTo (x0, y0, x1, y1, x2, y2) Object x0, y0, x1, y1, x2, y2;
X {
X	if (!gstate->cp_defined)
X 		return Error (PNoCurrentPoint);
X 	return CurveTo (gstate->path,
X 			ExtToInt (NewPoint (BodyReal (x0), BodyReal (y0))),
X 			ExtToInt (NewPoint (BodyReal (x1), BodyReal (y1))),
X 			ExtToInt (NewPoint (BodyReal (x2), BodyReal (y2))));
X }
X
static int PRCurveTo (x0, y0, x1, y1, x2, y2) Object x0, y0, x1, y1, x2, y2;
X {
X 	Point cp;
X 	
X	if (!gstate->cp_defined)
X 		return Error (PNoCurrentPoint);
X 	cp = IntToExt (gstate->cp);
X 	return CurveTo (gstate->path,
X 			ExtToInt (MovePoint (cp, NewPoint (BodyReal (x0), BodyReal (y0)))),
X 			ExtToInt (MovePoint (cp, NewPoint (BodyReal (x1), BodyReal (y1)))),
X 			ExtToInt (MovePoint (cp, NewPoint (BodyReal (x2), BodyReal (y2)))));
X }
X
static int PClosePath ()
X {
X 	return ClosePath (gstate->path);
X }
X
int PFlattenPath ()
X {
X 	Path res;
X 	
X 	if ((res = FlattenPath (gstate->path)) == NULL)
X 		return Error (PLimitCheck);
X 	SetPath (&gstate->path, res);
X	return TRUE;
X }
X
static int PReversePath ()
X {
X	Path res;
X 	
X 	if ((res = ReversePath (gstate->path)) == NULL)
X 		return Error (PLimitCheck);
X  	SetPath (&gstate->path, res);
X 	return TRUE;	
X }
X
static Path pathforall [PATHFORALLDEPTH], *pathp = pathforall;
static int path_depth = 0;
X
static int PPathForAll (move, line, curve, close) Object move, line, curve, close;
X {
X 	Path res;
X 	
X 	if ((res = PathCopy (gstate->path)) == NULL || path_depth == PATHFORALLDEPTH - 1)
X 		return Error (PLimitCheck);
X 	*++pathp = res;
X 	++path_depth;
X 	VOID Push (ExecStack, Nil);
X 	VOID Push (ExecStack, move);
X 	VOID Push (ExecStack, line);
X 	VOID Push (ExecStack, curve);
X 	VOID Push (ExecStack, close);
X 	VOID Push (ExecStack, OpPathForAll);
X 	return TRUE;
X }
X
static int PathForAll ()
X {
X 	Path res;
X 	Object move, line, curve, close, fn;
X 	Point p;
X 	
X 	close = Pop (ExecStack);
X 	curve = Pop (ExecStack);
X 	line = Pop (ExecStack);
X 	move = Pop (ExecStack);
X 	if (EmptyPath (*pathp))
X 	 {
X 	 	PathFree (*pathp--);
X 	 	--path_depth;
X 	 	VOID Pop (ExecStack);
X 		return TRUE;
X 	 }
X 	res = (*pathp)->next;
X 	switch (res->ptype)
X 	 {
X 	 	case EMove:
X 	 		p = IntToExt (res->pe.point);
X 	 		VOID Push (OpStack, MakeReal (p.x));
X 	 		VOID Push (OpStack, MakeReal (p.y));
X 	 		fn = move;
X 	 		break;
X 	 	
X 	 	case ELine:
X  	 		p = IntToExt (res->pe.point);
X 	 		VOID Push (OpStack, MakeReal (p.x));
X 	 		VOID Push (OpStack, MakeReal (p.y));
X 	 		fn = line;
X 	 		break;
X 	 	
X	 	case ECurve:
X	 		p = IntToExt (res->pe.curve.x0);
X 	 		VOID Push (OpStack, MakeReal (p.x));
X 	 		VOID Push (OpStack, MakeReal (p.y));
X	 		p = IntToExt (res->pe.curve.x1);
X 	 		VOID Push (OpStack, MakeReal (p.x));
X 	 		VOID Push (OpStack, MakeReal (p.y));
X	 		p = IntToExt (res->pe.curve.x2);
X 	 		VOID Push (OpStack, MakeReal (p.x));
X 	 		VOID Push (OpStack, MakeReal (p.y));
X	 		fn = curve;
X	 		break;
X	 	
X	 	case EClose:
X	 		fn = close;
X	 		break;
X	 	
X	 	default:
X	 		Panic ("OpPathForAll - encounters unknown path element");
X	 }
X	VOID Push (ExecStack, move);
X	VOID Push (ExecStack, line);
X	VOID Push (ExecStack, curve);
X	VOID Push (ExecStack, close);
X	VOID Push (ExecStack, OpPathForAll);
X	VOID Push (ExecStack, fn);
X	
X	PathDelete (res->next);
X	return TRUE;
X }
X
static int PPathProc ()
X {
X 	Object *body, *p;
X 	int sum = 0;
X 	Path pa;
X 	Point po;
X 	
X 	for (pa = gstate->path->next; pa != gstate->path; pa = pa->next)
X 		switch (pa->ptype)
X 		 {
X 		 	case EMove: case ELine: sum += 3; break;
X 		 	case ECurve: sum += 7; break;
X 		 	case EClose: ++sum; break;
X 		 }
X 	
X	p = body = (Object *) Malloc ((unsigned) sizeof (Object) * sum);
X 	for (pa = gstate->path->next; pa != gstate->path; pa = pa->next)
X 		switch (pa->ptype)
X 		 {
X 		 	case EMove:
X 		 		po = IntToExt (pa->pe.point);
X  		 		*p++ = MakeReal (po.x);
X 		 		*p++ = MakeReal (po.y);
X  		 		*p++ = Cvx (NameFrom ("moveto"));
X		 		break;
X 		 	
X		 	case ELine:
X		 		po = IntToExt (pa->pe.point);
X  		 		*p++ = MakeReal (po.x);
X 		 		*p++ = MakeReal (po.y);
X  		 		*p++ = Cvx (NameFrom ("lineto"));
X		 		break;
X 		 	
X 		 	case ECurve:
X 		 		po = IntToExt (pa->pe.curve.x0);
X  		 		*p++ = MakeReal (po.x);
X 		 		*p++ = MakeReal (po.y);
X 		 		po = IntToExt (pa->pe.curve.x1);
X  		 		*p++ = MakeReal (po.x);
X 		 		*p++ = MakeReal (po.y);
X		 		po = IntToExt (pa->pe.curve.x2);
X  		 		*p++ = MakeReal (po.x);
X 		 		*p++ = MakeReal (po.y);
X		 		*p++ = Cvx (NameFrom ("curve"));
X		 		break;
X 		 	
X 		 	case EClose:
X 		 		*p++ = Cvx (NameFrom ("closepath"));
X 		 		break;
X 		 }
X 	return Push (OpStack, Cvx (MakeArray (body, sum)));
X }
X
static int PPathBBox ()
X {
X 	Point right_top, left_bottom, left_top, right_bottom;
X 	float left, right, top, bottom, uleft, uright, utop, ubottom;
X 	
X 	if (!PathBBox (&left, &right, &top, &bottom))
X 		return FALSE;
X 	
X 	left_bottom	= IntToExt (NewHardPoint (left, bottom));
X 	right_bottom	= IntToExt (NewHardPoint (right, bottom));
X 	right_top 	= IntToExt (NewHardPoint (right, top));
X 	left_top	= IntToExt (NewHardPoint (left, top));
X 	
X 	uleft = uright = left_bottom.x; utop = ubottom = left_bottom.y;
X 	UserBound (&uleft, &uright, &utop, &ubottom, left_top);
X 	UserBound (&uleft, &uright, &utop, &ubottom, right_top);
X 	UserBound (&uleft, &uright, &utop, &ubottom, right_bottom);
X 	
X 	VOID Push (OpStack, MakeReal (uleft));
X  	VOID Push (OpStack, MakeReal (ubottom));
X 	VOID Push (OpStack, MakeReal (uright));
X	VOID Push (OpStack, MakeReal (utop));
X 	
X	return TRUE;
X }
END_OF_FILE
if test 11290 -ne `wc -c <'path.c'`; then
    echo shar: \"'path.c'\" unpacked with wrong size!
fi
# end of 'path.c'
fi
if test -f 'protocol.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'protocol.c'\"
else
echo shar: Extracting \"'protocol.c'\" \(3551 characters\)
sed "s/^X//" >'protocol.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X#include <stdio.h>
X
X#include "main.h"
X#include "graphics.h"
X#include "protocol.h"
X
X#define SCALE 16384
X
static FILE *devfpi, *devfpo;
char *getenv (), *strcpy (), *strcat ();
unsigned char getb ();
X
void master_protocol ()
X {
X 	char name [BUFSIZ], *e = getenv ("POSTSCRIPTDEVICE");
X 	
X 	if (e == NULL || *e == '\0')
X 		VOID strcpy (name, "|viewer");
X 	else
X 		VOID strcpy (name, e);
X 	if (*name == '|')
X 	 {
X 	 	int ip[2], op[2];
X 	 	
X 	 	pipe (ip);
X 	 	pipe (op);
X 	 	devfpi = fdopen (ip[0], "r");
X 	 	devfpo = fdopen (op[1], "w");
X 	 	
X 	 	if (fork () == 0)
X 	 	 {
X 	 	 	dup2 (op[0], 0);
X 	 	 	dup2 (ip[1], 1);
X 	 	 	close (op[1]);
X 	 	 	close (ip[0]);
X 	 	 	
X 	 	 	execl ("/bin/sh", "PSDEV", "-c", name + 1, NULL);
X 	 	 	fprintf (stderr, "NO SHELL!\n");
X 	 	 	exit (1);
X 	 	 }
X 	 	else
X 	 	 {
X 	 	 	close (op[0]);
X 	 	 	close (ip[1]);
X 	 	 }
X 	 }
X 	else if (*name == '%')
X 	 {
X 	 	devfpi = fopen (name + 1, "r");
X 	 	devfpo = fopen (name + 1, "w");
X 	 }
X 	else
X 	 {
X 	 	devfpi = NULL;
X 	 	devfpo = fopen (name, "w");
X 	 }
X }
X
void slave_protocol ()
X {
X	devfpi = stdin;
X	devfpo = stdout;
X }
X
void send_colour (colour) Colour colour;
X {
X 	send_small (colour.hue);
X 	send_small (colour.saturation);
X 	send_small (colour.brightness);
X }
X
Colour recv_colour ()
X {
X 	Colour res;
X 	
X 	res.hue = recv_small ();
X 	res.saturation = recv_small ();
X 	res.brightness = recv_small ();
X 	
X 	return res;
X }
X
void send_small (f) float f;
X {
X 	send_short ((int) (f * SCALE));
X }
X
float recv_small ()
X {
X	return (float) recv_short () / SCALE;
X }
X
void send_point (p) DevicePoint p;
X {
X	send_short (p.dx);
X	send_short (p.dy);
X }
X
DevicePoint recv_point ()
X {
X	short r = recv_short ();
X	
X	return NewDevicePoint (r, recv_short ());
X }
X
void send_byte (b) unsigned char b;
X {
X	putc (b, devfpo);
X }
X
unsigned char recv_byte ()
X {
X	return getb (devfpi);
X }
X
void send_short (i) short i;
X {
X 	send_byte (i & 0xff);
X 	send_byte (i >> 8);
X }
X
short recv_short ()
X {
X	short i;
X	
X	i = recv_byte () & 0xff;
X	i |= recv_byte () << 8;
X	
X	return i;
X }
X
void send_float (f) float f;
X {
X	fprintf (devfpo, "%g\n", f);
X }
X
float recv_float ()
X {
X 	float f;
X 	char buf [BUFSIZ], *p = buf;
X 	
X 	while ((*p++ = getb (devfpi)) != '\n')
X 		;
X 	*p++ = '\0';
X 	sscanf (buf, "%f\n", &f);
X 	
X 	return f;
X }
X
void send_string (s, len) char *s; int len;
X {
X 	PanicIf (len != fwrite (s, 1, len, devfpo), "could not send bitmap from driver");
X }
X
void recv_string (s, len) char *s; int len;
X {
X 	while (len--)
X 		*s++ = getb (devfpi);
X }
X
void flush_protocol ()
X {
X 	fflush (devfpo);
X }
X
int can_recv ()
X {
X 	return devfpi != NULL;
X }
X 
char buffer [BUFSIZ], *p;
int remaining = 0;
X
unsigned char getb (fp) FILE *fp;
X {
X 	if (remaining > 0)
X 	 {
X 	 	--remaining;
X 	 	return *p++;
X 	 }
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X/*
X 	if ((remaining = read (fp->_file, buffer, BUFSIZ)) <= 0)
X 	 	exit (1);
X*/
X 	if ((remaining = read (fp->_fd, buffer, BUFSIZ)) <= 0)
X 	 	exit (1);
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X
X 	p = buffer;
X 	return getb (fp);
X }
END_OF_FILE
if test 3551 -ne `wc -c <'protocol.c'`; then
    echo shar: \"'protocol.c'\" unpacked with wrong size!
fi
# end of 'protocol.c'
fi
if test -f 'stroke.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stroke.c'\"
else
echo shar: Extracting \"'stroke.c'\" \(12101 characters\)
sed "s/^X//" >'stroke.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X#include "main.h"
X
X#include "graphics.h"
X
extern Vector NewVector ();
extern Vector Transform ();
extern Point IntToExt ();
extern Path NewPath ();
extern Point NewPoint ();
extern Matrix Translate ();
extern Matrix Rotate ();
extern Vector ITransform ();
extern Matrix NewMatrix ();
X
int PStrokePath ();
X
int in_stroke = FALSE;
X
int Stroke ();
X
InitStroke ()
X {
X 	InstallOp ("strokepath",	PStrokePath,	0, 0, 0, 0);
X 	InstallOp ("stroke",		Stroke,		0, 0, 0, 0);
X }
X
int Stroke ()
X {
X 	int res;
X 	
X 	if (!PFlattenPath ())
X 		return FALSE;
X 	if (EmptyPath (gstate->path))
X 		return TRUE;
X 	if (gstate->device->dev == NULL)
X 		return PNewPath ();
X 	if (ThinStroke ())
X 		return TRUE;
X 	in_stroke = TRUE;
X 	res = PStrokePath () && Fill ();
X	VOID PNewPath ();
X	in_stroke = FALSE;
X	
X	return res;
X }
X
float Magnitude (v) Vector v;
X {
X 	return sqrt (v.vx * v.vx + v.vy * v.vy);
X }
X
static void Dash ()
X {
X 	Matrix m;
X 	Path p, new = NewPath (), last_move, last_dash;
X 	HardPoint move, here, next;
X 	Vector v, unit;
X 	int marking, start_marking = TRUE, index, start_index = 0;
X 	float dash_left, start_dash_left = gstate->dash_offset;
X 	float umag, dmag;
X 	
X 	m = gstate->CTM;
X 	m = NewMatrix (m.A, m.B, m.C, m.D, 0.0, 0.0);
X 	
X 	while (start_dash_left > gstate->dash_array [start_index])
X 	 {
X 	 	start_dash_left -= gstate->dash_array [start_index];
X 	 	if (++start_index == gstate->dash_length)
X 	 		start_index = 0;
X 	 	start_marking = !start_marking;
X 	 }
X 	start_dash_left = gstate->dash_array [start_index] - start_dash_left;
X 	
X 	for (p = gstate->path->next; p != gstate->path; p = p->next)
X 	 switch (p->ptype)
X 	  {
X 	  	case EMove:
X 	  		index = start_index;
X 	  		marking = start_marking;
X 	  		dash_left = start_dash_left;
X 	  		here = move = p->pe.point;
X 	  		VOID MoveTo (new, here);
X 	  		last_move = last_dash = new->last;
X 	  		break;
X 	  	
X 	  	case ELine:
X 	  	case EClose:
X 	  		next = p->ptype == ELine ? p->pe.point : move;
X 	  		v = NewVector (next.hx - here.hx, next.hy - here.hy, 1.0);
X 	  		dmag = Magnitude (v);
X 	  		if (dmag == 0)
X 	  		 {
X 	  		 	here = next;
X 	  			break;
X 	  		 }
X 	  		umag = Magnitude (ITransform (v, m));
X 	  		unit = NewVector (v.vx / umag, v.vy / umag, 1.0);
X 	  		while (umag > dash_left)
X 	  		 {
X 	  		 	here.hx += unit.vx * dash_left;
X 	  		 	here.hy += unit.vy * dash_left;
X
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X/*
X 	  		 	(*(marking ? LineTo : MoveTo)) (new, here);
X*/
X 	  		 	if (marking)
X					LineTo (new, here);
X				else
X					MoveTo (new, here);
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X
X 	  		 	if (!marking)
X 	  		 		last_dash = new->last;
X 	  		 	marking = !marking;
X 	  		 	umag -= dash_left;
X 	  		 	if (++index == gstate->dash_length)
X 	  		 		index = 0;
X 	  		 	dash_left = gstate->dash_array [index];
X 	  		 }
X 	  		if (p->ptype == ELine)
X 	  		 {
X 	  		 	dash_left -= umag;
X 	  		 	if (marking)
X 	  		 		VOID LineTo (new, next);
X 	  		 }
X 	  		else
X 	  		 {
X 	  		 	if (marking)
X 	  		 	 {
X 	  		 	 	if (start_marking)
X 	  		 	 		if (last_dash == last_move)
X 	  		 	 			ClosePath (new);
X 	  		 	 		else
X 	  		 	 		 {
X	  		 	 		 /*	LineTo (new, move);	*/
X 	  		 	 			MoveChunk (last_move, last_dash, new->last);
X 	  		 	 		 }
X 	  		 	 	else
X 	  		 	 		VOID LineTo (new, move);
X 	  		 	 }
X 	  		 }
X 	  		here = next;
X 	  		break;
X 	  	
X 	  	default:
X 	  		Panic ("Dash: unknown Path Element type");
X 	  }
X 	PathFree (gstate->path);
X 	gstate->path = new;
X 	gstate->cp = new->next->pe.point;
X }
X
MoveChunk (dest, begin, end) Path dest, begin, end;
X {
X	dest->ptype = ELine;
X	end->next->last = begin->last;
X	begin->last->next = end->next;
X	dest->last->next = begin;
X	
X	end->next = dest;
X	begin->last = dest->last;
X	dest->last = end;
X }
X
X/*
X * is 'b' to the left of 'a' ? if 'a' carries into 'b' ?
X *
X *			   /
X *			  /
X *			 b
X *			/
X *		       /
X * --------- a -------o
X * 
X */
X
leftof (a, b) float a, b;
X {
X	return Normalise (b - a) > 0;
X }
X
Miter (new, last_angle, angle, width) Path new; float last_angle, angle, width;
X {
X 	Matrix old;
X 	float diff;
X	
X	old = gstate->CTM;
X	if (leftof (last_angle, angle))
X	 {
X	 	diff = angle - last_angle;
X		VOID MoveTo (new, ExtToInt (NewPoint (0.0, 0.0)));
X		gstate->CTM = Rotate (gstate->CTM, -diff);
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, -width / 2)));
X		gstate->CTM = Rotate (gstate->CTM, diff / 2);
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, -(width / 2) / cos (diff / 2))));
X		gstate->CTM = old;
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, -width / 2)));
X	 }	
X	else
X	 {
X	 	diff = last_angle - angle;
X		VOID MoveTo (new, ExtToInt (NewPoint (0.0, 0.0)));
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, width / 2)));
X		gstate->CTM = Rotate (gstate->CTM, diff / 2);
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, (width / 2) / cos (diff / 2))));
X		gstate->CTM = Rotate (gstate->CTM, diff / 2);
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, width / 2)));
X		gstate->CTM = old;
X	 }
X	ClosePath (new);
X }
X
Bevel (new, last_angle, angle, width) Path new; float last_angle, angle, width;
X {
X 	Matrix old;
X 	float diff;
X	
X	old = gstate->CTM;
X	if (leftof (last_angle, angle))
X	 {
X	 	diff = angle - last_angle;
X		VOID MoveTo (new, ExtToInt (NewPoint (0.0, 0.0)));
X		gstate->CTM = Rotate (gstate->CTM, -diff);
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, -width / 2)));
X		gstate->CTM = old;
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, -width / 2)));
X	 }
X	else
X	 {
X	 	diff = last_angle - angle;
X		VOID MoveTo (new, ExtToInt (NewPoint (0.0, 0.0)));
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, width / 2)));
X		gstate->CTM = Rotate (gstate->CTM, diff);
X		VOID LineTo (new, ExtToInt (NewPoint (0.0, width / 2)));
X		gstate->CTM = old;
X	 }
X	ClosePath (new);
X }
X
BeginCap (new, width) Path new; float width;
X {
X	switch (gstate->line_cap)
X	 {
X	 	case CBUTT: break;
X	 	
X	 	case CSQUARE:
X	 		VOID MoveTo (new, ExtToInt (NewPoint (0.0, -width / 2)));
X	 		VOID LineTo (new, ExtToInt (NewPoint (0.0, width / 2)));
X	 		VOID LineTo (new, ExtToInt (NewPoint (-width / 2, width / 2)));
X	 		VOID LineTo (new, ExtToInt (NewPoint (-width / 2, -width / 2)));
X	 		ClosePath (new);
X	 		break;
X	 		
X	 	case CROUND:
X	 		VOID MoveTo (new, ExtToInt (NewPoint (0.0, width / 2)));
X	 		Arc (new, 1, NewPoint (0.0, 0.0), width / 2, PI / 2, 3 * PI / 2);
X	 		ClosePath (new);
X	 		break;
X	 		
X	 	default:
X	 		Panic ("BeginCap  - unknown line cap encountered");
X	 }
X }
X
LineJoin (new, width, last_angle, angle) Path new; float width, last_angle, angle;
X {
X 	float ang, sa;
X 	
X	switch (gstate->line_join)
X	 {
X	 	case JMITRE:
X	 		ang = Normalise (leftof (last_angle, angle) ? angle - last_angle : last_angle - angle);
X	 		ang = ang < 0 ? -ang : ang;
X	 		ang = ang > PI / 2 ? PI - ang : ang;
X	 		sa = sin (ang / 2);
X	 		if (sa != 0 && 1 / sa <= gstate->miter_limit && 1 / sa >= -gstate->miter_limit)
X	 			Miter (new, last_angle, angle, width);
X	 		else
X	 			Bevel (new, last_angle, angle, width);
X	 		
X	 		break;
X	 	
X	 	case JROUND:
X	 		VOID MoveTo (new, ExtToInt (NewPoint (width / 2, 0.0)));
X	 		Arc (new, 1, NewPoint (0.0, 0.0), width / 2, 0.0, 2 * PI);
X	 		ClosePath (new);
X	 		break;
X	 	
X	 	case JBEVEL: Bevel (new, last_angle, angle, width); break;
X	 	
X	 	default:
X	 		Panic ("LineJoin  - unknown line join encountered");
X	 }
X }
X
XEndCap (new, width, length) Path new; float width, length;
X {
X	switch (gstate->line_cap)
X	 {
X	 	case CBUTT: break;
X	 	
X	 	case CSQUARE:
X	 		VOID MoveTo (new, ExtToInt (NewPoint (length, -width / 2)));
X	 		VOID LineTo (new, ExtToInt (NewPoint (length + width / 2, -width / 2)));
X	 		VOID LineTo (new, ExtToInt (NewPoint (length + width / 2, width / 2)));
X	 		VOID LineTo (new, ExtToInt (NewPoint (length, width / 2)));
X	 		ClosePath (new);
X	 		break;
X	 		
X	 	case CROUND:
X	 		VOID MoveTo (new, ExtToInt (NewPoint (length, -width / 2)));
X	 		Arc (new, 1, NewPoint (length, 0.0), width / 2, -PI / 2, PI / 2);
X	 		ClosePath (new);
X	 		break;
X	 		
X	 	default:
X	 		Panic ("StrokeLineEnd  - unknown line cap encountered");
X	 }
X }
X
static float move_angle;
static Matrix move_matrix;
X
float LineSegment (p, new, ehere, enow, width, last_angle, last_type) Path p, new; Point ehere, enow; float width, last_angle; enum pelem_type last_type;
X {
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X/*
X 	float angle = atan2 (enow.y - ehere.y, enow.x - ehere.x),
X 		length = sqrt ((enow.y - ehere.y) * (enow.y - ehere.y) + (enow.x - ehere.x) * (enow.x - ehere.x));
X	Matrix old;
X*/
X	float angle, length = sqrt ((enow.y - ehere.y) * (enow.y - ehere.y) + (enow.x - ehere.x) * (enow.x - ehere.x));
X	Matrix old;
X
X	if ((enow.y - ehere.y) == 0 && (enow.x - ehere.x) ==  0)
X		angle = 0;
X	else
X		angle = atan2 (enow.y - ehere.y, enow.x - ehere.x);
X/* Changed by Henk Tullemans, Philips Research Laboratories, Eindhoven */
X
X	old = gstate->CTM;
X	
X	gstate->CTM = Rotate (Translate (gstate->CTM, ehere.x, ehere.y), angle);
X	VOID MoveTo (new, ExtToInt (NewPoint (0.0, -width / 2)));
X	VOID LineTo (new, ExtToInt (NewPoint (length, -width / 2)));
X	VOID LineTo (new, ExtToInt (NewPoint (length, width / 2)));
X	VOID LineTo (new, ExtToInt (NewPoint (0.0, width / 2)));
X	ClosePath (new);
X	
X	if (last_type == EMove)
X	 {
X	 	move_angle = angle;
X		move_matrix = gstate->CTM;
X	 }
X	else if (last_type == ELine)
X		LineJoin (new, width, last_angle, angle);
X	
X	if (p->ptype == EClose)
X	 {
X		if (last_type == ELine)
X		 {
X		 	gstate->CTM = move_matrix;
X			LineJoin (new, width, angle, move_angle);
X		 }
X	 }
X	else if (p->next->ptype == EMove || p->next->ptype == EHeader)
X	 {
X		EndCap (new, width, length);
X	 	gstate->CTM = move_matrix;
X	 	BeginCap (new, width);
X	 }
X	
X	gstate->CTM = old;
X	return angle;
X }
X
int PStrokePath ()
X {
X 	Path p, new = NewPath ();
X 	HardPoint prev, here, move;
X 	enum pelem_type last_type = EHeader;
X 	float angle, last_angle, width = gstate->line_width;
X 	
X 	PFlattenPath ();
X 	if (gstate->dash_length != 0)
X 		Dash ();
X 	for (p = gstate->path->next; p != gstate->path; last_type = p->ptype, p = p->next)
X 	 {
X	 	switch (p->ptype)
X	 	 {
X	 	  	case EMove:
X			 	prev = here;
X			 	move = here = p->pe.point;
X			 	break;
X			 	
X	 	  	case EClose:
X	 	  		if (last_type == EMove)
X	 	  			break;
X				angle = LineSegment (p, new, IntToExt (here), IntToExt (move), width, last_angle, last_type);
X			 	prev = here;
X			 	here = move;
X			 	last_type = EHeader;
X			 	break;
X			 	
X	 	  	case ELine:
X				angle = LineSegment (p, new, IntToExt (here), IntToExt (p->pe.point), width, last_angle, last_type);
X			 	prev = here;
X			 	here = p->pe.point;
X	 	  		break;
X	 	  		
X	 	  	default:
X	 	  		Panic ("unknown path element type in StrokePath");
X	 	 }
X	 	last_type = p->ptype;
X	 	last_angle = angle;
X	 }
X 	PathFree (gstate->path);
X 	gstate->path = new;
X 	return TRUE;
X }
X
int ThinStroke ()
X {
X 	Path p;
X 	Vector v;
X 	HardPoint here, prev;
X 	
X 	if (stroke_method != STROKE_THIN)
X 		return FALSE; /* not used - get better results with area fill */
X 	v = Transform (NewVector (gstate->line_width, gstate->line_width, 0.0), gstate->CTM);
X 	if (fabs (v.vx) > 1.1 || fabs (v.vy) > 1.1)
X 		return FALSE;
X 	if (gstate->dash_length != 0)
X 		Dash ();
X 	for (p = gstate->path->next; p != gstate->path; p = p->next)
X 	 switch (p->ptype)
X 	  {
X 	  	case EMove:
X 	  		here = prev = p->pe.point;
X 	  		break;
X 	  	
X 	  	case ELine:
X 	  		DevicePaintLine (gstate->device, prev, p->pe.point, gstate->colour);
X 	  		prev = p->pe.point;
X 	  		break;
X 	  	
X 	  	case EClose:
X 	  		DevicePaintLine (gstate->device, prev, here, gstate->colour);
X  	  		prev = here;
X	  		break;
X 	  		
X	 	default:
X	 	  	Panic ("unknown path element type in ThinStroke");
X 	  }
X	VOID PNewPath ();
X	
X	return TRUE;
X }
END_OF_FILE
if test 12101 -ne `wc -c <'stroke.c'`; then
    echo shar: \"'stroke.c'\" unpacked with wrong size!
fi
# end of 'stroke.c'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(1899 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
OBJECTS=array.o boolean.o config.o control.o dictionary.o file.o\
X	integer.o main.o math.o misc.o name.o operator.o\
X	poly.o property.o real.o save.o stack.o string.o unix.o
X#LIBS=libww.a -lsuntool -lsunwindow -lpixrect -g
GRAPHICS=cache.o colour.o device.o fill.o font.o gsave.o image.o mat.o matrix.o\
X	pat.o path.o state.o stroke.o
CFLAGS=-O -g
X
PS:	$(OBJECTS) $(GRAPHICS) hard.o canon.a
X#	cc $(CFLAGS)  $(OBJECTS) $(GRAPHICS) hard.o canon.a -lm $(LIBS) -o PS
X	cc $(CFLAGS)  $(OBJECTS) $(GRAPHICS) hard.o canon.a -lm -o PS
X
sunPS:	$(OBJECTS) $(GRAPHICS) hard.o canon.a pixrect
X	cc $(CFLAGS)  $(OBJECTS) $(GRAPHICS) hard.o canon.a -lm -lpixrect -o sunPS
X
CPS:	$(OBJECTS) $(GRAPHICS) colour-ww.o trapezoid.o canon.o
X#	cc $(CFLAGS)  $(OBJECTS) $(GRAPHICS) colour-ww.o canon.o trapezoid.o -lm $(LIBS) -o CPS
X	cc $(CFLAGS)  $(OBJECTS) $(GRAPHICS) colour-ww.o canon.o trapezoid.o -lm -o CPS
X
postscript:	$(OBJECTS) $(GRAPHICS) adapter.o protocol.o
X	cc $(CFLAGS) $(OBJECTS) $(GRAPHICS) adapter.o protocol.o -lm -o postscript
X
XXPS:	$(OBJECTS) $(GRAPHICS) X.o
X	cc $(CFLAGS)  $(OBJECTS) $(GRAPHICS) X.o -lm -lX -o XPS
X
canon.a:	canon.o screen.o trapezoid.o paint.o
X	ar ruv canon.a canon.o screen.o trapezoid.o paint.o
X	ranlib canon.a
X
viewer:	protocol.o viewer.o hard.o canon.a
X#	cc protocol.o viewer.o hard.o canon.a $(LIBS) -o viewer
X	cc protocol.o viewer.o hard.o canon.a -o viewer
X
all:	PS postscript viewer
X
ww:	ww.o wwlib installww
X
pixrect:	pixrect.o
X	cp pixrect.o hard.o
X
sun:	ww wwsun
X
orion:	orion.o installorion orionlib
X
XX.o:	
X	cc -c X.c
X
wwlib:
X	if [ -f libww.a ]; \
X	then \
X		echo 'echo libww.a' >lww; \
X	else \
X		echo 'echo -lww' >lww; \
X	fi; \
X	chmod +x lww
X	echo "echo `lww`" >libs; chmod +x libs
X
wwsun:	
X	echo "echo `lww` -lsuntool -lsunwindow -lpixrect" >libs; chmod +x libs
X
orionlib:
X	echo 'echo -lG' >libs; chmod +x libs
X
installww:
X	cp ww.o hard.o
X
installorion:
X	cp orion.o hard.o
END_OF_FILE
if test 1899 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
echo shar: End of shell archive.
exit 0