#ident "@(#)VOGLE:driver/hpdxy.c - VOGLE driver for DXY and HPGL"
#include
#include
#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;
/*
For importing into Microsoft Word 9x -- HPGL will not be supported
in Windows 97 or 2000.
Microsoft Word does not map the pens to the expected de-facto
color mappings by default
*/
static int remap[8]={0,1,2,3,4,5,6,7};
#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
/*
* basic commands for hpgl
* NOTE: Old HP plotters might require a , delimiter and no spaces
*/
static char *hpgl[] = {
"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 pcl */
static char *pcl[] = {
"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"
};
/* basic commands for dxy */
static char *dxy[] = {
"",
"M %d,%d\n",
"D %d,%d\n",
"S %d\n",
"P",
"\n",
"J %d\n",
"PG;\n",
"\033.)\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
*/
/******************************************************************************/
/* Performs the common parts of HPGL initialization. */
static int HPGL_common_init(int minx, int maxx, int miny, int maxy) {
vdevice.depth = 3; /* eight colors */
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, "SC 0,%d,0,%d;", vdevice.sizeSx, vdevice.sizeSy);
fprintf(fp,"TR0;\n"); /* transparency mode off, white areas are opaque */
plotcmds = hpgl;
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 HPGL initialization in portrait mode */
static int HPGL_common_initp(int minx, int maxx, int miny, int maxy) {
vdevice.depth = 3; /* eight colors */
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, "SC 0,%d,0,%d;", vdevice.sizeSx, vdevice.sizeSy);
fprintf(fp, "RO 90;"); /* rotate 90 degrees */
fprintf(fp,"TR0;\n"); /* transparency mode off, white areas are opaque */
plotcmds = hpgl;
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 PCL initialization. */
static int PCL_common_init(int minx, int maxx, int miny, int maxy) {
vdevice.depth = 3;
fp = _voutfile();
/* (exit PCL 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;SC 0,%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 */
plotcmds = pcl;
plotlstx = -1111111;
plotlsty = -1111111;
drawn = 0;
return(1);
}
/******************************************************************************/
/* Performs the common parts of PCL initialization in portrait mode */
static int PCL_common_initp(int minx, int maxx, int miny, int maxy) {
vdevice.depth = 3;
fp = _voutfile();
/* (exit PCL 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;SC 0,%d,0,%d;RO 90;",
minx, miny, maxx, maxy, vdevice.sizeSx, vdevice.sizeSy);
fprintf(fp,CLEAR_DEVICE);
fprintf(fp,"TR0;\n"); /* transparency mode off, white areas are opaque */
plotcmds = pcl;
plotlstx = -1111111;
plotlsty = -1111111;
drawn = 0;
return(1);
}
/******************************************************************************/
static int HPGL_PORT_init(void) {
/* 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(HPGL_common_initp(prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy));
}
/******************************************************************************/
static int PCL_PORT_init(void) {
/* 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(PCL_common_initp(prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy));
}
/******************************************************************************/
static int HPGL_LAND_init(void) {
/* 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(HPGL_common_init(prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy));
}
/******************************************************************************/
static int PCL_LAND_init(void) {
/* 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(PCL_common_init(prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy));
}
/******************************************************************************/
/*
* DXY_init
*
* set up dxy plotter. Returns 1 on success.
*/
static int DXY_init(void) {
fp = _voutfile();
vdevice.sizeX = vdevice.sizeY = 1920;
vdevice.sizeSx = 2668;
vdevice.sizeSy = 1920;
plotcmds = dxy;
strncpy(CLEAR_DEVICE,plotcmds[P_CLEAR],100); /* this has parameters sometimes so it is treated differently */
plotlstx = -1;
plotlsty = -1;
drawn = 0;
fprintf(fp, plotcmds[P_RESET]);
return(1);
}
/******************************************************************************/
/*
* PLOT_draw
*
* print the commands to draw a line from the current graphics position
* to (x, y).
*/
static int PLOT_draw(int x, int 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;
return(UNUSED);
}
/******************************************************************************/
/* PLOT_exit
* exit from vogle printing the command to put away the pen and flush the buffer.
*/
static int PLOT_exit(void) {
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;
return(UNUSED);
}
/******************************************************************************/
/* PLOT_clear flush current page without resetting graphics state of printer
*/
static int PLOT_clear(void) {
if (drawn){
/*
CLEAR_DEVICE is plotcmds[P_CLEAR]) expanded
to a fixed string for this device format
*/
fprintf(fp, CLEAR_DEVICE);
}
drawn = 0;
return(UNUSED);
}
/******************************************************************************/
static int PLOT_setlw(int i) {
static float line_width = 0.2;
if ( i <= -1 ) {
line_width=0.0; /* hpgl will draw thinnest line possible */
} else {
line_width=(float)vdevice.sizeX/10000.0*abs(i); /* figure number of rasters */
/*
Assuming pen width is in mm and 300dpi resolution
1 "raster" =1/300 inch
1inch=25.4mm
:= approximately one raster at 300dpi is .085 mm
*/
line_width=line_width*0.0846666/4.0;
}
fprintf(fp,plotcmds[P_WIDE] , line_width);
return(UNUSED);
}
/******************************************************************************/
/*
* 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 int PLOT_color(int i) {
static float line_width = 0.2;
if ( i < 0 ) {
PLOT_setlw(abs(i));
} else {
if(i<8){
fprintf(fp, plotcmds[P_PEN], remap[i]);
}else{
fprintf(fp, plotcmds[P_PEN], i);
}
/*
The pen thickness might return to the default each time a new
pen is selected in hpgl; but vogle expects these properties to
be separate. Newer versions of HPGL 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);
}
return(UNUSED);
}
/******************************************************************************/
/* load in large or small */
static int HPGL_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);
}
/******************************************************************************/
/* load in large or small */
static int DXY_font(char *font) {
if (strcmp(font, "small") == 0) {
vdevice.hwidth = 24.25;
vdevice.hheight = vdevice.hwidth * 2.0;
fprintf(fp, plotcmds[P_TXTSIZE], 3);
} else if (strcmp(font, "large") == 0) {
vdevice.hwidth = 36.375;
vdevice.hheight = vdevice.hwidth * 2.0;
fprintf(fp, plotcmds[P_TXTSIZE], 5);
} else
return(0);
return(1);
}
/******************************************************************************/
/* draw a character */
static int PLOT_char(char c) {
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;
return(UNUSED);
}
/******************************************************************************/
/* output a string. */
static int PLOT_string(char *s) {
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;
return(UNUSED);
}
/******************************************************************************/
/* "fill" a polygon */
static int PLOT_fill(int n, int x[], int 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;
return(UNUSED);
}
/******************************************************************************/
/* no operations - do nothing but return -1 */
static int noop(void) { return(-1); }
static int noop2(int *x, int *y) { return(-1); }
static int noop4(int a, int b, int c, int d) { return(-1); }
/******************************************************************************/
static DevEntry hpgldev = {
"hpgl", /* char *devname -- name of device */
"large", /* char *large -- name of large font */
"small", /* char *small -- name of small font */
noop, /* int (*Vbackb)() -- Set drawing in back buffer */
PLOT_char, /* int (*Vchar)() -- Draw a hardware character */
noop, /* int (*Vcheckkey)() -- Check if a key was hit */
PLOT_clear, /* int (*Vclear)() -- Clear screen to current color */
PLOT_color, /* int (*Vcolor)() -- Set current color */
PLOT_draw, /* int (*Vdraw)() -- Draw a line */
PLOT_exit, /* int (*Vexit)() -- Exit graphics */
PLOT_fill, /* int (*Vfill)() -- Fill a polygon */
HPGL_font, /* int (*Vfont)() -- Set hardware font */
noop, /* int (*Vfrontb)() -- Set drawing in front buffer */
noop, /* int (*Vgetkey)() -- Wait for and get next key hit */
HPGL_LAND_init, /* int (*Vinit)() -- Initialise device */
noop2, /* int (*Vlocator)() -- Get mouse/cross hair position */
noop4, /* int (*Vmapcolor)() -- Set color indices */
PLOT_setlw, /* int (*Vsetlw)() -- Set line width */
PLOT_string, /* int (*Vstring)() -- Draw a hardware string */
noop, /* int (*Vswapb)() -- Swap front and back buffers */
noop /* int (*Vsync)() -- Syncronise display */
};
/******************************************************************************/
static DevEntry dxydev = {
"dxy", /* char *devname -- name of device */
"large", /* char *large -- name of large font */
"small", /* char *small -- name of small font */
noop, /* int (*Vbackb)() -- Set drawing in back buffer */
PLOT_char, /* int (*Vchar)() -- Draw a hardware character */
noop, /* int (*Vcheckkey)() -- Check if a key was hit */
PLOT_clear, /* int (*Vclear)() -- Clear screen to current color */
PLOT_color, /* int (*Vcolor)() -- Set current color */
PLOT_draw, /* int (*Vdraw)() -- Draw a line */
PLOT_exit, /* int (*Vexit)() -- Exit graphics */
PLOT_fill, /* int (*Vfill)() -- Fill a polygon */
HPGL_font, /* int (*Vfont)() -- Set hardware font */
noop, /* int (*Vfrontb)() -- Set drawing in front buffer */
noop, /* int (*Vgetkey)() -- Wait for and get next key hit */
DXY_init, /* int (*Vinit)() -- Initialise device */
noop2, /* int (*Vlocator)() -- Get mouse/cross hair position */
noop4, /* int (*Vmapcolor)() -- Set color indices */
PLOT_setlw, /* int (*Vsetlw)() -- Set line width */
PLOT_string, /* int (*Vstring)() -- Draw a hardware string */
noop, /* int (*Vswapb)() -- Swap front and back buffers */
noop /* int (*Vsync)() -- Syncronise display */
};
/******************************************************************************/
int HPGL_setpens(void){
int i;
char *env_variable;
if ((env_variable = (char *)getenv("VPENS")) != NULL){
sscanf(env_variable, "%d,%d,%d,%d,%d,%d,%d,%d",
&remap[0], &remap[1], &remap[2], &remap[3],
&remap[4], &remap[5], &remap[6], &remap[7]);
} else{
for(i=0; i<8; i++){
remap[i]=i;
}
}
return(UNUSED);
}
/******************************************************************************/
/*
* _HPGL_devcpy
*
* copy the HPGL device into vdevice.dev.
*/
int _HPGL_A2_devcpy(void) {
/* if you don't have structure assignment ...
char *dev, *tdev, *edev;
dev = (char *)&hpgldev;
tdev = (char *)&vdevice.dev;
edev = dev + sizeof(Device);
while (dev != edev)
*tdev++ = *dev++;
*/
vdevice.dev = hpgldev;
return(UNUSED);
}
/******************************************************************************/
int _PCL_LAND_devcpy(void) {
vdevice.dev = hpgldev;
vdevice.dev.Vinit = PCL_LAND_init;
return(UNUSED);
}
/******************************************************************************/
int _PCL_PORT_devcpy(void) {
vdevice.dev = hpgldev;
vdevice.dev.Vinit = PCL_PORT_init;
return(UNUSED);
}
/******************************************************************************/
int _HPGL_PORT_devcpy(void) {
vdevice.dev = hpgldev;
vdevice.dev.Vinit = HPGL_PORT_init;
/*strcpy(vdevice.dev.devname,"hpglport");*/
/*vdevice.dev.devname={'h','p','g','l','p','o','r','t','\0'};*/
vdevice.dev.devname="hpglport";
HPGL_setpens();
return(UNUSED);
}
/******************************************************************************/
int _HPGL_LAND_devcpy(void) {
vdevice.dev = hpgldev;
vdevice.dev.Vinit = HPGL_LAND_init;
/*strcpy(vdevice.dev.devname,"hpglland");*/
/*vdevice.dev.devname={'h','p','g','l','l','a','n','d','\0'};*/
vdevice.dev.devname="hpglland";
HPGL_setpens();
return(UNUSED);
}
/******************************************************************************/
/*
* _DXY_devcpy
*
* copy the DXY device into vdevice.dev.
*/
int _DXY_devcpy(void) {
/* if you don't have structure assignment ...
char *dev, *tdev, *edev;
dev = (char *)&dxydev;
tdev = (char *)&vdevice.dev;
edev = dev + sizeof(DevEntry);
while (dev != edev)
*tdev++ = *dev++;
*/
vdevice.dev = dxydev;
return(UNUSED);
}
/******************************************************************************/