Graphviz  2.35.20130930.0449
gvloadimage_core.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17 
18 #include <stdlib.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #if HAVE_SYS_MMAN_H
22 #include <sys/mman.h>
23 #endif
24 #ifdef _MSC_VER
25 #include <io.h>
26 #endif
27 
28 #include "gvplugin_loadimage.h"
29 #include "agxbuf.h"
30 #include "utils.h"
31 #include "gvio.h"
32 
33 extern void core_loadimage_xdot(GVJ_t*, usershape_t*, boxf, boolean);
34 extern shape_desc *find_user_shape(char *name);
35 
36 typedef enum {
46 } format_type;
47 
48 static void core_loadimage_svg(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
49 {
50 
51 // FIXME - no idea why this magic 72/96 is needed for images! >>>
52  double width = (b.UR.x-b.LL.x)*72/96;
53  double height = (b.UR.y-b.LL.y)*72/96;
54  double originx = (b.UR.x+b.LL.x - width)/2;
55  double originy = (b.UR.y+b.LL.y + height)/2;
56 // <<<
57  assert(job);
58  assert(us);
59  assert(us->name);
60 
61  gvputs(job, "<image xlink:href=\"");
62  gvputs(job, us->name);
63  if (job->rotation) {
64 
65 // FIXME - this is messed up >>>
66  gvprintf (job, "\" width=\"%gpx\" height=\"%gpx\" preserveAspectRatio=\"xMidYMid meet\" x=\"%g\" y=\"%g\"",
67  height, width, originx, -originy);
68  gvprintf (job, " transform=\"rotate(%d %g %g)\"",
69  job->rotation, originx, -originy);
70 // <<<
71  }
72  else {
73  gvprintf (job, "\" width=\"%gpx\" height=\"%gpx\" preserveAspectRatio=\"xMinYMin meet\" x=\"%g\" y=\"%g\"",
74  width, height, originx, -originy);
75  }
76  gvputs(job, "/>\n");
77 }
78 
79 static void core_loadimage_fig(GVJ_t * job, usershape_t *us, boxf bf, boolean filled)
80 {
81  int object_code = 2; /* always 2 for polyline */
82  int sub_type = 5; /* always 5 for image */
83  int line_style = 0; /* solid, dotted, dashed */
84  int thickness = 0;
85  int pen_color = 0;
86  int fill_color = -1;
87  int depth = 1;
88  int pen_style = -1; /* not used */
89  int area_fill = 0;
90  double style_val = 0.0;
91  int join_style = 0;
92  int cap_style = 0;
93  int radius = 0;
94  int forward_arrow = 0;
95  int backward_arrow = 0;
96  int npoints = 5;
97  int flipped = 0;
98 
99  box b;
100 
101  assert(job);
102  assert(us);
103  assert(us->name);
104 
105  BF2B(bf, b);
106 
107  gvprintf(job, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n %d %s\n",
108  object_code, sub_type, line_style, thickness, pen_color,
109  fill_color, depth, pen_style, area_fill, style_val, join_style,
110  cap_style, radius, forward_arrow, backward_arrow, npoints,
111  flipped, us->name);
112  gvprintf(job," %d %d %d %d %d %d %d %d %d %d\n",
113  b.LL.x, b.LL.y,
114  b.LL.x, b.UR.y,
115  b.UR.x, b.UR.y,
116  b.UR.x, b.LL.y,
117  b.LL.x, b.LL.y);
118 }
119 
120 static void core_loadimage_vrml(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
121 {
122  obj_state_t *obj;
123  node_t *n;
124 
125  assert(job);
126  obj = job->obj;
127  assert(obj);
128  assert(us);
129  assert(us->name);
130 
131  n = job->obj->u.n;
132  assert(n);
133 
134  gvprintf(job, "Shape {\n");
135  gvprintf(job, " appearance Appearance {\n");
136  gvprintf(job, " material Material {\n");
137  gvprintf(job, " ambientIntensity 0.33\n");
138  gvprintf(job, " diffuseColor 1 1 1\n");
139  gvprintf(job, " }\n");
140  gvprintf(job, " texture ImageTexture { url \"%s\" }\n", us->name);
141  gvprintf(job, " }\n");
142  gvprintf(job, "}\n");
143 }
144 
145 static void ps_freeimage(usershape_t *us)
146 {
147 #if HAVE_SYS_MMAN_H
148  munmap(us->data, us->datasize);
149 #else
150  free(us->data);
151 #endif
152 }
153 
154 /* usershape described by a postscript file */
155 static void core_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
156 {
157  assert(job);
158  assert(us);
159  assert(us->name);
160 
161  if (us->data) {
162  if (us->datafree != ps_freeimage) {
163  us->datafree(us); /* free incompatible cache data */
164  us->data = NULL;
165  us->datafree = NULL;
166  us->datasize = 0;
167  }
168  }
169 
170  if (!us->data) { /* read file into cache */
171  int fd;
172  struct stat statbuf;
173 
174  if (!gvusershape_file_access(us))
175  return;
176  fd = fileno(us->f);
177  switch (us->type) {
178  case FT_PS:
179  case FT_EPS:
180  fstat(fd, &statbuf);
181  us->datasize = statbuf.st_size;
182 #if HAVE_SYS_MMAN_H
183  us->data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
184 #else
185  us->data = malloc(statbuf.st_size);
186  read(fd, us->data, statbuf.st_size);
187 #endif
188  us->must_inline = TRUE;
189  break;
190  default:
191  break;
192  }
193  if (us->data)
194  us->datafree = ps_freeimage;
196  }
197 
198  if (us->data) {
199  gvprintf(job, "gsave %g %g translate newpath\n",
200  b.LL.x - (double)(us->x), b.LL.y - (double)(us->y));
201  if (us->must_inline)
202  epsf_emit_body(job, us);
203  else
204  gvprintf(job, "user_shape_%d\n", us->macro_id);
205  gvprintf(job, "grestore\n");
206  }
207 }
208 
209 /* usershape described by a member of a postscript library */
210 static void core_loadimage_pslib(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
211 {
212  int i;
213  pointf AF[4];
214  shape_desc *shape;
215 
216  assert(job);
217  assert(us);
218  assert(us->name);
219 
220  if ((shape = (shape_desc*)us->data)) {
221  AF[0] = b.LL;
222  AF[2] = b.UR;
223  AF[1].x = AF[0].x;
224  AF[1].y = AF[2].y;
225  AF[3].x = AF[2].x;
226  AF[3].y = AF[0].y;
227  if (filled) {
228 // ps_begin_context();
229 // ps_set_color(S[SP].fillcolor);
230  gvprintf(job, "[ ");
231  for (i = 0; i < 4; i++)
232  gvprintf(job, "%g %g ", AF[i].x, AF[i].y);
233  gvprintf(job, "%g %g ", AF[0].x, AF[0].y);
234  gvprintf(job, "] %d true %s\n", 4, us->name);
235 // ps_end_context();
236  }
237  gvprintf(job, "[ ");
238  for (i = 0; i < 4; i++)
239  gvprintf(job, "%g %g ", AF[i].x, AF[i].y);
240  gvprintf(job, "%g %g ", AF[0].x, AF[0].y);
241  gvprintf(job, "] %d false %s\n", 4, us->name);
242  }
243 }
244 
245 static void core_loadimage_vml(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
246 {
247  unsigned int graphHeight;
248  graphHeight =(int)(job->bb.UR.y - job->bb.LL.y);
249  gvprintf (job, "<v:image src=\"%s\" style=\" position:absolute; width:%.2f; height:%.2f; left:%.2f ; top:%.2f\"",
250  us->name, b.UR.x - b.LL.x, b.UR.y - b.LL.y, b.LL.x, graphHeight-b.UR.y);
251  gvputs(job, " />\n");
252 }
253 
254 static void core_loadimage_tk(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
255 {
256  gvprintf (job, "image create photo \"photo_%s\" -file \"%s\"\n",
257  us->name, us->name);
258  gvprintf (job, "$c create image %.2f %.2f -image \"photo_%s\"\n",
259  us->name, (b.UR.x + b.LL.x) / 2, (b.UR.y + b.LL.y) / 2);
260 }
261 
262 void core_loadimage_null(GVJ_t *gvc, usershape_t *us, boxf b, boolean filled)
263 {
264  /* null function - basically suppress the missing loader message */
265 }
266 
267 static gvloadimage_engine_t engine_svg = {
268  core_loadimage_svg
269 };
270 
271 static gvloadimage_engine_t engine_fig = {
272  core_loadimage_fig
273 };
274 
275 static gvloadimage_engine_t engine_vrml = {
276  core_loadimage_vrml
277 };
278 
279 static gvloadimage_engine_t engine_ps = {
280  core_loadimage_ps
281 };
282 
283 static gvloadimage_engine_t engine_pslib = {
284  core_loadimage_pslib
285 };
286 
287 static gvloadimage_engine_t engine_null = {
289 };
290 
291 static gvloadimage_engine_t engine_xdot = {
293 };
294 
295 static gvloadimage_engine_t engine_vml = {
296  core_loadimage_vml
297 };
298 
299 static gvloadimage_engine_t engine_tk = {
300  core_loadimage_tk
301 };
302 
304  {FORMAT_PNG_SVG, "png:svg", 1, &engine_svg, NULL},
305  {FORMAT_GIF_SVG, "gif:svg", 1, &engine_svg, NULL},
306  {FORMAT_JPEG_SVG, "jpeg:svg", 1, &engine_svg, NULL},
307  {FORMAT_JPEG_SVG, "jpe:svg", 1, &engine_svg, NULL},
308  {FORMAT_JPEG_SVG, "jpg:svg", 1, &engine_svg, NULL},
309 
310  {FORMAT_PNG_FIG, "png:fig", 1, &engine_fig, NULL},
311  {FORMAT_GIF_FIG, "gif:fig", 1, &engine_fig, NULL},
312  {FORMAT_JPEG_FIG, "jpeg:fig", 1, &engine_fig, NULL},
313  {FORMAT_JPEG_FIG, "jpe:fig", 1, &engine_fig, NULL},
314  {FORMAT_JPEG_FIG, "jpg:fig", 1, &engine_fig, NULL},
315 
316  {FORMAT_PNG_VRML, "png:vrml", 1, &engine_vrml, NULL},
317  {FORMAT_GIF_VRML, "gif:vrml", 1, &engine_vrml, NULL},
318  {FORMAT_JPEG_VRML, "jpeg:vrml", 1, &engine_vrml, NULL},
319  {FORMAT_JPEG_VRML, "jpe:vrml", 1, &engine_vrml, NULL},
320  {FORMAT_JPEG_VRML, "jpg:vrml", 1, &engine_vrml, NULL},
321 
322  {FORMAT_PS_PS, "eps:ps", 1, &engine_ps, NULL},
323  {FORMAT_PS_PS, "ps:ps", 1, &engine_ps, NULL},
324  {FORMAT_PSLIB_PS, "(lib):ps", 1, &engine_pslib, NULL}, /* for pslib */
325 
326  {FORMAT_PNG_MAP, "png:map", 1, &engine_null, NULL},
327  {FORMAT_GIF_MAP, "gif:map", 1, &engine_null, NULL},
328  {FORMAT_JPEG_MAP, "jpeg:map", 1, &engine_null, NULL},
329  {FORMAT_JPEG_MAP, "jpe:map", 1, &engine_null, NULL},
330  {FORMAT_JPEG_MAP, "jpg:map", 1, &engine_null, NULL},
331  {FORMAT_PS_MAP, "ps:map", 1, &engine_null, NULL},
332  {FORMAT_PS_MAP, "eps:map", 1, &engine_null, NULL},
333  {FORMAT_SVG_MAP, "svg:map", 1, &engine_null, NULL},
334 
335  {FORMAT_PNG_DOT, "png:dot", 1, &engine_null, NULL},
336  {FORMAT_GIF_DOT, "gif:dot", 1, &engine_null, NULL},
337  {FORMAT_JPEG_DOT, "jpeg:dot", 1, &engine_null, NULL},
338  {FORMAT_JPEG_DOT, "jpe:dot", 1, &engine_null, NULL},
339  {FORMAT_JPEG_DOT, "jpg:dot", 1, &engine_null, NULL},
340  {FORMAT_PS_DOT, "ps:dot", 1, &engine_null, NULL},
341  {FORMAT_PS_DOT, "eps:dot", 1, &engine_null, NULL},
342  {FORMAT_SVG_DOT, "svg:dot", 1, &engine_null, NULL},
343 
344  {FORMAT_PNG_XDOT, "png:xdot", 1, &engine_xdot, NULL},
345  {FORMAT_GIF_XDOT, "gif:xdot", 1, &engine_xdot, NULL},
346  {FORMAT_JPEG_XDOT, "jpeg:xdot", 1, &engine_xdot, NULL},
347  {FORMAT_JPEG_XDOT, "jpe:xdot", 1, &engine_xdot, NULL},
348  {FORMAT_JPEG_XDOT, "jpg:xdot", 1, &engine_xdot, NULL},
349  {FORMAT_PS_XDOT, "ps:xdot", 1, &engine_xdot, NULL},
350  {FORMAT_PS_XDOT, "eps:xdot", 1, &engine_xdot, NULL},
351  {FORMAT_SVG_XDOT, "svg:xdot", 1, &engine_xdot, NULL},
352 
353  {FORMAT_SVG_SVG, "svg:svg", 1, &engine_svg, NULL},
354 
355  {FORMAT_PNG_VML, "png:vml", 1, &engine_vml, NULL},
356  {FORMAT_GIF_VML, "gif:vml", 1, &engine_vml, NULL},
357  {FORMAT_JPEG_VML, "jpeg:vml", 1, &engine_vml, NULL},
358  {FORMAT_JPEG_VML, "jpe:vml", 1, &engine_vml, NULL},
359  {FORMAT_JPEG_VML, "jpg:vml", 1, &engine_vml, NULL},
360 
361  {FORMAT_GIF_TK, "gif:tk", 1, &engine_tk, NULL},
362 
363  {0, NULL, 0, NULL, NULL}
364 };