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 | |
31 | extern void core_loadimage_xdot(GVJ_t*, usershape_t*, boxf, boolean); |
32 | extern shape_desc *find_user_shape(char *name); |
33 | |
34 | typedef 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 | |
46 | static 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 | |
75 | static 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 | |
116 | static 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 | |
141 | static 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 */ |
151 | static 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 */ |
208 | static 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 | |
243 | static 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 | |
252 | static 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 | |
260 | void 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 | |
265 | static gvloadimage_engine_t engine_svg = { |
266 | core_loadimage_svg |
267 | }; |
268 | |
269 | static gvloadimage_engine_t engine_fig = { |
270 | core_loadimage_fig |
271 | }; |
272 | |
273 | static gvloadimage_engine_t engine_vrml = { |
274 | core_loadimage_vrml |
275 | }; |
276 | |
277 | static gvloadimage_engine_t engine_ps = { |
278 | core_loadimage_ps |
279 | }; |
280 | |
281 | static gvloadimage_engine_t engine_pslib = { |
282 | core_loadimage_pslib |
283 | }; |
284 | |
285 | static gvloadimage_engine_t engine_null = { |
286 | core_loadimage_null |
287 | }; |
288 | |
289 | static gvloadimage_engine_t engine_xdot = { |
290 | core_loadimage_xdot |
291 | }; |
292 | |
293 | static gvloadimage_engine_t engine_vml = { |
294 | core_loadimage_vml |
295 | }; |
296 | |
297 | static gvloadimage_engine_t engine_tk = { |
298 | core_loadimage_tk |
299 | }; |
300 | |
301 | gvplugin_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 | |