1 /*!
2 \file lib/display/r_raster.c
3
4 \brief Display Library - Raster graphics subroutines
5
6 (C) 2001-2015 by the GRASS Development Team
7
8 This program is free software under the GNU General Public License
9 (>=v2). Read the file COPYING that comes with GRASS for details.
10
11 \author Original author CERL
12 \author Monitors support by Martin Landa <landa.martin gmail.com>
13 */
14
15 #include <grass/config.h>
16
17 #include <errno.h>
18 #include <signal.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23
24 #include <grass/gis.h>
25 #include <grass/glocale.h>
26 #include <grass/display.h>
27 #include <grass/spawn.h>
28
29 #include "driver.h"
30
31 extern const struct driver *PNG_Driver(void);
32 extern const struct driver *PS_Driver(void);
33 extern const struct driver *HTML_Driver(void);
34 #ifdef USE_CAIRO
35 extern const struct driver *Cairo_Driver(void);
36 #endif
37
38 static struct {
39 double t, b, l, r;
40 } screen, frame;
41
init(void)42 static void init(void)
43 {
44 const char *fenc = getenv("GRASS_ENCODING");
45 const char *font = getenv("GRASS_FONT");
46 const char *line_width = getenv("GRASS_RENDER_LINE_WIDTH");
47 const char *text_size = getenv("GRASS_RENDER_TEXT_SIZE");
48 const char *frame_str = getenv("GRASS_RENDER_FRAME");
49
50 D_font(font ? font : "romans");
51
52 if (fenc)
53 D_encoding(fenc);
54
55 if (line_width)
56 COM_Line_width(atof(line_width));
57
58 if (text_size) {
59 double s = atof(text_size);
60 D_text_size(s, s);
61 }
62
63 D_text_rotation(0);
64
65 COM_Get_window(&screen.t, &screen.b, &screen.l, &screen.r);
66 if (frame_str) {
67 sscanf(frame_str, "%lf,%lf,%lf,%lf", &frame.t, &frame.b, &frame.l, &frame.r);
68 COM_Set_window(frame.t, frame.b, frame.l, frame.r);
69 }
70 else
71 frame = screen;
72 }
73
74 /*!
75 \brief Open display driver
76
77 Default display driver is Cairo, if not available PNG is used.
78
79 \return 0 on success
80 */
D_open_driver(void)81 int D_open_driver(void)
82 {
83 const char *p, *c, *m;
84 const struct driver *drv;
85
86 G_debug(1, "D_open_driver():");
87 p = getenv("GRASS_RENDER_IMMEDIATE");
88 c = getenv("GRASS_RENDER_COMMAND");
89 m = G_getenv_nofatal("MONITOR");
90
91 if (!p && (m || c)) {
92 char *cmd;
93 char progname[GPATH_MAX];
94
95 cmd = G_recreate_command();
96
97 if (c && m) {
98 G_warning(_("Both %s and %s are defined. "
99 "%s will be ignored."),
100 "GRASS_RENDER_COMMAND", "MONITOR",
101 "MONITOR");
102 m = NULL;
103 }
104
105 if (c)
106 sprintf(progname, "%s", c);
107 else { /* monitors managed by d.mon -> call default renderer */
108 char element[GPATH_MAX];
109
110 G_temp_element(element);
111 strcat(element, "/");
112 strcat(element, "MONITORS");
113 strcat(element, "/");
114 strcat(element, m);
115 G_file_name(progname, element, "render.py", G_mapset());
116 }
117
118 G_debug(1, "rendering redirected to %s", progname);
119 /* assuming Python script here (could be extended in the future) */
120 G_spawn_ex(getenv("GRASS_PYTHON"), getenv("GRASS_PYTHON"), progname,
121 cmd, NULL);
122
123 G_free(cmd);
124
125 /* force exiting GRASS command, leave rendering on
126 * GRASS_RENDER_COMMAND program */
127 exit(0);
128 }
129
130 if (!p)
131 G_fatal_error(_("Neither %s (managed by d.mon command) nor %s "
132 "(used for direct rendering) defined"),
133 "MONITOR", "GRASS_RENDER_IMMEDIATE");
134
135 if (p && G_strcasecmp(p, "default") == 0)
136 p = NULL;
137
138 drv =
139 (p && G_strcasecmp(p, "png") == 0) ? PNG_Driver() :
140 (p && G_strcasecmp(p, "ps") == 0) ? PS_Driver() :
141 (p && G_strcasecmp(p, "html") == 0) ? HTML_Driver() :
142 #ifdef USE_CAIRO
143 (p && G_strcasecmp(p, "cairo") == 0) ? Cairo_Driver() :
144 Cairo_Driver();
145 #else
146 PNG_Driver();
147 #endif
148
149 if (p && G_strcasecmp(drv->name, p) != 0)
150 G_warning(_("Unknown display driver <%s>"), p);
151 G_verbose_message(_("Using display driver <%s>..."), drv->name);
152 LIB_init(drv);
153
154 init();
155
156 return 0;
157 }
158
159 /*!
160 \brief Close display driver
161
162 If GRASS_NOTIFY is defined, run notifier.
163 */
D_close_driver(void)164 void D_close_driver(void)
165 {
166 const char *cmd = getenv("GRASS_NOTIFY");
167
168 COM_Graph_close();
169
170 if (cmd)
171 system(cmd);
172 }
173
174 /*!
175 \brief Append command to the cmd file (unused)
176
177 \todo To be removed
178 */
D_save_command(const char * cmd)179 int D_save_command(const char *cmd)
180 {
181 return 0;
182 }
183
184 /*!
185 \brief Erase display (internal use only)
186 */
D__erase(void)187 void D__erase(void)
188 {
189 COM_Erase();
190 }
191
192 /*!
193 \brief Set text size (width and height)
194
195 \param width text pixel width
196 \param height text pixel height
197 */
D_text_size(double width,double height)198 void D_text_size(double width, double height)
199 {
200 COM_Text_size(width, height);
201 }
202
203 /*!
204 \brief Set text rotation
205
206 \param rotation value
207 */
D_text_rotation(double rotation)208 void D_text_rotation(double rotation)
209 {
210 COM_Text_rotation(rotation);
211 }
212
213 /*!
214 \brief Draw text
215
216 Writes <em>text</em> in the current color and font, at the current text
217 width and height, starting at the current screen location.
218
219 \param text text to be drawn
220 */
D_text(const char * text)221 void D_text(const char *text)
222 {
223 COM_Text(text);
224 }
225
226 /*!
227 \brief Choose font
228
229 Set current font to <em>font name</em>.
230
231 \param name font name
232 */
D_font(const char * name)233 void D_font(const char *name)
234 {
235 COM_Set_font(name);
236 }
237
238 /*!
239 \brief Set encoding
240
241 \param name encoding name
242 */
D_encoding(const char * name)243 void D_encoding(const char *name)
244 {
245 COM_Set_encoding(name);
246 }
247
248 /*!
249 \brief Get font list
250
251 \param[out] list list of font names
252 \param[out] number of items in the list
253 */
D_font_list(char *** list,int * count)254 void D_font_list(char ***list, int *count)
255 {
256 COM_Font_list(list, count);
257 }
258
259 /*!
260 \brief Get font info
261
262 \param[out] list list of font info
263 \param[out] number of items in the list
264 */
D_font_info(char *** list,int * count)265 void D_font_info(char ***list, int *count)
266 {
267 COM_Font_info(list, count);
268 }
269
270 /*!
271 * \brief get graphical clipping window
272 *
273 * Queries the graphical clipping window (origin is top right)
274 *
275 * \param[out] t top edge of clip window
276 * \param[out] b bottom edge of clip window
277 * \param[out] l left edge of clip window
278 * \param[out] r right edge of clip window
279 * \return ~
280 */
281
D_get_clip_window(double * t,double * b,double * l,double * r)282 void D_get_clip_window(double *t, double *b, double *l, double *r)
283 {
284 COM_Get_window(t, b, l, r);
285 }
286
287 /*!
288 * \brief set graphical clipping window
289 *
290 * Sets the graphical clipping window to the specified rectangle
291 * (origin is top right)
292 *
293 * \param t top edge of clip window
294 * \param b bottom edge of clip window
295 * \param l left edge of clip window
296 * \param r right edge of clip window
297 * \return ~
298 */
299
D_set_clip_window(double t,double b,double l,double r)300 void D_set_clip_window(double t, double b, double l, double r)
301 {
302 if (t < frame.t) t = frame.t;
303 if (b > frame.b) b = frame.b;
304 if (l < frame.l) l = frame.l;
305 if (r > frame.r) r = frame.r;
306
307 COM_Set_window(t, b, l, r);
308 }
309
310 /*!
311 * \brief get graphical window (frame)
312 *
313 * Queries the graphical frame (origin is top right)
314 *
315 * \param[out] t top edge of frame
316 * \param[out] b bottom edge of frame
317 * \param[out] l left edge of frame
318 * \param[out] r right edge of frame
319 * \return ~
320 */
321
D_get_frame(double * t,double * b,double * l,double * r)322 void D_get_frame(double *t, double *b, double *l, double *r)
323 {
324 *t = frame.t;
325 *b = frame.b;
326 *l = frame.l;
327 *r = frame.r;
328 }
329
330 /*!
331 * \brief get screen bounds
332 *
333 * Queries the screen bounds (origin is top right)
334 *
335 * \param[out] t top edge of screen
336 * \param[out] b bottom edge of screen
337 * \param[out] l left edge of screen
338 * \param[out] r right edge of screen
339 * \return ~
340 */
341
D_get_screen(double * t,double * b,double * l,double * r)342 void D_get_screen(double *t, double *b, double *l, double *r)
343 {
344 *t = screen.t;
345 *b = screen.b;
346 *l = screen.l;
347 *r = screen.r;
348 }
349
350 /*!
351 * \brief set graphical clipping window to map window
352 *
353 * Sets the graphical clipping window to the pixel window that corresponds
354 * to the current database region.
355 *
356 * \param ~
357 * \return ~
358 */
359
D_set_clip_window_to_map_window(void)360 void D_set_clip_window_to_map_window(void)
361 {
362 D_set_clip_window(
363 D_get_d_north(), D_get_d_south(),
364 D_get_d_west(), D_get_d_east());
365 }
366
367 /*!
368 * \brief set clipping window to screen window
369 *
370 * Sets the clipping window to the pixel window that corresponds to the
371 * full screen window. Off screen rendering is still clipped.
372 *
373 * \param ~
374 * \return ~
375 */
376
D_set_clip_window_to_screen_window(void)377 void D_set_clip_window_to_screen_window(void)
378 {
379 COM_Set_window(frame.t, frame.b, frame.l, frame.r);
380 }
381
382