32 changed files with 536 additions and 510 deletions
-
4src/frontend/com_let.c
-
950src/frontend/postsc.c
-
9src/frontend/spiceif.c
-
8src/misc/string.c
-
2src/misc/stringutil.h
-
2src/spicelib/analysis/Makefile.am
-
2src/spicelib/analysis/ckt.h
-
3src/spicelib/analysis/cktdest.c
-
4src/spicelib/analysis/cktdojob.c
-
1src/spicelib/analysis/cktfbran.c
-
2src/spicelib/analysis/cktic.c
-
5src/spicelib/analysis/cktload.c
-
2src/spicelib/analysis/cktmask.c
-
3src/spicelib/analysis/cktmpar.c
-
1src/spicelib/analysis/cktparam.c
-
1src/spicelib/analysis/cktpname.c
-
1src/spicelib/analysis/cktpzld.c
-
2src/spicelib/analysis/cktpzset.c
-
1src/spicelib/analysis/cktsens.c
-
1src/spicelib/analysis/cktsetup.c
-
3src/spicelib/analysis/cktsgen.c
-
3src/spicelib/analysis/cktsopt.c
-
2src/spicelib/analysis/ckttemp.c
-
2src/spicelib/analysis/ckttroub.c
-
1src/spicelib/analysis/ckttrunc.c
-
12src/spicelib/analysis/distoan.c
-
2src/spicelib/analysis/noisean.c
-
4src/spicelib/analysis/pzan.c
-
2src/spicelib/analysis/tfanal.c
-
3src/spicelib/parser/inp2r.c
-
6src/spicelib/parser/inpfindl.c
-
2src/spicelib/parser/inppas2.c
@ -1,472 +1,478 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1988 Jeffrey M. Hsu |
|||
**********/ |
|||
|
|||
/* |
|||
Postscript driver |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cpdefs.h" |
|||
#include "graph.h" |
|||
#include "ftedbgra.h" |
|||
#include "ftedev.h" |
|||
#include "fteinput.h" |
|||
|
|||
#include "postsc.h" |
|||
#include "variable.h" |
|||
|
|||
#define RAD_TO_DEG (180.0 / M_PI) |
|||
#define DEVDEP(g) (*((PSdevdep *) (g)->devdep)) |
|||
#define MAX_PS_LINES 1000 |
|||
#define SOLID 0 |
|||
#define DOTTED 1 |
|||
|
|||
#define gtype graph->grid.gridtype |
|||
#define xoff dispdev->minx |
|||
#define yoff dispdev->miny |
|||
#define XOFF 48 /* printer left margin */ |
|||
#define YOFF 48 /* printer bottom margin */ |
|||
#define XTADJ 0 /* printer text adjustment x */ |
|||
#define YTADJ 4 /* printer text adjustment y */ |
|||
|
|||
#define GRIDSIZE 420 /* printer gridsize divisible by 10, [7-2] */ |
|||
#define GRIDSIZES 360 /* printer gridsize divisible by [10-8], [6-2] */ |
|||
|
|||
#define FONTSIZE 10 /* printer default fontsize */ |
|||
#define FONTWIDTH 6 /* printer default fontwidth */ |
|||
#define FONTHEIGHT 14 /* printer default fontheight */ |
|||
|
|||
typedef struct { |
|||
int lastlinestyle, lastcolor; /* initial invalid value */ |
|||
int lastx, lasty, linecount; |
|||
} PSdevdep; |
|||
|
|||
static char *linestyle[] = { |
|||
"[]", /* solid */ |
|||
"[1 2]", /* dotted */ |
|||
"[7 7]", /* longdashed */ |
|||
"[3 3]", /* shortdashed */ |
|||
"[7 2 2 2]", /* longdotdashed */ |
|||
"[3 2 1 2]", /* shortdotdashed */ |
|||
"[8 3 2 3]", |
|||
"[14 2]", |
|||
"[3 5 1 5]" /* dotdashed */ |
|||
}; |
|||
|
|||
static FILE *plotfile; |
|||
char psfont[128], psfontsize[32], psscale[32], pscolor[32]; |
|||
static int fontsize = FONTSIZE; |
|||
static int fontwidth = FONTWIDTH; |
|||
static int fontheight = FONTHEIGHT; |
|||
static int screenflag = 0; |
|||
static int colorflag = 0; |
|||
static double scale; /* Used for fine tuning */ |
|||
static int xtadj; /* text adjustment x */ |
|||
static int ytadj; /* text adjustment y */ |
|||
static int hcopygraphid; |
|||
|
|||
|
|||
extern int DestroyGraph (int id); |
|||
extern void internalerror (char *message); |
|||
void PS_LinestyleColor(int linestyleid, int colorid); |
|||
void PS_SelectColor(int colorid); |
|||
void PS_Stroke(void); |
|||
|
|||
int |
|||
PS_Init(void) |
|||
{ |
|||
char pswidth[30], psheight[30]; |
|||
|
|||
if (!cp_getvar("hcopyscale", VT_STRING, psscale)) { |
|||
scale = 1.0; |
|||
} else { |
|||
sscanf(psscale, "%lf", &scale); |
|||
if ((scale <= 0) || (scale > 10)) |
|||
scale = 1.0; |
|||
} |
|||
|
|||
if (!cp_getvar("hcopypscolor", VT_STRING, pscolor)) { |
|||
colorflag = 0; |
|||
dispdev->numcolors = 2; |
|||
dispdev->numlinestyles = NUMELEMS(linestyle); |
|||
} else { |
|||
colorflag = 1; |
|||
dispdev->numcolors = 18; /* don't know what the maximum should be */ |
|||
dispdev->numlinestyles = 1; |
|||
} |
|||
pscolor[0]='\0'; |
|||
|
|||
if (!cp_getvar("hcopywidth", VT_STRING, pswidth)) { |
|||
dispdev->width = 7.75 * 72.0 * scale; /* (8 1/2 - 3/4) * 72 */ |
|||
} else { |
|||
sscanf(pswidth, "%d", &(dispdev->width)); |
|||
if (dispdev->width <= 100) |
|||
dispdev->width = 100; |
|||
if (dispdev->width >= 10000) |
|||
dispdev->width = 10000; |
|||
} |
|||
if (!cp_getvar("hcopyheight", VT_STRING, psheight)) { |
|||
dispdev->height = dispdev->width; |
|||
} else { |
|||
sscanf(psheight, "%d", &(dispdev->height)); |
|||
if (dispdev->height <= 100) |
|||
dispdev->height = 100; |
|||
if (dispdev->height >= 10000) |
|||
dispdev->height = 10000; |
|||
} |
|||
|
|||
/* The following side effects have to be considered |
|||
* when the printer is called by com_hardcopy ! |
|||
* gr_init: |
|||
* viewportxoff = 8 * fontwidth |
|||
* viewportyoff = 4 * fontheight |
|||
* gr_resize_internal: |
|||
* viewport.width = absolute.width - 2 * viewportxoff |
|||
* viewport.height = absolute.height - 2 * viewportyoff |
|||
*/ |
|||
|
|||
if (!cp_getvar("hcopyfont", VT_STRING, psfont)) |
|||
strcpy(psfont, "Helvetica"); |
|||
if (!cp_getvar("hcopyfontsize", VT_STRING, psfontsize)) { |
|||
fontsize = 10; |
|||
fontwidth = 6; |
|||
fontheight = 14; |
|||
xtadj = XTADJ * scale; |
|||
ytadj = YTADJ * scale; |
|||
} else { |
|||
sscanf(psfontsize, "%d", &fontsize); |
|||
if ((fontsize < 10) || (fontsize > 14)) |
|||
fontsize = 10; |
|||
fontwidth = 0.5 + 0.6 * fontsize; |
|||
fontheight = 2.5 + 1.2 * fontsize; |
|||
xtadj = XTADJ * scale * fontsize / 10; |
|||
ytadj = YTADJ * scale * fontsize / 10; |
|||
} |
|||
|
|||
screenflag = 0; |
|||
dispdev->minx = XOFF / scale; |
|||
dispdev->miny = YOFF / scale; |
|||
return(0); |
|||
} |
|||
|
|||
/* devdep initially contains name of output file */ |
|||
int |
|||
PS_NewViewport(GRAPH *graph) |
|||
{ |
|||
int x1,x2,y1,y2; |
|||
hcopygraphid = graph->graphid; |
|||
|
|||
if (!(plotfile = fopen(graph->devdep, "w"))) { |
|||
perror(graph->devdep); |
|||
graph->devdep = (char *) NULL; |
|||
return(1); |
|||
} |
|||
|
|||
if (graph->absolute.width) { |
|||
/* hardcopying from the screen */ |
|||
|
|||
screenflag = 1; |
|||
} |
|||
|
|||
/* reasonable values, used in gr_ for placement */ |
|||
graph->fontwidth = fontwidth * scale; /* was 12, p.w.h. */ |
|||
graph->fontheight = fontheight * scale; /* was 24, p.w.h. */ |
|||
|
|||
graph->absolute.width = dispdev->width; |
|||
graph->absolute.height = dispdev->height; |
|||
/* Also done in gr_init, if called . . . */ |
|||
graph->viewportxoff = 8 * fontwidth; |
|||
graph->viewportyoff = 4 * fontheight; |
|||
|
|||
xoff = scale * XOFF; |
|||
yoff = scale * YOFF; |
|||
|
|||
x1 = 0.75 * 72; |
|||
y1 = x1; |
|||
x2 = graph->absolute.width + .75 * 72; |
|||
y2 = graph->absolute.height + .75 * 72; |
|||
/* start file off with a % */ |
|||
fprintf(plotfile, "%%!PS-Adobe-3.0 EPSF-3.0\n"); |
|||
fprintf(plotfile, "%%%%Creator: nutmeg\n"); |
|||
fprintf(plotfile, "%%%%BoundingBox: %d %d %d %d\n",x1,y1,x2,y2); |
|||
|
|||
fprintf(plotfile, "%g %g scale\n", 1.0 / scale, 1.0 / scale); |
|||
|
|||
if (colorflag == 1){ /* set the background to color0 */ |
|||
PS_SelectColor(0); |
|||
fprintf(plotfile,"%s setrgbcolor\n",pscolor); |
|||
fprintf(plotfile,"newpath\n"); |
|||
fprintf(plotfile,"%d %d moveto %d %d lineto\n",x1,y1,x2,y1); |
|||
fprintf(plotfile,"%d %d lineto %d %d lineto\n",x2,y2,x1,y2); |
|||
fprintf(plotfile,"closepath fill\n"); |
|||
} |
|||
|
|||
/* set up a reasonable font */ |
|||
fprintf(plotfile, "/%s findfont %d scalefont setfont\n\n", |
|||
psfont, (int) (fontsize * scale)); |
|||
|
|||
graph->devdep = tmalloc(sizeof(PSdevdep)); |
|||
DEVDEP(graph).lastlinestyle = -1; |
|||
DEVDEP(graph).lastcolor = -1; |
|||
DEVDEP(graph).lastx = -1; |
|||
DEVDEP(graph).lasty = -1; |
|||
DEVDEP(graph).linecount = 0; |
|||
PS_SelectColor(0); |
|||
graph->linestyle = -1; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void |
|||
PS_Close(void) |
|||
{ |
|||
/* in case PS_Close is called as part of an abort, |
|||
w/o having reached PS_NewViewport */ |
|||
if (plotfile){ |
|||
PS_Stroke(); |
|||
fprintf(plotfile, "showpage\n%%%%EOF\n"); |
|||
fclose(plotfile); |
|||
plotfile = NULL; |
|||
} |
|||
|
|||
/* In case of hardcopy command destroy the hardcopy graph |
|||
* and reset currentgraph to graphid 1, if possible |
|||
*/ |
|||
if (!screenflag) { |
|||
DestroyGraph(hcopygraphid); |
|||
currentgraph = FindGraph(1); |
|||
} |
|||
} |
|||
|
|||
void |
|||
PS_Clear(void) |
|||
{ |
|||
/* do nothing */ |
|||
} |
|||
|
|||
void |
|||
PS_DrawLine(int x1, int y1, int x2, int y2) |
|||
{ |
|||
/* note: this is not extendible to more than one graph |
|||
=> will have to give NewViewport a writeable graph XXX */ |
|||
|
|||
if (DEVDEP(currentgraph).linecount > MAX_PS_LINES |
|||
|| DEVDEP(currentgraph).linecount == 0 |
|||
|| x1 != DEVDEP(currentgraph).lastx |
|||
|| y1 != DEVDEP(currentgraph).lasty){ |
|||
PS_Stroke(); |
|||
fprintf(plotfile, "newpath\n"); |
|||
fprintf(plotfile, "%d %d moveto\n", x1 + xoff, y1 + yoff); |
|||
DEVDEP(currentgraph).linecount += 1; |
|||
} |
|||
if (x1 != x2 || y1 != y2) { |
|||
fprintf(plotfile, "%d %d lineto\n", x2 + xoff, y2 + yoff); |
|||
DEVDEP(currentgraph).linecount += 1; |
|||
} |
|||
|
|||
DEVDEP(currentgraph).lastx = x2; |
|||
DEVDEP(currentgraph).lasty = y2; |
|||
} |
|||
|
|||
void |
|||
PS_Arc(int x0, int y0, int r, double theta1, double theta2) |
|||
{ |
|||
double x1, y1; |
|||
double angle1, angle2; |
|||
PS_Stroke(); |
|||
while (theta1 >= theta2) |
|||
theta2 += 2 * M_PI; |
|||
|
|||
angle1 = (double) (RAD_TO_DEG * theta1); |
|||
angle2 = (double) (RAD_TO_DEG * theta2); |
|||
x1 = (double) x0 + r * cos(theta1); |
|||
y1 = (double) y0 + r * sin(theta1); |
|||
|
|||
fprintf(plotfile, "%f %f moveto ", x1+(double)xoff, y1+(double)yoff); |
|||
fprintf(plotfile, "%d %d %d %f %f arc\n", x0+xoff, y0+yoff, r, |
|||
angle1, angle2); |
|||
fprintf(plotfile, "stroke\n"); |
|||
|
|||
DEVDEP(currentgraph).linecount = 0; |
|||
} |
|||
|
|||
void |
|||
PS_Text(char *text, int x, int y) |
|||
{ |
|||
int savedlstyle, savedcolor; |
|||
|
|||
/* set linestyle to solid |
|||
or may get funny color text on some plotters */ |
|||
savedlstyle = currentgraph->linestyle; |
|||
savedcolor = currentgraph->currentcolor; |
|||
|
|||
PS_SetLinestyle(SOLID); |
|||
PS_SetColor(1); |
|||
|
|||
/* stroke the path if there's an open one */ |
|||
PS_Stroke(); |
|||
/* move to (x, y) */ |
|||
fprintf(plotfile, "%d %d moveto\n", x + xoff + xtadj, y + yoff + ytadj); |
|||
fprintf(plotfile, "(%s) show\n", text); |
|||
|
|||
DEVDEP(currentgraph).lastx = -1; |
|||
DEVDEP(currentgraph).lasty = -1; |
|||
|
|||
/* restore old linestyle */ |
|||
|
|||
PS_SetColor(savedcolor); |
|||
PS_SetLinestyle(savedlstyle); |
|||
} |
|||
|
|||
/* PS_DefineColor */ |
|||
/* PS_DefineLinestyle */ |
|||
|
|||
int |
|||
PS_SetLinestyle(int linestyleid) |
|||
{ |
|||
/* special case |
|||
get it when PS_Text restores a -1 linestyle */ |
|||
if (linestyleid == -1) { |
|||
currentgraph->linestyle = -1; |
|||
return 0; |
|||
} |
|||
if (linestyleid < 0 || linestyleid > dispdev->numlinestyles) { |
|||
internalerror("bad linestyleid inside PS_SetLinestyle"); |
|||
return 0; |
|||
} |
|||
PS_LinestyleColor(linestyleid, currentgraph->currentcolor); |
|||
return 0; |
|||
} |
|||
|
|||
void |
|||
PS_SetColor(int colorid) |
|||
{ |
|||
PS_LinestyleColor(currentgraph->linestyle, colorid); |
|||
} |
|||
|
|||
void |
|||
PS_Update(void) |
|||
{ |
|||
fflush(plotfile); |
|||
} |
|||
|
|||
/**************** PRIVAT FUNCTIONS OF PS FRONTEND *****************************/ |
|||
|
|||
void |
|||
PS_SelectColor(int colorid) /* should be replaced by PS_DefineColor */ |
|||
{ |
|||
char colorN[30]="", colorstring[30]=""; |
|||
char rgb[30], s_red[30]="0x", s_green[30]="0x", s_blue[30]="0x"; |
|||
long red=0, green=0, blue=0, scale=1; |
|||
int i; |
|||
typedef struct { int red, green, blue;} COLOR; |
|||
/* duplicated colors from src/frontend/plotting/x11.c in rgb-style */ |
|||
const COLOR colors[]= {{ 0, 0, 0}, /*0: black */ |
|||
{255, 255, 255}, /*1: white */ |
|||
{255, 0, 0}, /*2: red */ |
|||
{ 0, 0, 255}, /*3: blue */ |
|||
{255, 165, 0}, /*4: orange */ |
|||
{ 0, 255, 0}, /*5: green */ |
|||
{255, 192, 203}, /*6: pink */ |
|||
{165, 42, 42}, /*7: brown */ |
|||
{240, 230, 140}, /*8: khaki */ |
|||
{221, 160, 221}, /*9: plum */ |
|||
{218, 112, 214}, /*10: orchid */ |
|||
{238, 130, 238}, /*11: violet */ |
|||
{176, 48, 96}, /*12: maroon */ |
|||
{ 64, 224, 208}, /*13: turqoise */ |
|||
{160, 82, 45}, /*14: sienna */ |
|||
{255, 127, 80}, /*15: coral */ |
|||
{ 0, 255, 255}, /*16: cyan */ |
|||
{255, 0, 255}, /*17: magenta */ |
|||
/*{255, 215, 0}, 18: gold */ |
|||
{ 96, 96, 96}, /*18: gray for smith grid */ |
|||
/*{255, 255, 0}, 19: yello */ |
|||
{150, 150, 150}, /*19: gray for smith grid */ |
|||
{128, 128, 128}}; /*20: gray for normal grid */ |
|||
|
|||
/* Extract the rgbcolor, format is: "rgb:<red>/<green>/<blue>" */ |
|||
sprintf(colorN, "color%d",colorid); |
|||
if (cp_getvar(colorN, VT_STRING, colorstring)){ |
|||
for (i=0; colorstring[i]; i++) |
|||
if (colorstring[i] == '/' || colorstring[i] == ':') |
|||
colorstring[i] = ' '; |
|||
|
|||
sscanf(colorstring,"%s %s %s %s",rgb, &(s_red[2]), &(s_green[2]), &(s_blue[2])); |
|||
|
|||
if ((strlen(s_blue) == strlen(s_red) && strlen(s_green) == strlen(s_red)) |
|||
&& (strlen(s_blue) > 2) && (strlen(s_blue) < 7)){ |
|||
sscanf(s_red,"%lx",&red); |
|||
sscanf(s_green,"%lx",&green); |
|||
sscanf(s_blue,"%lx",&blue); |
|||
scale= (1 << (strlen(s_blue) - 2) * 4) - 1; |
|||
sprintf(colorstring,"%1.3f %1.3f %1.3f", |
|||
(float) red/scale, (float) green/scale, (float) blue/scale); |
|||
strcpy(pscolor, colorstring); |
|||
} |
|||
} |
|||
if (colorid < 0 || colorid > 20) { |
|||
internalerror("bad colorid inside PS_SelectColor"); |
|||
}else if (scale == 1){ /* colorN is not an rgbstring, use default color */ |
|||
sprintf(colorstring,"%1.3f %1.3f %1.3f",colors[colorid].red/255.0, |
|||
colors[colorid].green/255.0, colors[colorid].blue/255.0) ; |
|||
strcpy(pscolor, colorstring); |
|||
} |
|||
} |
|||
|
|||
void |
|||
PS_LinestyleColor(int linestyleid, int colorid) |
|||
{ |
|||
/* we have some different linestyles and colors: |
|||
- color and linestyle we got via function call |
|||
- color and linestyle we used last time for drawing |
|||
- generated color and linestyle we'll use for drawing this time */ |
|||
/* these are the rules: |
|||
DOTTED and colored ps -> color20 (used for grid) and SOLID |
|||
color18 or 19 and black-white -> linestyle is DOTTED */ |
|||
|
|||
int gencolor=0,genstyle=0; |
|||
|
|||
if (colorflag == 1){ |
|||
genstyle = SOLID; |
|||
if (linestyleid==DOTTED) |
|||
gencolor = 20; |
|||
else |
|||
gencolor = colorid; |
|||
} else { /* colorflag == 0 -> mono*/ |
|||
if ((colorid == 18) || (colorid == 19)) |
|||
genstyle=DOTTED; |
|||
else |
|||
genstyle=linestyleid; |
|||
} |
|||
|
|||
/* change color if nessecary */ |
|||
if (colorflag == 1 && gencolor != DEVDEP(currentgraph).lastcolor){ |
|||
PS_SelectColor(gencolor); |
|||
PS_Stroke(); |
|||
fprintf(plotfile,"%s setrgbcolor\n",pscolor); |
|||
DEVDEP(currentgraph).lastcolor = gencolor; |
|||
} |
|||
currentgraph->currentcolor = colorid; |
|||
|
|||
/* change linestyle if nessecary */ |
|||
if (colorflag == 0 && genstyle != DEVDEP(currentgraph).lastlinestyle){ |
|||
PS_Stroke(); |
|||
fprintf(plotfile, "%s 0 setdash\n", linestyle[genstyle]); |
|||
DEVDEP(currentgraph).lastlinestyle= genstyle; |
|||
} |
|||
currentgraph->linestyle = linestyleid; |
|||
} |
|||
|
|||
void |
|||
PS_Stroke(void) |
|||
{ |
|||
/* strokes an open path */ |
|||
if (DEVDEP(currentgraph).linecount > 0) { |
|||
fprintf(plotfile, "stroke\n"); |
|||
DEVDEP(currentgraph).linecount = 0; |
|||
} |
|||
} |
|||
|
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1988 Jeffrey M. Hsu |
|||
**********/ |
|||
|
|||
/* |
|||
Postscript driver |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cpdefs.h" |
|||
#include "graph.h" |
|||
#include "ftedbgra.h" |
|||
#include "ftedev.h" |
|||
#include "fteinput.h" |
|||
|
|||
#include "postsc.h" |
|||
#include "variable.h" |
|||
|
|||
#define RAD_TO_DEG (180.0 / M_PI) |
|||
#define DEVDEP(g) (*((PSdevdep *) (g)->devdep)) |
|||
#define MAX_PS_LINES 1000 |
|||
#define SOLID 0 |
|||
#define DOTTED 1 |
|||
|
|||
#define gtype graph->grid.gridtype |
|||
#define xoff dispdev->minx |
|||
#define yoff dispdev->miny |
|||
#define XOFF 48 /* printer left margin */ |
|||
#define YOFF 48 /* printer bottom margin */ |
|||
#define XTADJ 0 /* printer text adjustment x */ |
|||
#define YTADJ 4 /* printer text adjustment y */ |
|||
|
|||
#define GRIDSIZE 420 /* printer gridsize divisible by 10, [7-2] */ |
|||
#define GRIDSIZES 360 /* printer gridsize divisible by [10-8], [6-2] */ |
|||
|
|||
#define FONTSIZE 10 /* printer default fontsize */ |
|||
#define FONTWIDTH 6 /* printer default fontwidth */ |
|||
#define FONTHEIGHT 14 /* printer default fontheight */ |
|||
|
|||
typedef struct { |
|||
int lastlinestyle, lastcolor; /* initial invalid value */ |
|||
int lastx, lasty, linecount; |
|||
} PSdevdep; |
|||
|
|||
static char *linestyle[] = { |
|||
"[]", /* solid */ |
|||
"[1 2]", /* dotted */ |
|||
"[7 7]", /* longdashed */ |
|||
"[3 3]", /* shortdashed */ |
|||
"[7 2 2 2]", /* longdotdashed */ |
|||
"[3 2 1 2]", /* shortdotdashed */ |
|||
"[8 3 2 3]", |
|||
"[14 2]", |
|||
"[3 5 1 5]" /* dotdashed */ |
|||
}; |
|||
|
|||
static FILE *plotfile; |
|||
char psfont[128], psfontsize[32], psscale[32], pscolor[32]; |
|||
static int fontsize = FONTSIZE; |
|||
static int fontwidth = FONTWIDTH; |
|||
static int fontheight = FONTHEIGHT; |
|||
static int screenflag = 0; |
|||
static int colorflag = 0; |
|||
static double scale; /* Used for fine tuning */ |
|||
static int xtadj; /* text adjustment x */ |
|||
static int ytadj; /* text adjustment y */ |
|||
static int hcopygraphid; |
|||
|
|||
|
|||
extern int DestroyGraph (int id); |
|||
extern void internalerror (char *message); |
|||
void PS_LinestyleColor(int linestyleid, int colorid); |
|||
void PS_SelectColor(int colorid); |
|||
void PS_Stroke(void); |
|||
|
|||
int |
|||
PS_Init(void) |
|||
{ |
|||
char pswidth[30], psheight[30]; |
|||
|
|||
if (!cp_getvar("hcopyscale", VT_STRING, psscale)) { |
|||
scale = 1.0; |
|||
} else { |
|||
sscanf(psscale, "%lf", &scale); |
|||
if ((scale <= 0) || (scale > 10)) |
|||
scale = 1.0; |
|||
} |
|||
|
|||
if (!cp_getvar("hcopypscolor", VT_STRING, pscolor)) { |
|||
colorflag = 0; |
|||
dispdev->numcolors = 2; |
|||
dispdev->numlinestyles = NUMELEMS(linestyle); |
|||
} else { |
|||
colorflag = 1; |
|||
dispdev->numcolors = 18; /* don't know what the maximum should be */ |
|||
dispdev->numlinestyles = 1; |
|||
} |
|||
pscolor[0]='\0'; |
|||
|
|||
if (!cp_getvar("hcopywidth", VT_STRING, pswidth)) { |
|||
dispdev->width = 7.75 * 72.0 * scale; /* (8 1/2 - 3/4) * 72 */ |
|||
} else { |
|||
sscanf(pswidth, "%d", &(dispdev->width)); |
|||
if (dispdev->width <= 100) |
|||
dispdev->width = 100; |
|||
if (dispdev->width >= 10000) |
|||
dispdev->width = 10000; |
|||
} |
|||
if (!cp_getvar("hcopyheight", VT_STRING, psheight)) { |
|||
dispdev->height = dispdev->width; |
|||
} else { |
|||
sscanf(psheight, "%d", &(dispdev->height)); |
|||
if (dispdev->height <= 100) |
|||
dispdev->height = 100; |
|||
if (dispdev->height >= 10000) |
|||
dispdev->height = 10000; |
|||
} |
|||
|
|||
/* The following side effects have to be considered |
|||
* when the printer is called by com_hardcopy ! |
|||
* gr_init: |
|||
* viewportxoff = 8 * fontwidth |
|||
* viewportyoff = 4 * fontheight |
|||
* gr_resize_internal: |
|||
* viewport.width = absolute.width - 2 * viewportxoff |
|||
* viewport.height = absolute.height - 2 * viewportyoff |
|||
*/ |
|||
|
|||
if (!cp_getvar("hcopyfont", VT_STRING, psfont)) |
|||
strcpy(psfont, "Helvetica"); |
|||
if (!cp_getvar("hcopyfontsize", VT_STRING, psfontsize)) { |
|||
fontsize = 10; |
|||
fontwidth = 6; |
|||
fontheight = 14; |
|||
xtadj = XTADJ * scale; |
|||
ytadj = YTADJ * scale; |
|||
} else { |
|||
sscanf(psfontsize, "%d", &fontsize); |
|||
if ((fontsize < 10) || (fontsize > 14)) |
|||
fontsize = 10; |
|||
fontwidth = 0.5 + 0.6 * fontsize; |
|||
fontheight = 2.5 + 1.2 * fontsize; |
|||
xtadj = XTADJ * scale * fontsize / 10; |
|||
ytadj = YTADJ * scale * fontsize / 10; |
|||
} |
|||
|
|||
screenflag = 0; |
|||
dispdev->minx = XOFF / scale; |
|||
dispdev->miny = YOFF / scale; |
|||
|
|||
return(0); |
|||
|
|||
} |
|||
|
|||
/* devdep initially contains name of output file */ |
|||
int |
|||
PS_NewViewport(GRAPH *graph) |
|||
{ |
|||
int x1,x2,y1,y2; |
|||
hcopygraphid = graph->graphid; |
|||
|
|||
if (!(plotfile = fopen(graph->devdep, "w"))) { |
|||
perror(graph->devdep); |
|||
graph->devdep = (char *) NULL; |
|||
return(1); |
|||
} |
|||
|
|||
if (graph->absolute.width) { |
|||
/* hardcopying from the screen */ |
|||
|
|||
screenflag = 1; |
|||
} |
|||
|
|||
/* reasonable values, used in gr_ for placement */ |
|||
graph->fontwidth = fontwidth * scale; /* was 12, p.w.h. */ |
|||
graph->fontheight = fontheight * scale; /* was 24, p.w.h. */ |
|||
|
|||
graph->absolute.width = dispdev->width; |
|||
graph->absolute.height = dispdev->height; |
|||
/* Also done in gr_init, if called . . . */ |
|||
graph->viewportxoff = 8 * fontwidth; |
|||
graph->viewportyoff = 4 * fontheight; |
|||
|
|||
xoff = scale * XOFF; |
|||
yoff = scale * YOFF; |
|||
|
|||
x1 = 0.75 * 72; |
|||
y1 = x1; |
|||
x2 = graph->absolute.width + .75 * 72; |
|||
y2 = graph->absolute.height + .75 * 72; |
|||
/* start file off with a % */ |
|||
fprintf(plotfile, "%%!PS-Adobe-3.0 EPSF-3.0\n"); |
|||
fprintf(plotfile, "%%%%Creator: nutmeg\n"); |
|||
fprintf(plotfile, "%%%%BoundingBox: %d %d %d %d\n",x1,y1,x2,y2); |
|||
|
|||
fprintf(plotfile, "%g %g scale\n", 1.0 / scale, 1.0 / scale); |
|||
|
|||
if (colorflag == 1){ /* set the background to color0 */ |
|||
PS_SelectColor(0); |
|||
fprintf(plotfile,"%s setrgbcolor\n",pscolor); |
|||
fprintf(plotfile,"newpath\n"); |
|||
fprintf(plotfile,"%d %d moveto %d %d lineto\n",x1,y1,x2,y1); |
|||
fprintf(plotfile,"%d %d lineto %d %d lineto\n",x2,y2,x1,y2); |
|||
fprintf(plotfile,"closepath fill\n"); |
|||
} |
|||
|
|||
/* set up a reasonable font */ |
|||
fprintf(plotfile, "/%s findfont %d scalefont setfont\n\n", |
|||
psfont, (int) (fontsize * scale)); |
|||
|
|||
graph->devdep = tmalloc(sizeof(PSdevdep)); |
|||
DEVDEP(graph).lastlinestyle = -1; |
|||
DEVDEP(graph).lastcolor = -1; |
|||
DEVDEP(graph).lastx = -1; |
|||
DEVDEP(graph).lasty = -1; |
|||
DEVDEP(graph).linecount = 0; |
|||
PS_SelectColor(0); |
|||
graph->linestyle = -1; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void |
|||
PS_Close(void) |
|||
{ |
|||
|
|||
/* in case PS_Close is called as part of an abort, |
|||
w/o having reached PS_NewViewport */ |
|||
if (plotfile) { |
|||
PS_Stroke(); |
|||
fprintf(plotfile, "showpage\n%%%%EOF\n"); |
|||
fclose(plotfile); |
|||
plotfile = NULL; |
|||
} |
|||
/* In case of hardcopy command destroy the hardcopy graph |
|||
* and reset currentgraph to graphid 1, if possible |
|||
*/ |
|||
if (!screenflag) { |
|||
DestroyGraph(hcopygraphid); |
|||
currentgraph = FindGraph(1); |
|||
} |
|||
} |
|||
|
|||
void |
|||
PS_Clear(void) |
|||
{ |
|||
|
|||
/* do nothing */ |
|||
|
|||
} |
|||
|
|||
void |
|||
PS_DrawLine(int x1, int y1, int x2, int y2) |
|||
{ |
|||
|
|||
/* note: this is not extendible to more than one graph |
|||
=> will have to give NewViewport a writeable graph XXX */ |
|||
|
|||
if (DEVDEP(currentgraph).linecount > MAX_PS_LINES |
|||
|| DEVDEP(currentgraph).linecount == 0 |
|||
|| x1 != DEVDEP(currentgraph).lastx |
|||
|| y1 != DEVDEP(currentgraph).lasty){ |
|||
PS_Stroke(); |
|||
fprintf(plotfile, "newpath\n"); |
|||
fprintf(plotfile, "%d %d moveto\n", x1 + xoff, y1 + yoff); |
|||
DEVDEP(currentgraph).linecount += 1; |
|||
} |
|||
if (x1 != x2 || y1 != y2) { |
|||
fprintf(plotfile, "%d %d lineto\n", x2 + xoff, y2 + yoff); |
|||
DEVDEP(currentgraph).linecount += 1; |
|||
} |
|||
|
|||
DEVDEP(currentgraph).lastx = x2; |
|||
DEVDEP(currentgraph).lasty = y2; |
|||
} |
|||
|
|||
void |
|||
PS_Arc(int x0, int y0, int r, double theta1, double theta2) |
|||
{ |
|||
double x1, y1; |
|||
double angle1, angle2; |
|||
PS_Stroke(); |
|||
while (theta1 >= theta2) |
|||
theta2 += 2 * M_PI; |
|||
|
|||
angle1 = (double) (RAD_TO_DEG * theta1); |
|||
angle2 = (double) (RAD_TO_DEG * theta2); |
|||
x1 = (double) x0 + r * cos(theta1); |
|||
y1 = (double) y0 + r * sin(theta1); |
|||
|
|||
fprintf(plotfile, "%f %f moveto ", x1+(double)xoff, y1+(double)yoff); |
|||
fprintf(plotfile, "%d %d %d %f %f arc\n", x0+xoff, y0+yoff, r, |
|||
angle1, angle2); |
|||
fprintf(plotfile, "stroke\n"); |
|||
|
|||
DEVDEP(currentgraph).linecount = 0; |
|||
} |
|||
|
|||
void |
|||
PS_Text(char *text, int x, int y) |
|||
{ |
|||
int savedlstyle, savedcolor; |
|||
|
|||
/* set linestyle to solid |
|||
or may get funny color text on some plotters */ |
|||
savedlstyle = currentgraph->linestyle; |
|||
savedcolor = currentgraph->currentcolor; |
|||
|
|||
PS_SetLinestyle(SOLID); |
|||
PS_SetColor(1); |
|||
|
|||
/* stroke the path if there's an open one */ |
|||
PS_Stroke(); |
|||
/* move to (x, y) */ |
|||
fprintf(plotfile, "%d %d moveto\n", x + xoff + xtadj, y + yoff + ytadj); |
|||
fprintf(plotfile, "(%s) show\n", text); |
|||
|
|||
DEVDEP(currentgraph).lastx = -1; |
|||
DEVDEP(currentgraph).lasty = -1; |
|||
|
|||
/* restore old linestyle */ |
|||
|
|||
PS_SetColor(savedcolor); |
|||
PS_SetLinestyle(savedlstyle); |
|||
} |
|||
|
|||
/* PS_DefineColor */ |
|||
/* PS_DefineLinestyle */ |
|||
|
|||
int |
|||
PS_SetLinestyle(int linestyleid) |
|||
{ |
|||
|
|||
/* special case |
|||
get it when PS_Text restores a -1 linestyle */ |
|||
if (linestyleid == -1) { |
|||
currentgraph->linestyle = -1; |
|||
return 0; |
|||
} |
|||
if (linestyleid < 0 || linestyleid > dispdev->numlinestyles) { |
|||
internalerror("bad linestyleid inside PS_SetLinestyle"); |
|||
return 0; |
|||
} |
|||
PS_LinestyleColor(linestyleid, currentgraph->currentcolor); |
|||
return 0; |
|||
} |
|||
|
|||
void |
|||
PS_SetColor(int colorid) |
|||
{ |
|||
PS_LinestyleColor(currentgraph->linestyle, colorid); |
|||
} |
|||
|
|||
void |
|||
PS_Update(void) |
|||
{ |
|||
fflush(plotfile); |
|||
} |
|||
|
|||
/**************** PRIVAT FUNCTIONS OF PS FRONTEND *****************************/ |
|||
|
|||
void |
|||
PS_SelectColor(int colorid) /* should be replaced by PS_DefineColor */ |
|||
{ |
|||
char colorN[30]="", colorstring[30]=""; |
|||
char rgb[30], s_red[30]="0x", s_green[30]="0x", s_blue[30]="0x"; |
|||
long red=0, green=0, blue=0, scale=1; |
|||
int i; |
|||
typedef struct { int red, green, blue;} COLOR; |
|||
/* duplicated colors from src/frontend/plotting/x11.c in rgb-style */ |
|||
const COLOR colors[]= {{ 0, 0, 0}, /*0: black */ |
|||
{255, 255, 255}, /*1: white */ |
|||
{255, 0, 0}, /*2: red */ |
|||
{ 0, 0, 255}, /*3: blue */ |
|||
{255, 165, 0}, /*4: orange */ |
|||
{ 0, 255, 0}, /*5: green */ |
|||
{255, 192, 203}, /*6: pink */ |
|||
{165, 42, 42}, /*7: brown */ |
|||
{240, 230, 140}, /*8: khaki */ |
|||
{221, 160, 221}, /*9: plum */ |
|||
{218, 112, 214}, /*10: orchid */ |
|||
{238, 130, 238}, /*11: violet */ |
|||
{176, 48, 96}, /*12: maroon */ |
|||
{ 64, 224, 208}, /*13: turqoise */ |
|||
{160, 82, 45}, /*14: sienna */ |
|||
{255, 127, 80}, /*15: coral */ |
|||
{ 0, 255, 255}, /*16: cyan */ |
|||
{255, 0, 255}, /*17: magenta */ |
|||
/*{255, 215, 0}, 18: gold */ |
|||
{ 96, 96, 96}, /*18: gray for smith grid */ |
|||
/*{255, 255, 0}, 19: yello */ |
|||
{150, 150, 150}, /*19: gray for smith grid */ |
|||
{128, 128, 128}}; /*20: gray for normal grid */ |
|||
|
|||
/* Extract the rgbcolor, format is: "rgb:<red>/<green>/<blue>" */ |
|||
sprintf(colorN, "color%d",colorid); |
|||
if (cp_getvar(colorN, VT_STRING, colorstring)){ |
|||
for (i=0; colorstring[i]; i++) |
|||
if (colorstring[i] == '/' || colorstring[i] == ':') |
|||
colorstring[i] = ' '; |
|||
|
|||
sscanf(colorstring,"%s %s %s %s",rgb, &(s_red[2]), &(s_green[2]), &(s_blue[2])); |
|||
|
|||
if ((strlen(s_blue) == strlen(s_red) && strlen(s_green) == strlen(s_red)) |
|||
&& (strlen(s_blue) > 2) && (strlen(s_blue) < 7)){ |
|||
sscanf(s_red,"%lx",&red); |
|||
sscanf(s_green,"%lx",&green); |
|||
sscanf(s_blue,"%lx",&blue); |
|||
scale= (1 << (strlen(s_blue) - 2) * 4) - 1; |
|||
sprintf(colorstring,"%1.3f %1.3f %1.3f", |
|||
(float) red/scale, (float) green/scale, (float) blue/scale); |
|||
strcpy(pscolor, colorstring); |
|||
} |
|||
} |
|||
if (colorid < 0 || colorid > 20) { |
|||
internalerror("bad colorid inside PS_SelectColor"); |
|||
}else if (scale == 1){ /* colorN is not an rgbstring, use default color */ |
|||
sprintf(colorstring,"%1.3f %1.3f %1.3f",colors[colorid].red/255.0, |
|||
colors[colorid].green/255.0, colors[colorid].blue/255.0) ; |
|||
strcpy(pscolor, colorstring); |
|||
} |
|||
} |
|||
|
|||
void |
|||
PS_LinestyleColor(int linestyleid, int colorid) |
|||
{ |
|||
/* we have some different linestyles and colors: |
|||
- color and linestyle we got via function call |
|||
- color and linestyle we used last time for drawing |
|||
- generated color and linestyle we'll use for drawing this time */ |
|||
/* these are the rules: |
|||
DOTTED and colored ps -> color20 (used for grid) and SOLID |
|||
color18 or 19 and black-white -> linestyle is DOTTED */ |
|||
|
|||
int gencolor=0,genstyle=0; |
|||
|
|||
if (colorflag == 1){ |
|||
genstyle = SOLID; |
|||
if (linestyleid==DOTTED) |
|||
gencolor = 20; |
|||
else |
|||
gencolor = colorid; |
|||
} else { /* colorflag == 0 -> mono*/ |
|||
if ((colorid == 18) || (colorid == 19)) |
|||
genstyle=DOTTED; |
|||
else |
|||
genstyle=linestyleid; |
|||
} |
|||
|
|||
/* change color if nessecary */ |
|||
if (colorflag == 1 && gencolor != DEVDEP(currentgraph).lastcolor){ |
|||
PS_SelectColor(gencolor); |
|||
PS_Stroke(); |
|||
fprintf(plotfile,"%s setrgbcolor\n",pscolor); |
|||
DEVDEP(currentgraph).lastcolor = gencolor; |
|||
} |
|||
currentgraph->currentcolor = colorid; |
|||
|
|||
/* change linestyle if nessecary */ |
|||
if (colorflag == 0 && genstyle != DEVDEP(currentgraph).lastlinestyle){ |
|||
PS_Stroke(); |
|||
fprintf(plotfile, "%s 0 setdash\n", linestyle[genstyle]); |
|||
DEVDEP(currentgraph).lastlinestyle= genstyle; |
|||
} |
|||
currentgraph->linestyle = linestyleid; |
|||
} |
|||
|
|||
void |
|||
PS_Stroke(void) |
|||
{ |
|||
/* strokes an open path */ |
|||
if (DEVDEP(currentgraph).linecount > 0) { |
|||
fprintf(plotfile, "stroke\n"); |
|||
DEVDEP(currentgraph).linecount = 0; |
|||
} |
|||
} |
|||
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue