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