#ident "@(#)VOGLE:driver/hpgl2.c - VOGLE driver for HPGL2/2"
#ident "@(#)VOGLE:author - John S. Urban"
#ident "@(#)VOGLE:version - 1.0,"
#include
#include
#include "vogle.h"
#define MIN(x,y) ((x) < (y) ? (x) : (y))
extern FILE *_voutfile();
static int drawn = 0;
static int plotlstx, plotlsty; /* position of last draw */
extern FILE *fp;
#define CMAPSIZE 256
#define P_RESET 0
#define P_MOVE 1
#define P_DRAW 2
#define P_TXTSIZE 3
#define P_BEGTXT 4
#define P_ENDTXT 5
#define P_PEN 6
#define P_WIDE 7
#define P_CLEAR 8
#define P_EXIT 9
#define P_FILL 10
#define P_ENDFILL 11
#define P_BREAKFILL 12
static char P_REESTABLISH[80];
/* basic commands for HPGL2 */
static char *HPGL2[] = {
"DF;\n",
"PU%d,%d;\n",
"PD%d,%d;\n",
"SI%.4f,%.4f;\n",
"LB",
"\003\n",
"SP%d;\n",
"PW%.4f;\n",
"PG;\n",
"\033.)\n",
"PM0",
"PM2;FP0;EP", /* exit polygon mode fill polygon using odd-even algorithm; fill polygon; edge-fill polygon */
"PM1"
};
/* basic commands for pcl5 */
static char *pcl5[] = {
"DF;\n",
"PU%d,%d;\n",
"PD%d,%d;\n",
"SI%.4f,%.4f;\n",
"LB",
"\003\n",
"SP%d;\n",
"PW%.4f;\n",
"\033%%1A\033E\n\033&l2A\033&l1O\033%%1B\n",
"\033%%1A\033E\n",
"PM0\n",
"PM2;FP0;EP\n", /* exit polygon mode fill polygon using odd-even algorithm; fill polygon; edge-fill polygon */
"PM1\n"
};
static char **plotcmds;
static char CLEAR_DEVICE[100];
/******************************************************************************/
/*
CORRECT THESE NOTES:
prefxs and prefys are preferred plotting area size in rasters
prefy is the BOTTOM margin on this - make big note in manual
NON-INTUITIVE for LANDSCAPE: prefx is the LEFT margin
A4 : 10200 x 7320
A3 : 14720 x 10560
A2 : 18734 x 13440
A1 : 29774 x 21360
17 x 11 : 15370 x 10259
8.5 x 11: 7650 x 9540
11 x 8.5: 9540 x 7650
*/
/******************************************************************************/
static int
HPGL2_PORT_init()
{
/* 8.5 x 11 portrait paper Letter size - JSU */
int prefx, prefy, prefxs, prefys;
vogle_getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
if (prefxs != -1 ) {
vdevice.sizeSy = prefys;
vdevice.sizeSx = prefxs;
vdevice.sizeX = vdevice.sizeY = MIN(prefys, prefxs );
}else{
prefx = 0;
prefy = 0;
vdevice.sizeSx = 7650;
vdevice.sizeSy = 9540;
vdevice.sizeX = vdevice.sizeY = 7650;
}
return(HPGL2_common_initp(prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy));
}
/******************************************************************************/
static int
PCL5_PORT_init()
{
/* 8.5 x 11 portrait paper Letter size - JSU */
int prefx, prefy, prefxs, prefys;
vogle_getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
if (prefxs != -1 ) {
vdevice.sizeSy = prefys;
vdevice.sizeSx = prefxs;
vdevice.sizeX = vdevice.sizeY = MIN(prefys, prefxs );
}else{
prefx = 0;
prefy = 0;
vdevice.sizeSx = 7650;
vdevice.sizeSy = 9540;
vdevice.sizeX = vdevice.sizeY = 7650;
}
return(PCL5_common_initp(prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy));
}
/******************************************************************************/
static int
HPGL2_LAND_init()
{
/* 8.5 x 11 landscape paper Letter size - JSU */
int prefx, prefy, prefxs, prefys;
vogle_getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
if (prefxs != -1 ) {
vdevice.sizeSy = prefys;
vdevice.sizeSx = prefxs;
vdevice.sizeX = vdevice.sizeY = MIN(prefys, prefxs );
}else{
prefx = 0;
prefy = 0;
vdevice.sizeSy = 7650;
vdevice.sizeSx = 9540;
vdevice.sizeX = vdevice.sizeY = 7650;
}
return(HPGL2_common_init(prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy));
}
/******************************************************************************/
static int
PCL5_LAND_init()
{
/* 8.5 x 11 landscape paper Letter size - JSU */
int prefx, prefy, prefxs, prefys;
vogle_getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
if (prefxs != -1 ) {
vdevice.sizeSy = prefys;
vdevice.sizeSx = prefxs;
vdevice.sizeX = vdevice.sizeY = MIN(prefys, prefxs );
}else{
prefx = 0;
prefy = 0;
vdevice.sizeSy = 7650;
vdevice.sizeSx = 9540;
vdevice.sizeX = vdevice.sizeY = 7650;
}
return(PCL5_common_init(prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy));
}
/******************************************************************************/
/* Performs the common parts of HPGL2 initialization. */
static int
HPGL2_common_init(minx, maxx, miny, maxy)
int minx, maxx, miny, maxy;
{
vdevice.depth = 3;
fp = _voutfile();
/* * The next line is for serial lines if you need to set modes */
fprintf(fp, "\033.(;\033.I81;;17;\033.N;19:IN;");
/* * Cause scaling to be 0 to maxX maxY. */
fprintf(fp, "IP%d,%d,%d,%d;", minx, miny, maxx, maxy);
fprintf(fp, "SC0,%d,0,%d;", vdevice.sizeSx, vdevice.sizeSy);
fprintf(fp,"TR0;\n"); /* transparency mode off, white areas are opaque */
fprintf(fp,"NP256;\n"); /* Establish the number of pens in the HPGL/2 palette*/
fprintf(fp,"CR0,255,0,255,0,255;\n"); /* set color range for relative color data in the HPGL/2 palette*/
plotcmds = HPGL2;
strncpy(CLEAR_DEVICE,plotcmds[P_CLEAR],100); /* this has parameters sometimes so it is treated differently */
plotlstx = -1111111;
plotlsty = -1111111;
drawn = 0;
return(1);
}
/******************************************************************************/
/* Performs the common parts of PCL5 initialization. */
static int
PCL5_common_init(minx, maxx, miny, maxy)
int minx, maxx, miny, maxy;
{
vdevice.depth = 3;
fp = _voutfile();
/* (exit PCL5 mode) Enter HPGL2 mode, cause scaling to be 0 to maxX maxY */
sprintf(CLEAR_DEVICE, "\033%%%%1A\033E\n\033&l2A\033&l1O\033%%%%1B\nIP%d,%d,%d,%d;SC0,%d,0,%d;",
minx, miny, maxx, maxy, vdevice.sizeSx, vdevice.sizeSy);
fprintf(fp,CLEAR_DEVICE);
fprintf(fp,"TR0;\n"); /* transparency mode off, white areas are opaque */
fprintf(fp,"NP256;\n"); /* Establish the number of pens in the HPGL/2 palette*/
fprintf(fp,"CR0,255,0,255,0,255;\n"); /* set color range for relative color data in the HPGL/2 palette*/
plotcmds = pcl5;
plotlstx = -1111111;
plotlsty = -1111111;
drawn = 0;
return(1);
}
/******************************************************************************/
/* Performs the common parts of HPGL2 initialization in portrait mode */
static int HPGL2_common_initp(minx, maxx, miny, maxy)
int minx, maxx, miny, maxy;
{
vdevice.depth = 3;
fp = _voutfile();
/* * The next line is for serial lines if you need to set modes */
fprintf(fp, "\033.(;\033.I81;;17;\033.N;19:IN;");
/* * Cause scaling to be 0 to maxX maxY. */
fprintf(fp, "IP%d,%d,%d,%d;", minx, miny, maxx, maxy);
fprintf(fp, "SC0,%d,0,%d;", vdevice.sizeSx, vdevice.sizeSy);
fprintf(fp, "RO90;"); /* rotate 90 degrees */
fprintf(fp,"TR0;\n"); /* transparency mode off, white areas are opaque */
fprintf(fp,"NP256;\n"); /* Establish the number of pens in the HPGL/2 palette*/
fprintf(fp,"CR0,255,0,255,0,255;\n"); /* set color range for relative color data in the HPGL/2 palette*/
plotcmds = HPGL2;
strncpy(CLEAR_DEVICE,plotcmds[P_CLEAR],100); /* this has parameters sometimes so it is treated differently */
plotlstx = -1111111;
plotlsty = -1111111;
drawn = 0;
return(1);
}
/******************************************************************************/
/* Performs the common parts of PCL5 initialization in portrait mode */
static int PCL5_common_initp(minx, maxx, miny, maxy)
int minx, maxx, miny, maxy;
{
vdevice.depth = 3;
fp = _voutfile();
/* (exit PCL5 mode) Enter HPGL2 mode, cause scaling to be 0 to maxX maxY , rotate 90 degrees */
sprintf(CLEAR_DEVICE, "\033%%%%1A\033E\n\033&l2A\033&l1O\033%%%%1B\nIP%d,%d,%d,%d;SC0,%d,0,%d;RO90;",
minx, miny, maxx, maxy, vdevice.sizeSx, vdevice.sizeSy);
fprintf(fp,CLEAR_DEVICE);
fprintf(fp,"TR0;\n"); /* transparency mode off, white areas are opaque */
fprintf(fp,"NP256;\n"); /* Establish the number of pens in the HPGL/2 palette*/
fprintf(fp,"CR0,255,0,255,0,255;\n"); /* set color range for relative color data in the HPGL/2 palette*/
plotcmds = pcl5;
plotlstx = -1111111;
plotlsty = -1111111;
drawn = 0;
return(1);
}
/******************************************************************************/
/*
* PLOT_draw
*
* print the commands to draw a line from the current graphics position
* to (x, y).
*/
static
PLOT_draw(x, y)
int x, y;
{
if (plotlstx != vdevice.cpVx || plotlsty != vdevice.cpVy)
fprintf(fp, plotcmds[P_MOVE], vdevice.cpVx, vdevice.cpVy);
fprintf(fp, plotcmds[P_DRAW], x, y);
plotlstx = x;
plotlsty = y;
drawn = 1;
}
/******************************************************************************/
/* PLOT_exit
* exit from vogle printing the command to put away the pen and flush the buffer.
*/
static PLOT_exit()
{
fprintf(fp, plotcmds[P_PEN], 0);
fprintf(fp, plotcmds[P_EXIT]);
fflush(fp);
if (fp != stdout && fp != stderr ){
fflush(fp);
if(vdevice.writestoprocess == 2){
pclose(fp);
}else{
fclose(fp);
}
}
drawn = 1;
}
/******************************************************************************/
/* PLOT_clear flush current page without resetting graphics state of printer
*/
static
PLOT_clear()
{
if (drawn){
/*
CLEAR_DEVICE is plotcmds[P_CLEAR]) expanded
to a fixed string for this device format
*/
fprintf(fp, CLEAR_DEVICE);
}
drawn = 0;
}
/******************************************************************************/
/*
* PLOT_color
*
* change the current pen number.
*
* set the current drawing color index if ind >= 0.
* set the line width in raster units if ind < 0.
* use of -1 value implies use thinnest line
*/
static
PLOT_color(i)
int i;
{
static float line_width = 0.2;
if ( i < 0 )
{
if ( i == -1 )
{
line_width=0.0; /* HPGL2 will draw thinnest line possible */
} else
{
line_width=abs(i)*.085; /* approximately one raster at 300dpi is .085 mm */
}
fprintf(fp,plotcmds[P_WIDE] , line_width);
} else {
fprintf(fp, plotcmds[P_PEN], i);
/*
The pen thickness might return to the default each time
a new pen is selected in HPGL2; but vogle expects
these properties to be separate. Newer versions of HPGL2 documentation
indicate that PW stays in effect until a PU or another PW command
is encountered; but an older manual states that the pen thickness
returns to the default value when a new pen is selected. A third
possibility is that each pen retains its last thickness so I think
it is better to force it each time a pen number is selected.
Could reduce redundant calls by checking if same as last call
*/
fprintf(fp,plotcmds[P_WIDE] , line_width);
}
}
/******************************************************************************/
/*
* PLOT_setlw
*
* set the line width in raster units
* use of -1 value implies use thinnest line
*/
static PLOT_setlw(int i) {
static float line_width = 0.2;
if ( i <= -1 ) {
line_width=0.0; /* HPGL2 will draw thinnest line possible */
} else {
line_width=(float)vdevice.sizeX/10000.0*abs(i); /* figure number of rasters */
/* approximately one raster at 300dpi is .085 mm */
line_width=line_width*3.333*0.085;
}
fprintf(fp,plotcmds[P_WIDE] , line_width);
}
/******************************************************************************/
/* change index i in the color map to the appropriate rgb value. */
PLOT_mapcolor(i, r, g, b)
int i;
int r, g, b;
{
/* fprintf(stderr, "mapcolor = %d %d %d %d\n", i,r,g,b); */
if (i >= CMAPSIZE || i < 0 ){
return(-1);
}
if (i >= CMAPSIZE)
return(0);
fprintf(fp, "PC%d,%d,%d,%d\n", i, r, g, b);
return(0);
}
/******************************************************************************/
/*
* HPGL2_font
*
* load in large or small
*/
static int
HPGL2_font(font)
char *font;
{
if (strcmp(font, "small") == 0) {
vdevice.hwidth = 97.01; /* Size in plotter resolution units */
vdevice.hheight = vdevice.hwidth * 2.0;
fprintf(fp, plotcmds[P_TXTSIZE], 0.16, 0.32);
} else if (strcmp(font, "large") == 0) {
vdevice.hwidth = 145.5;
vdevice.hheight = vdevice.hwidth * 2.0;
fprintf(fp, plotcmds[P_TXTSIZE], 0.24, 0.48);
} else
return(0);
return(1);
}
/******************************************************************************/
/*
* PLOT_char
*
* draw a character.
*/
static int PLOT_char(char c)
{
int dy, dx;
if (plotlstx != vdevice.cpVx || plotlsty != vdevice.cpVy)
fprintf(fp, plotcmds[P_MOVE], vdevice.cpVx, vdevice.cpVy);
fprintf(fp, plotcmds[P_BEGTXT]);
fprintf(fp, "%c", c);
fprintf(fp, plotcmds[P_ENDTXT]);
plotlstx = plotlsty = -1111111;
drawn = 1;
}
/******************************************************************************/
/* output a string. */
static
PLOT_string(s)
char *s;
{
int dy, dx;
if (plotlstx != vdevice.cpVx || plotlsty != vdevice.cpVy)
fprintf(fp, plotcmds[P_MOVE], vdevice.cpVx, vdevice.cpVy);
fprintf(fp, plotcmds[P_BEGTXT]);
fputs(s, fp);
fprintf(fp, plotcmds[P_ENDTXT]);
plotlstx = plotlsty = -1111111;
drawn = 1;
}
/******************************************************************************/
/* "fill" a polygon */
static
PLOT_fill(n, x, y)
int n, x[], y[];
{
int i;
int xclose, yclose, move_draw;
xclose=x[0];
yclose=y[0];
if (plotlstx != x[0] || plotlsty != y[0])
fprintf(fp, plotcmds[P_MOVE], x[0], y[0]); /* update current position if needed */
fprintf(fp, plotcmds[P_FILL]); /* enter polygon mode */
move_draw=P_DRAW;
for (i = 1; i < n; i++){
/* If not last point in list and hit first point close this as a subpolygon */
if (x[i] == xclose && y[i] == yclose && (i != (n-1)) )
{
fprintf(fp, plotcmds[P_DRAW], x[i], y[i]); /* define polygon vertices */
fprintf(fp, plotcmds[P_BREAKFILL]); /* end subpolygon */
move_draw=P_MOVE; /* move to first point in next subpolygon */
}else{
fprintf(fp, plotcmds[move_draw],x[i],y[i]); /* define polygon vertices */
move_draw=P_DRAW; /* if moving because starting a new subpolygon return to drawing */
}
}
fprintf(fp, plotcmds[P_ENDFILL]); /* end polygon and fill it */
fprintf(fp, plotcmds[P_MOVE], x[n-1], y[n-1]); /* current position should be last one moved to, not x0,y0 */
plotlstx = vdevice.cpVx = x[n - 1];
plotlsty = vdevice.cpVy = y[n - 1];
drawn = 1;
}
/******************************************************************************/
static DevEntry HPGL2dev = {
"HPGL2",
"large",
"small",
noop,
PLOT_char,
noop,
PLOT_clear,
PLOT_color,
PLOT_draw,
PLOT_exit,
PLOT_fill,
HPGL2_font,
noop,
noop,
HPGL2_LAND_init,
noop,
PLOT_mapcolor,
PLOT_setlw,
PLOT_string,
noop,
noop
};
/******************************************************************************/
/*
* _HPGL2_devcpy
*
* copy the HPGL2 device into vdevice.dev.
*/
_HPGL2_A2_devcpy()
{
/* if you don't have structure assignment ...
char *dev, *tdev, *edev;
dev = (char *)&HPGL2dev;
tdev = (char *)&vdevice.dev;
edev = dev + sizeof(Device);
while (dev != edev)
*tdev++ = *dev++;
*/
vdevice.dev = HPGL2dev;
}
/******************************************************************************/
_PCL5_LAND_devcpy()
{
vdevice.dev = HPGL2dev;
vdevice.dev.Vinit = PCL5_LAND_init;
}
/******************************************************************************/
_PCL5_PORT_devcpy()
{
vdevice.dev = HPGL2dev;
vdevice.dev.Vinit = PCL5_PORT_init;
}
/******************************************************************************/
_HPGL2_PORT_devcpy()
{
vdevice.dev = HPGL2dev;
vdevice.dev.Vinit = HPGL2_PORT_init;
}
/******************************************************************************/
_HPGL2_LAND_devcpy()
{
vdevice.dev = HPGL2dev;
vdevice.dev.Vinit = HPGL2_LAND_init;
}
/******************************************************************************/