/*
************************************************************************
History
************************************************************************
*/
/*
26 March 1996
Add color routines for color postscript
*/
/*
************************************************************************
Include files
************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include "grdevsub.h"
/*
************************************************************************
Type definitions
************************************************************************
*/
typedef struct
{
float x,y;
}
polytype;
/*
************************************************************************
Defines
************************************************************************
*/
/* DEFINES */
#define MAXPOLY 12
#define CANONYOFF 10.625
#define CANONXOFF 0.00
#define CANONSC 300
#define NTEMPSTR 4
#define BOOLEAN int
#define TRUE 1
#define FALSE 0
/*
************************************************************************
Module-Wide Variables
************************************************************************
*/
float curx, cury, textsize;
int fillflag, settextflag;
FILE *__f;
polytype temppoly[MAXPOLY];
char __tempstr[NTEMPSTR][256];
int __itempstr = 0;
int PSflag = 0;
/*
************************************************************************
Local Functions
************************************************************************
*/
/* CONVERT float TO ROUNDED integer */
int round (float x) {
int i = x + 0.5;
return(i);
}
/* CONVERT float TO SHORT FORMATED STRING (TRUNCATED TRAILING 0 AND .) */
char *fmt (float x, int n) {
char *t, *u;
t = &__tempstr[__itempstr++][1]; /* ROTATE BETWEEN STRING BUFFERS */
__itempstr %= NTEMPSTR;
sprintf (t, "%12.*f", n, 72*x);
/* Remove Leading Blanks */
while (*t==' ' && *t!=0)
t++;
/* if DECIMAL POINT REMOVE TRAILING ZEROS */
if (n>0) {
/* Point to end of string */
u = t + strlen(t) - 1;
while (*u=='0' && u!=t)
u--;
*(u+1) = 0;
/* Remove trailing decimal point */
if (*u=='.')
*u = 0;
}
/* REMOVE JUST TRAILING DECIMAL */
else if (n==0) {
/* Point to end of string */
u = t + strlen(t) - 1;
/* Remove trailing decimal point */
if (*u=='.')
*u = 0;
}
/* Pad with one leading blank */
*(--t) = ' ';
return(t);
}
/* CONVERT INTEGER TO SPECIAL CANON PRINTER FORMAT */
void sendvals (int NumToPrinter)
{
static char TempStr[4];
unsigned char Sign;
unsigned int OutByte, LoByte, HiByte;
int n = 0;
if (NumToPrinter>=0)
Sign = 1;
else
{
Sign = 0;
NumToPrinter = -NumToPrinter;
}
LoByte = NumToPrinter & 0x00FF;
HiByte = (NumToPrinter & 0xFF00) >> 8;
/* FIRST BYTE */
OutByte = HiByte >> 2;
if (OutByte>0)
TempStr[n++] = OutByte + 64;
/* Second Byte */
OutByte = ((HiByte & 0x0003) << 4)
+ ((LoByte & 0x00f0) >> 4);
if (OutByte>0 || n)
TempStr[n++] = OutByte + 64; /* Set Second Bit*/
/* Third Byte */
OutByte = LoByte & 0x000f;
if (Sign)
TempStr[n++] = OutByte + 48;
else
TempStr[n++] = OutByte + 32;
TempStr[n] = 0;
fprintf (__f, "%s", TempStr);
}
/* CANON DEVICE DEPENDENT ROUTINES */
void Canon_InitFile (void)
{
fprintf (__f, "%s%s", "\033","<"); /* SOFT RESET */
fprintf (__f, "%s%s", "\033",";"); /* ISO */
fprintf (__f, "%s%s", "\033","[2&z"); /* FULL PAINT */
fprintf (__f, "%s%s", "\033",";"); /* ISO */
fprintf (__f, "%s%s", "\033","[&}"); /* VDM */
fprintf (__f, "%s%s", "#","\036"); /* BEGIN PICTURE */
fprintf (__f, "%s", "!0"); /* SET SCALE (units 0.01 inch, scale 1 inch) */
sendvals ( -3);
sendvals ( 3);
fprintf (__f, "%s", "\036");
fprintf (__f, "%s%s","$","\036"); /* BEGIN BODY */
fprintf (__f, "%s%s","E10","\036"); /* LINE TYPE */
fprintf (__f, "%s","F1"); /* LINE WIDTH (3 dots) */
sendvals ( -2);
fprintf (__f, "%s", "\036");
fprintf (__f, "%s%s","}G0","\036"); /* LINE STYLE */
}
void Canon_DrawTo (float x, float y)
{
/* DEVICE SPECIFIC DRAWING COMMANDS */
fprintf (__f, "%s", "1");
sendvals (round( CANONSC*(CANONXOFF+curx)));
sendvals (round( CANONSC*(CANONYOFF-cury)));
sendvals (round( CANONSC*(x-curx)));
sendvals (round(-CANONSC*(y-cury)));
fprintf (__f, "%s", "\036");
/* RESET CURRENT POSITION */
curx = x;
cury = y;
}
void Canon_DrawRel (float dx, float dy)
{
/* DEVICE SPECIFIC DRAWING COMMANDS */
fprintf (__f, "%s", "1");
sendvals (round(CANONSC*(CANONXOFF+curx)));
sendvals (round(CANONSC*(CANONYOFF-cury)));
sendvals (round( CANONSC*dx));
sendvals (round(-CANONSC*dy));
fprintf (__f, "%s", "\036");
/* RESET CURRENT POSITION */
curx = curx + dx;
cury = cury + dy;
}
void Canon_Drawpoly (int npoly, polytype *poly)
{
int i;
/* SET FILL STATE */
fprintf (__f, "%s", "I");
if (fillflag)
sendvals ( 1);
else
sendvals ( 0);
fprintf (__f, "%s", "\036");
/* DRAW POLYGON */
fprintf (__f, "%s", "*/2");
sendvals (round(CANONSC*(CANONXOFF+curx+poly[0].x)));
sendvals (round(CANONSC*(CANONYOFF-cury-poly[0].y)));
for (i=1;i<npoly;i++)
{
sendvals (round( CANONSC*poly[i].x));
sendvals (round(-CANONSC*poly[i].y));
}
fprintf (__f, "%s", "\036");
}
void Canon_WriteText (char *instr)
{
fprintf (__f, "%s%s", "}p", "\036"); /* EXIT VDM MODE */
fprintf (__f, "%s%s", "\033","[11h"); /* SIZE UNIT MODE */
fprintf (__f, "%s%s%s%s%s",
"\033[7 I", /* SELECT SIZE UNIT (1/300") */
"\033[?8l", /* ENABLE PROPORTIONAL SPACING */
"\033[?32h ", /* ENABLE SCALABLE FONT SEL. */
"\033PzSwiss.ISO_USA", /* SELECT FONT */
"\033\\");
fprintf (__f, "%s%s%i%s", "\033", "[",round(300*textsize), " C"); /* CHARCTER SIZE */
fprintf (__f, "%s%s%i%s", "\033", "[",round(300*curx),"`"); /* HOR POS */
fprintf (__f, "%s%s%i%s", "\033", /* VER POS */
"[",round(300*(CANONYOFF-cury-2*textsize)),"d");
fprintf (__f, "%s", instr);
/* RETURN TO VDM MODE */
fprintf (__f, "%s%s", "\033","[0&}"); /* VDM */
fprintf (__f, "%s%s", "#","\036"); /* BEGIN PICTURE */
fprintf (__f, "%s", "!0"); /* SET SCALE (units 0.01 inch, scale 1 inch) */
sendvals ( -3);
sendvals ( 3);
fprintf (__f, "%s", "\036");
fprintf (__f, "%s%s","$","\036"); /* BEGIN BODY */
}
void Canon_Circle (float radius)
{
/* SET FILL STATE */
fprintf (__f, "%s", "I");
if (fillflag)
sendvals ( 1);
else
sendvals ( 0);
fprintf (__f, "%s", "\036");
/* WRITE CIRCLE */
fprintf (__f, "%s", "5");
sendvals ( round(CANONSC*(CANONXOFF+curx)));
sendvals ( round(CANONSC*(CANONYOFF-cury)));
sendvals ( round(CANONSC*radius));
fprintf (__f, "%s", "\036");
}
void Canon_WritePage (void)
{
/* DEVICE SPECIFIC COMMANDS */
fprintf (__f, "%s", "\014");
}
/* PostScript DEVICE DEPENDENT ROUTINES */
void PS_InitFile (void)
{
char **HeaderPtr;
char *HeaderComments[] =
{
"%!PS-Adobe-3.0",
"%%Creator: XMD",
"%%EndComments",
NULL
};
/* Write header comments */
HeaderPtr = HeaderComments;
while (*HeaderPtr!=NULL)
{
fprintf (__f, "%s\n", *HeaderComments);
HeaderPtr++;
}
/* SET LINE WIDTH AND CAPS */
fprintf (__f, "%s\n", "0.48 setlinewidth 1 setlinecap ");
/* SET FILL LEVEL */
fprintf (__f, "%s\n", "0 setgray");
/* STORE SETTINGS */
fprintf (__f, "%s\n", "gsave ");
}
void PS_DrawTo (float x, float y)
{
/* DEVICE SPECIFIC DRAWING COMMANDS */
fprintf (__f, "%s%s%s ", fmt(curx,3), fmt(cury,3), " moveto" );
fprintf (__f, "%s%s%s\n", fmt(x, 3), fmt(y, 3), " lineto stroke");
/* RESET CURRENT POSITION */
curx = x;
cury = y;
}
void PS_DrawRel (float dx, float dy)
{
/* DEVICE SPECIFIC DRAWING COMMANDS */
fprintf (__f, "%s%s%s", fmt(curx,3), fmt(cury,3), " moveto" );
fprintf (__f, "%s%s%s\n", fmt(dx, 3), fmt(dy, 3), " rlineto stroke");
/* RESET CURRENT POSITION */
curx = curx + dx;
cury = cury + dy;
}
void PS_Drawpoly (int npoly, polytype *poly)
{
int i;
fprintf (__f, "%s%s%s\n", fmt(curx,3), fmt(cury,3), " moveto");
if (npoly>=1)
fprintf (__f, "%s%s%s\n", fmt(poly[0].x,3), fmt(poly[0].y,3), " rmoveto");
if (npoly> 1)
for (i=1;i<npoly;i++)
fprintf (__f, "%s%s%s\n", fmt(poly[i].x,3), fmt(poly[i].y,3), " rlineto");
if (npoly>=1)
if (fillflag)
fprintf (__f, "%s\n", "closepath fill");
else
fprintf (__f, "%s\n", "closepath stroke");
}
void PS_WriteText (char *instr)
{
/* DEVICE SPECIFIC TEXT COMMANDS */
if (settextflag)
{
fprintf (__f, "%s%s%s\n", "/Courier findfont", fmt(textsize,0),
" scalefont setfont ");
settextflag = 0;
}
fprintf (__f, "%s%s%s\n", fmt(curx,2), fmt(cury,2), " moveto");
fprintf (__f, "%s%s%s\n", "(", instr, ") show newpath" );
}
void PS_Circle (float radius)
{
/* DEVICE SPECIFIC CIRCLE COMMANDS */
fprintf (__f, "%s%s%s%s", fmt(curx,3), fmt(cury,3), fmt(radius,3), " 0 360 arc ");
if (fillflag)
fprintf (__f, "%s\n", "fill");
else
fprintf (__f, "%s\n", "stroke");
}
void PS_WritePage (void)
{
/* DEVICE SPECIFIC COMMANDS */
fprintf (__f, "%s\n", "newpath showpage grestore");
}
/* Set color according to Cyan-Magenta-Yellow-Black model */
void PS_setcmybcolor (float Cyan, float Magenta, float Yellow, float Black)
{
fprintf (__f, "%5.3f %5.3f %5.3f %5.3f setcmybcolor\n",
Cyan, Magenta, Yellow, Black);
}
/* Set color according to Hue-Saturation-Brightness model */
void PS_sethsbcolor (float Hue, float Saturation, float Brightness)
{
fprintf (__f, "%5.3f %5.3f %5.3f sethsbcolor\n", Hue, Saturation, Brightness);
}
/* Set color according to Red-Green-Blue model */
void PS_setrgbcolor (float Red, float Green, float Blue)
{
fprintf (__f, "%5.3f %5.3f %5.3f setrgbcolor\n", Red, Green, Blue);
}
/*
************************************************************************
Exported Functions
************************************************************************
*/
/* "ROUTING" ROUTINES */
void grdev_initfile (void)
{
if (PSflag)
PS_InitFile();
else
Canon_InitFile();
}
void grdev_drawto (float x, float y)
{
if (PSflag)
PS_DrawTo (x, y);
else
Canon_DrawTo (x,y);
}
void grdev_drawrel (float dx, float dy)
{
if (PSflag)
PS_DrawRel (dx,dy);
else
Canon_DrawRel (dx,dy);
}
void grdev_drawpoly (int npoly, polytype *poly)
{
if (PSflag)
PS_Drawpoly (npoly, poly);
else
Canon_Drawpoly (npoly, poly);
}
void grdev_writetext (char *instr)
{
int i, flag;
/* REMOVE TRAILING \n */
i = strlen(instr);
while (i && instr[i]!='\n')
i--;
flag = (instr[i]=='\n');
if (flag)
instr[i] = 0;
/* PRINT STRING */
if (PSflag)
PS_WriteText (instr);
else
Canon_WriteText (instr);
/* RESTORE \n */
if (flag)
instr[i] = '\n';
}
void grdev_circle (float radius)
{
if (PSflag)
PS_Circle (radius);
else
Canon_Circle (radius);
}
void grdev_writepage (void)
{
if (PSflag)
PS_WritePage ();
else
Canon_WritePage();
}
void grdev_setrgbcolor (BYTE Red, BYTE Green, BYTE Blue, BOOLEAN ForceChange)
{
static int LastRed = 0;
static int LastGreen = 0;
static int LastBlue = 0;
static float Factor = 1.0 / 255.0;
/* Return if device doesnot support color */
if (!PSflag)
return;
/* Color doesn't change - ignore */
if
(
!ForceChange &&
LastRed == Red &&
LastGreen == Green &&
LastBlue == Blue
)
return;
/* Set new color */
PS_setrgbcolor (Factor*Red, Factor*Green, Factor*Blue);
/* Record color */
LastRed = Red;
LastGreen = Green;
LastBlue = Blue;
}
void grdev_sethsbcolor (BYTE Hue, BYTE Saturation, BYTE Brightness, BOOLEAN ForceChange)
{
static int LastHue = 0;
static int LastSaturation = 0;
static int LastBrightness = 1;
static float Factor = 1.0 / 255.0;
/* Return if device doesnot support color */
if (!PSflag)
return;
/* Color doesn't change - ignore */
if
(
!ForceChange &&
LastHue == Hue &&
LastSaturation == Saturation &&
LastBrightness == Brightness
)
return;
/* Set new color */
PS_sethsbcolor (Factor*Hue, Factor*Saturation, Factor*Brightness);
/* Record color */
LastHue = Hue;
LastSaturation = Saturation;
LastBrightness = Brightness;
}
void grdev_setcmybcolor (BYTE Cyan, BYTE Magenta, BYTE Yellow, BYTE Black, BOOLEAN ForceChange)
{
static int LastCyan = 0;
static int LastMagenta = 0;
static int LastYellow = 0;
static int LastBlack = 1;
static float Factor = 1.0 / 255.0;
/* Return if device doesnot support color */
if (!PSflag)
return;
/* Color doesn't change - ignore */
if
(
!ForceChange &&
LastCyan == Cyan &&
LastMagenta == Magenta &&
LastYellow == Yellow &&
LastBlack == Black
)
return;
/* Set new color */
PS_setcmybcolor (Factor*Cyan, Factor*Magenta, Factor*Yellow, Factor*Black);
/* Record color */
LastCyan = Cyan;
LastMagenta = Magenta;
LastYellow = Yellow;
LastBlack = Black;
}
void grdev_setcolor(ColorModel_t ColorModel, ColorTable_t ColorTable)
{
static ColorModel_t LastColorModel = COLOR_RGB;
static ColorTable_t LastColorTable = {0, 0, 0, 0};
BOOLEAN ColorModelChange;
int icolor;
/* If color hasn't changed from last time, ignore this call */
if (LastColorModel == ColorModel)
{
/* Test RGB color model */
if
(
(LastColorModel==COLOR_RGB || LastColorModel==COLOR_HSB) &&
LastColorTable[0]==ColorTable[0] &&
LastColorTable[1]==ColorTable[1] &&
LastColorTable[2]==ColorTable[2]
)
return;
/* Test CMYB color model */
if
(
LastColorModel==COLOR_CMYB &&
LastColorTable[0]==ColorTable[0] &&
LastColorTable[1]==ColorTable[1] &&
LastColorTable[2]==ColorTable[2] &&
LastColorTable[3]==ColorTable[3]
)
return;
}
/* Call correct color model routine */
ColorModelChange = (LastColorModel!=ColorModel);
if (ColorModel==COLOR_RGB)
grdev_setrgbcolor
(ColorTable[0], ColorTable[1], ColorTable[2], ColorModelChange);
else if (ColorModel==COLOR_HSB)
grdev_sethsbcolor
(ColorTable[0], ColorTable[1], ColorTable[2], ColorModelChange);
else if (ColorModel==COLOR_CMYB)
grdev_setcmybcolor
(ColorTable[0], ColorTable[1], ColorTable[2], ColorTable[3], ColorModelChange);
/* Store current color setting */
LastColorModel = ColorModel;
for (icolor=0; icolor<NCMYB; ++icolor)
LastColorTable[icolor] = ColorTable[icolor];
}
/* DEVICE INDEPENDENT ROUTINES */
void grdev_init (void)
{
/* DEVICE SPECIFIC COMMANDS */
/* INITALIZE VARIABLES */
fillflag = 0;
curx = 0;
cury = 0;
textsize = 1.0/6.0;
settextflag = 1;
}
void grdev_assignfile (FILE *fin)
{
__f = fin;
}
void grdev_canon (void)
{
PSflag = 0;
}
void grdev_ps (void)
{
PSflag = 1;
}
void grdev_moveto (float x, float y)
{
curx = x;
cury = y;
}
void grdev_moverel(float dx, float dy)
{
curx = curx + dx;
cury = cury + dy;
}
void grdev_setfill (int flag)
{
fillflag = flag;
}
void grdev_settextsize (float size)
{
textsize = size;
settextflag = 1;
}
float grdev_gettextsize (void)
{
return(textsize);
}
void grdev_triangle (float radius)
{
temppoly[0].x = 0.0;
temppoly[0].y = radius;
temppoly[1].x = 0.5*sqrt(3)*radius;
temppoly[1].y = -1.5 *radius;
temppoly[2].x = -sqrt(3)*radius;
temppoly[2].y = 0.0;
grdev_drawpoly (3, temppoly);
}
void grdev_itriangle (float radius )
{
temppoly[0].x = 0.0;
temppoly[0].y = -radius;
temppoly[1].x = 0.5*sqrt(3)*radius;
temppoly[1].y = 1.5 *radius;
temppoly[2].x = -sqrt(3)*radius;
temppoly[2].y = 0.0;
grdev_drawpoly (3, temppoly);
grdev_drawpoly (3, temppoly);
}
void grdev_diamond (float radius )
{
temppoly[0].x = 0.0;
temppoly[0].y = radius;
temppoly[1].x = radius;
temppoly[1].y = -radius;
temppoly[2].x = -radius;
temppoly[2].y = -radius;
temppoly[3].x = -radius;
temppoly[3].y = radius;
grdev_drawpoly (4, temppoly);
}
void grdev_cross (float radius)
{
grdev_moverel ( 0, -radius);
grdev_drawrel ( 0, 2*radius);
grdev_moverel ( -radius, -radius);
grdev_drawrel (2*radius, 0 );
grdev_moverel ( -radius, 0 );
}
void grdev_square (float radius )
{
radius = radius / sqrt(2);
temppoly[0].x = radius;
temppoly[0].y = radius;
temppoly[1].x = 0;
temppoly[1].y = -2*radius;
temppoly[2].x = -2*radius;
temppoly[2].y = 0;
temppoly[3].x = 0;
temppoly[3].y = 2*radius;
grdev_drawpoly (4, temppoly);
}
void grdev_asterisk (float radius )
{
float dx,dy, xcen,ycen;
xcen = curx;
ycen = cury;
dx = 0.5*sqrt(3)*radius;
dy = 0.5 *radius;
/* DRAW VERTICAL ARM */
grdev_moverel (0, radius);
grdev_drawrel (0, -2*radius);
grdev_moveto (xcen, ycen);
/* DRAW LEFT ARM */
grdev_moverel (dx, dy);
grdev_drawrel (-2*dx, -2*dy);
grdev_moveto (xcen, ycen);
/* DRAW RIGHT ARM */
grdev_moverel (-dx, dy);
grdev_drawrel (2*dx, -2*dy);
grdev_moveto (xcen, ycen);
}
void grdev_printf (char *format, ...)
{
char cbuffer[1024];
va_list argptr;
/* CONVERT ARGUMENTS TO STRING */
va_start (argptr, format);
vsprintf (cbuffer, format, argptr);
va_end (argptr);
/* CALL WRITE TEXT */
grdev_writetext (cbuffer);
}