GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
cairodriver/Graph.c
Go to the documentation of this file.
1 
15 #include "cairodriver.h"
16 
17 #if CAIRO_HAS_PS_SURFACE
18 #include <cairo-ps.h>
19 #endif
20 #if CAIRO_HAS_PDF_SURFACE
21 #include <cairo-pdf.h>
22 #endif
23 #if CAIRO_HAS_SVG_SURFACE
24 #include <cairo-svg.h>
25 #endif
26 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
27 #include <cairo-xlib.h>
28 #include <cairo-xlib-xrender.h>
29 #endif
30 
31 #include <unistd.h>
32 #ifndef __MINGW32__
33 #include <fcntl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/mman.h>
37 #endif
38 
39 #if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
40 #include <X11/X.h>
41 #include <X11/Xlib.h>
42 #include <X11/Xutil.h>
43 #endif
44 
45 /* globals */
46 char *file_name;
50 unsigned char *grid;
53 int mapped;
54 
55 /* background color */
57 
58 /* cairo objects */
59 cairo_surface_t *surface;
60 cairo_t *cairo;
61 
62 static void init_cairo(void);
63 static int ends_with(const char *string, const char *suffix);
64 static void map_file(void);
65 
66 #if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
67 static int init_xlib(void)
68 {
69  Display *dpy;
70  Drawable win;
71  unsigned long xid;
72  XVisualInfo templ;
73  XVisualInfo *vinfo;
74  int count;
75  Window root;
76  unsigned int depth;
77  int si;
78  unsigned int ui;
79  Visual *visual;
80  char *p;
81 
82  p = getenv("GRASS_CAIRO_DRAWABLE");
83  if (!p || sscanf(p, "%li", &xid) != 1)
84  G_fatal_error("invalid Drawable XID: %s", p);
85  win = xid;
86 
87  dpy = XOpenDisplay(NULL);
88  if (!dpy)
89  G_fatal_error("Unable to open display");
90 
91  p = getenv("GRASS_CAIRO_VISUAL");
92  if (!p || sscanf(p, "%li", &xid) != 1)
93  G_fatal_error("invalid Visual XID: %s", p);
94  templ.visualid = xid;
95 
96  vinfo = XGetVisualInfo(dpy, VisualIDMask, &templ, &count);
97  if (!vinfo || !count)
98  G_fatal_error("Unable to obtain visual");
99  visual = vinfo[0].visual;
100 
101  if (!XGetGeometry
102  (dpy, win, &root, &si, &si, &width, &height, &ui, &depth))
103  G_fatal_error("Unable to query drawable");
104 
105  surface = cairo_xlib_surface_create(dpy, win, visual, width, height);
106 
107  if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
108  G_fatal_error("Failed to initialize Xlib surface");
109 
110  cairo = cairo_create(surface);
111 
112  file_name = "<X11>";
114 
117 
118  return 0;
119 }
120 #endif
121 
122 static int init_file(void)
123 {
124  int do_read = 0;
125  int do_map = 0;
126  char *p;
127 
128  /* set image properties */
131  stride = width * 4;
132 
133  /* get file name */
134  p = getenv("GRASS_CAIROFILE");
135  if (!p || strlen(p) == 0)
136  p = DEFAULT_FILE_NAME;
137 
138  file_name = p;
139 
140  /* get file type (from extension) */
141  if (file_type == FTYPE_X11) ; /* skip */
142  else if (ends_with(file_name, ".ppm"))
144  else if (ends_with(file_name, ".bmp"))
146 #if CAIRO_HAS_PNG_FUNCTIONS
147  else if (ends_with(file_name, ".png"))
149 #endif
150 #if CAIRO_HAS_PDF_SURFACE
151  else if (ends_with(file_name, ".pdf"))
153 #endif
154 #if CAIRO_HAS_PS_SURFACE
155  else if (ends_with(file_name, ".ps"))
157 #endif
158 #if CAIRO_HAS_SVG_SURFACE
159  else if (ends_with(file_name, ".svg"))
161 #endif
162  else
163  G_fatal_error("Unknown file extension: %s", p);
164  G_debug(1, "File type: %s (%d)", file_name, file_type);
165 
166  switch (file_type) {
167  case FTYPE_PDF:
168  case FTYPE_PS:
169  case FTYPE_SVG:
170  is_vector = 1;
171  break;
172  }
173 
174  p = getenv("GRASS_CAIRO_MAPPED");
175  do_map = p && strcmp(p, "TRUE") == 0 && ends_with(file_name, ".bmp");
176 
177  p = getenv("GRASS_CAIRO_READ");
178  do_read = p && strcmp(p, "TRUE") == 0;
179 
180  if (is_vector) {
181  do_read = do_map = 0;
182  bgcolor_a = 1.0;
183  }
184 
185  if (do_read && access(file_name, 0) != 0)
186  do_read = 0;
187 
188  G_message
189  ("cairo: collecting to file: %s,\n GRASS_WIDTH=%d, GRASS_HEIGHT=%d",
191 
192  if (do_read && do_map)
193  map_file();
194 
195  if (!mapped && !is_vector)
196  grid = G_malloc(height * stride);
197 
198  init_cairo();
199 
200  if (!do_read && !is_vector) {
201  Cairo_Erase();
202  modified = 1;
203  }
204 
205  if (do_read && !mapped)
206  read_image();
207 
208  if (do_map && !mapped) {
209  write_image();
210  map_file();
211  init_cairo();
212  }
213 
214  return 0;
215 }
216 
217 int Cairo_Graph_set(int argc, char **argv)
218 {
219  char *p;
220 
221  G_gisinit("Cairo driver");
222  G_debug(1, "Cairo_Graph_set");
223 
224  /* get background color */
225  p = getenv("GRASS_BACKGROUNDCOLOR");
226  if (p && *p) {
227  unsigned int red, green, blue;
228 
229  if (sscanf(p, "%02x%02x%02x", &red, &green, &blue) == 3) {
230  bgcolor_r = CAIROCOLOR(red);
231  bgcolor_g = CAIROCOLOR(green);
232  bgcolor_b = CAIROCOLOR(blue);
233  }
234  else
235  G_fatal_error("Unknown background color: %s", p);
236  }
237  else
238  bgcolor_r = bgcolor_g = bgcolor_b = 1.0;
239 
240  /* get background transparency setting */
241  p = getenv("GRASS_TRANSPARENT");
242  if (p && strcmp(p, "TRUE") == 0)
243  bgcolor_a = 0.0;
244  else
245  bgcolor_a = 1.0;
246 
247  p = getenv("GRASS_AUTO_WRITE");
248  auto_write = p && strcmp(p, "TRUE") == 0;
249 
250 #if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
251  p = getenv("GRASS_CAIRO_DRAWABLE");
252  if (p)
253  return init_xlib();
254 #endif
255  return init_file();
256 }
257 
259 {
260  G_debug(1, "Cairo_Graph_close");
261 
262  write_image();
263 
264  if (cairo) {
265  cairo_destroy(cairo);
266  cairo = NULL;
267  }
268  if (surface) {
269  cairo_surface_destroy(surface);
270  surface = NULL;
271  }
272 }
273 
274 static void init_cairo(void)
275 {
276  G_debug(1, "init_cairo");
277 
278  /* create cairo surface */
279  switch (file_type) {
280  case FTYPE_PPM:
281  case FTYPE_BMP:
282  case FTYPE_PNG:
283  surface =
284  (cairo_surface_t *) cairo_image_surface_create_for_data(grid,
285  CAIRO_FORMAT_ARGB32,
286  width,
287  height,
288  stride);
289  break;
290 #if CAIRO_HAS_PDF_SURFACE
291  case FTYPE_PDF:
292  surface =
293  (cairo_surface_t *) cairo_pdf_surface_create(file_name,
294  (double)width,
295  (double)height);
296  break;
297 #endif
298 #if CAIRO_HAS_PS_SURFACE
299  case FTYPE_PS:
300  surface =
301  (cairo_surface_t *) cairo_ps_surface_create(file_name,
302  (double)width,
303  (double)height);
304  break;
305 #endif
306 #if CAIRO_HAS_SVG_SURFACE
307  case FTYPE_SVG:
308  surface =
309  (cairo_surface_t *) cairo_svg_surface_create(file_name,
310  (double)width,
311  (double)height);
312  break;
313 #endif
314  default:
315  G_fatal_error("Unknown Cairo surface type");
316  break;
317  }
318 
319  if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
320  G_fatal_error("Failed to initialize Cairo surface");
321 
322  cairo = cairo_create(surface);
323 }
324 
325 /* Returns TRUE if string ends with suffix (case insensitive) */
326 static int ends_with(const char *string, const char *suffix)
327 {
328  if (strlen(string) < strlen(suffix))
329  return FALSE;
330 
331  return G_strcasecmp(suffix,
332  string + strlen(string) - strlen(suffix)) == 0;
333 }
334 
335 static void map_file(void)
336 {
337 #ifndef __MINGW32__
338  size_t size = HEADER_SIZE + width * height * sizeof(unsigned int);
339  void *ptr;
340  int fd;
341 
342  fd = open(file_name, O_RDWR);
343  if (fd < 0)
344  return;
345 
346  ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t) 0);
347  if (ptr == MAP_FAILED)
348  return;
349 
350  if (grid) {
351  cairo_destroy(cairo);
352  cairo_surface_destroy(surface);
353  G_free(grid);
354  }
355  grid = (unsigned char *)ptr + HEADER_SIZE;
356 
357  close(fd);
358 
359  mapped = 1;
360 #endif
361 }
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower)
Definition: strings.c:192
#define FTYPE_BMP
Definition: cairodriver.h:26
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
#define HEADER_SIZE
Definition: cairodriver.h:17
#define FALSE
Definition: dbfopen.c:117
void Cairo_Graph_close(void)
FILE * fd
Definition: g3dcolor.c:368
#define CAIROCOLOR(a)
Definition: cairodriver.h:21
int modified
int is_vector
tuple width
int count
#define FTYPE_PS
Definition: cairodriver.h:29
double bgcolor_r
int screen_top
Definition: driver/init.c:35
#define FTYPE_PPM
Definition: cairodriver.h:25
#define FTYPE_X11
Definition: cairodriver.h:31
unsigned char * grid
int screen_left
Definition: driver/init.c:32
tuple size
value.Bind(wx.EVT_TEXT, self.OnVolumeIsosurfMap)
Definition: tools.py:2334
char * getenv()
int stride
double bgcolor_g
double bgcolor_b
void write_image(void)
double bgcolor_a
void G_message(const char *msg,...)
Print a message to stderr.
Definition: lib/gis/error.c:74
char * file_name
cairo_t * cairo
int screen_right
Definition: driver/init.c:33
tuple surface
Definition: tools.py:1397
#define FTYPE_PNG
Definition: cairodriver.h:27
int
Definition: g3dcolor.c:48
int auto_write
Definition: cairodriver.h:44
return NULL
Definition: dbfopen.c:1394
#define FTYPE_SVG
Definition: cairodriver.h:30
int mapped
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
#define DEFAULT_FILE_NAME
Definition: cairodriver.h:15
int screen_bottom
Definition: driver/init.c:34
int file_type
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
void Cairo_Erase(void)
#define FTYPE_PDF
Definition: cairodriver.h:28
int height
int Cairo_Graph_set(int, char **)
void read_image(void)