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