GRASS GIS 8 Programmer's Manual 8.2.1(2023)-exported
psdriver/graph_set.c
Go to the documentation of this file.
1/*
2 * Start up graphics processing. Anything that needs to be assigned, set up,
3 * started-up, or otherwise initialized happens here. This is called only at
4 * the startup of the graphics driver.
5 *
6 * The external variables define the pixle limits of the graphics surface. The
7 * coordinate system used by the applications programs has the (0,0) origin
8 * in the upper left-hand corner. Hence,
9 * screen_left < screen_right
10 * screen_top < screen_bottom
11 */
12
13#include <string.h>
14#include <stdlib.h>
15#include <stdarg.h>
16#include <time.h>
17#include <math.h>
18#include <unistd.h>
19
20#include <grass/gis.h>
21#include <grass/glocale.h>
22#include "psdriver.h"
23
24#define DATE_FORMAT "%c"
25
26struct ps_state ps;
27
28static double width, height;
29static int landscape;
30
31struct paper
32{
33 const char *name;
34 double width, height;
35 double left, right, bot, top;
36};
37
38static const struct paper papers[] = {
39 /* name width height left right bottom top */
40 {"a4", 8.268, 11.693, 0.5, 0.5, 1.0, 1.0},
41 {"a3", 11.693, 16.535, 0.5, 0.5, 1.0, 1.0},
42 {"a2", 16.54, 23.39, 1.0, 1.0, 1.0, 1.0},
43 {"a1", 23.39, 33.07, 1.0, 1.0, 1.0, 1.0},
44 {"a0", 33.07, 46.77, 1.0, 1.0, 1.0, 1.0},
45 {"us-legal", 8.5, 14.0, 1.0, 1.0, 1.0, 1.0},
46 {"us-letter", 8.5, 11.0, 1.0, 1.0, 1.0, 1.0},
47 {"us-tabloid", 11.0, 17.0, 1.0, 1.0, 1.0, 1.0},
48 {NULL, 0, 0, 0, 0, 0, 0}
49};
50
51static void write_prolog(void)
52{
53 char prolog_file[GPATH_MAX];
54 char date_str[256];
55 FILE *prolog_fp;
56 time_t t = time(NULL);
57 struct tm *tm = localtime(&t);
58
59 strftime(date_str, sizeof(date_str), DATE_FORMAT, tm);
60
61 sprintf(prolog_file, "%s/etc/psdriver.ps", G_gisbase());
62
63 prolog_fp = fopen(prolog_file, "r");
64 if (!prolog_fp)
65 G_fatal_error("Unable to open prolog file");
66
67 if (ps.encapsulated)
68 output("%%!PS-Adobe-3.0 EPSF-3.0\n");
69 else
70 output("%%!PS-Adobe-3.0\n");
71
72 output("%%%%LanguageLevel: %d\n", 3);
73 output("%%%%Creator: GRASS PS Driver\n");
74 output("%%%%Title: %s\n", ps.outfile);
75 output("%%%%For: %s\n", G_whoami());
76 output("%%%%Orientation: %s\n", landscape ? "Landscape" : "Portrait");
77 output("%%%%BoundingBox: %d %d %d %d\n",
78 (int)floor(ps.left), (int)floor(ps.bot),
79 (int)ceil(ps.right), (int)ceil(ps.top));
80 output("%%%%CreationDate: %s\n", date_str);
81 output("%%%%EndComments\n");
82
83 output("%%%%BeginProlog\n");
84 while (!feof(prolog_fp)) {
85 char buf[256];
86
87 if (!fgets(buf, sizeof(buf), prolog_fp))
88 break;
89
90 fputs(buf, ps.tempfp);
91 }
92 output("%%%%EndProlog\n");
93
94 fclose(prolog_fp);
95}
96
97void write_setup(void)
98{
99 output("%%%%BeginSetup\n");
100
101 output("%.1f %.1f translate\n", ps.left, ps.bot);
102
103 if (landscape)
104 output("90 rotate 0 1 -1 scale\n");
105 else
106 output("0 %.1f translate 1 -1 scale\n", height);
107
108 output("%.1f %.1f BEGIN\n", width, height);
109
110 output("%%%%EndSetup\n");
111 output("%%%%Page: 1 1\n");
112}
113
114static double in2pt(double x)
115{
116 return x * 72;
117}
118
119static void swap(double *x, double *y)
120{
121 double tmp = *x;
122
123 *x = *y;
124 *y = tmp;
125}
126
127static void get_paper(void)
128{
129 const char *name = getenv("GRASS_RENDER_PS_PAPER");
130 const struct paper *paper;
131 int i;
132
133 width = screen_width;
134 height = screen_height;
135
136 ps.left = 0;
137 ps.right = width;
138 ps.bot = 0;
139 ps.top = height;
140
141 if (landscape)
142 swap(&ps.right, &ps.top);
143
144 if (!name)
145 return;
146
147 for (i = 0;; i++) {
148 paper = &papers[i];
149
150 if (!paper->name)
151 return;
152
153 if (G_strcasecmp(name, paper->name) == 0)
154 break;
155 }
156
157 ps.left = in2pt(paper->left);
158 ps.right = in2pt(paper->width) - in2pt(paper->right);
159 ps.bot = in2pt(paper->bot);
160 ps.top = in2pt(paper->height) - in2pt(paper->top);
161
162 width = ps.right - ps.left;
163 height = in2pt(paper->height) - in2pt(paper->top) - in2pt(paper->bot);
164
165 if (landscape)
166 swap(&width, &height);
167
168 ps.right = ps.left + width;
169 ps.bot = ps.top + height;
170}
171
173{
174 const char *p;
175
176 G_gisinit("PS driver");
177
178 p = getenv("GRASS_RENDER_FILE");
179 if (!p || strlen(p) == 0)
180 p = FILE_NAME;
181
182 ps.outfile = p;
183 p = ps.outfile + strlen(ps.outfile) - 4;
184 ps.encapsulated = (G_strcasecmp(p, ".eps") == 0);
185
186 p = getenv("GRASS_RENDER_TRUECOLOR");
187 ps.true_color = p && strcmp(p, "TRUE") == 0;
188
189 p = getenv("GRASS_RENDER_PS_LANDSCAPE");
190 landscape = p && strcmp(p, "TRUE") == 0;
191
192 p = getenv("GRASS_RENDER_PS_HEADER");
193 ps.no_header = p && strcmp(p, "FALSE") == 0;
194
195 p = getenv("GRASS_RENDER_PS_TRAILER");
196 ps.no_trailer = p && strcmp(p, "FALSE") == 0;
197
198 G_verbose_message(_("ps: truecolor status %s"),
199 ps.true_color ? _("enabled") : _("disabled"));
200
201 get_paper();
202
204 if (ps.no_header && access(ps.outfile, F_OK) == 0)
206
207 ps.tempfp = fopen(ps.tempfile, ps.no_header ? "a" : "w");
208
209 if (!ps.tempfp)
210 G_fatal_error("Unable to open output file: %s", ps.outfile);
211
212 if (!ps.no_header) {
213 write_prolog();
214 write_setup();
215 }
216
217 G_verbose_message(_("ps: collecting to file '%s'"), ps.outfile);
218 G_verbose_message(_("ps: image size %dx%d"),
220
221 fflush(ps.tempfp);
222
223 return 0;
224}
225
226/*!
227 \brief Get render file
228
229 \return file name
230*/
231const char *PS_Graph_get_file(void)
232{
233 return ps.outfile;
234}
235
236void output(const char *fmt, ...)
237{
238 va_list va;
239
240 va_start(va, fmt);
241 vfprintf(ps.tempfp, fmt, va);
242 va_end(va);
243}
#define NULL
Definition: ccmath.h:32
double t
int screen_height
Definition: driver/init.c:30
int screen_width
Definition: driver/init.c:29
void G_verbose_message(const char *msg,...)
Print a message to stderr but only if module is in verbose mode.
Definition: gis/error.c:109
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:160
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition: gisbase.c:41
#define FILE_NAME
Definition: htmlmap.h:9
struct tm * localtime()
const char * name
Definition: named_colr.c:7
struct ps_state ps
int PS_Graph_set(void)
void output(const char *fmt,...)
const char * PS_Graph_get_file(void)
Get render file.
#define DATE_FORMAT
void write_setup(void)
int G_rename_file(const char *oldname, const char *newname)
Rename a file or a directory in the filesystem.
Definition: rename.c:32
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower)
Definition: strings.c:47
FILE * tempfp
Definition: psdriver.h:14
double left
Definition: psdriver.h:18
int no_trailer
Definition: psdriver.h:17
int no_header
Definition: psdriver.h:17
int true_color
Definition: psdriver.h:15
double top
Definition: psdriver.h:18
int encapsulated
Definition: psdriver.h:16
double bot
Definition: psdriver.h:18
const char * outfile
Definition: psdriver.h:13
const char * tempfile
Definition: psdriver.h:13
double right
Definition: psdriver.h:18
char * G_tempfile(void)
Returns a temporary file name.
Definition: tempfile.c:62
const char * G_whoami(void)
Gets user's name.
Definition: whoami.c:35
#define x