Graphviz  2.41.20170921.2350
gvloadimage_rsvg.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 #include "config.h"
15 
16 #include <stdlib.h>
17 #include <sys/stat.h>
18 
19 #include "gvplugin_loadimage.h"
20 
21 #ifdef HAVE_PANGOCAIRO
22 #ifdef HAVE_RSVG
23 #include <librsvg/rsvg.h>
24 #ifndef RSVG_CAIRO_H
25 #include <librsvg/rsvg-cairo.h>
26 #endif
27 #include <cairo/cairo-svg.h>
28 
29 #ifdef _WIN32
30 #define NUL_FILE "nul"
31 #else
32 #define NUL_FILE "/dev/null"
33 #endif
34 
35 typedef enum {
36  FORMAT_SVG_CAIRO,
37 } format_type;
38 
39 
40 static void gvloadimage_rsvg_free(usershape_t *us)
41 {
42  rsvg_handle_close((RsvgHandle*)us->data, NULL);
43 }
44 
45 static RsvgHandle* gvloadimage_rsvg_load(GVJ_t * job, usershape_t *us)
46 {
47  RsvgHandle* rsvgh = NULL;
48  guchar *fileBuf = NULL;
49  GError *err = NULL;
50  gsize fileSize;
51  gint result;
52 
53  int fd;
54  struct stat stbuf;
55 
56  assert(job);
57  assert(us);
58  assert(us->name);
59 
60  if (us->data) {
61  if (us->datafree == gvloadimage_rsvg_free)
62  rsvgh = (RsvgHandle*)(us->data); /* use cached data */
63  else {
64  us->datafree(us); /* free incompatible cache data */
65  us->data = NULL;
66  }
67 
68  }
69 
70  if (!rsvgh) { /* read file into cache */
71  if (!gvusershape_file_access(us))
72  return NULL;
73  switch (us->type) {
74  case FT_SVG:
75 
76 
77 #if HAVE_G_TYPE_INIT
78 /* g_type_init() was deprecated in glib 2.36.0 */
79 #if !GLIB_CHECK_VERSION (2, 36, 0)
80  g_type_init();
81 #endif
82 #else
83  rsvg_init();
84 #endif
85 
86  rsvgh = rsvg_handle_new();
87 
88  if (rsvgh == NULL) {
89  fprintf(stderr, "rsvg_handle_new_from_file returned an error: %s\n", err->message);
90 #if HAVE_G_TYPE_TERM
91  g_type_term();
92 #else
93 #ifndef HAVE_SVG_2_36
94  rsvg_term();
95 #endif
96 #endif
97  return NULL;
98  }
99 
100  fd = fileno(us->f);
101  fstat(fd, &stbuf);
102  fileSize = stbuf.st_size;
103 
104  fileBuf = calloc(fileSize + 1, sizeof(guchar));
105 
106  if (fileBuf == NULL) {
107 #if HAVE_G_OBJECT_UNREF
108  g_object_unref(rsvgh);
109 #else
110  rsvg_handle_free(rsvgh);
111 #endif
112 #if HAVE_G_TYPE_TERM
113  g_type_term();
114 #else
115 #ifndef HAVE_SVG_2_36
116  rsvg_term();
117 #endif
118 #endif
119  return NULL;
120  }
121 
122  rewind(us->f);
123 
124  if ((result = fread(fileBuf, 1, fileSize, us->f)) < fileSize) {
125  free(fileBuf);
126 #if HAVE_G_OBJECT_UNREF
127  g_object_unref(rsvgh);
128 #else
129  rsvg_handle_free(rsvgh);
130 #endif
131 #if HAVE_G_TYPE_TERM
132  g_type_term();
133 #else
134 #ifndef HAVE_SVG_2_36
135  rsvg_term();
136 #endif
137 #endif
138  return NULL;
139  }
140 
141  if (rsvg_handle_write(rsvgh, (const guchar *)fileBuf, (gsize)fileSize, &err) == FALSE) {
142  fprintf(stderr, "rsvg_handle_write returned an error: %s\n", err->message);
143  free(fileBuf);
144 #if HAVE_G_OBJECT_UNREF
145  g_object_unref(rsvgh);
146 #else
147  rsvg_handle_free(rsvgh);
148 #endif
149 #if HAVE_G_TYPE_TERM
150  g_type_term();
151 #else
152 #ifndef HAVE_SVG_2_36
153  rsvg_term();
154 #endif
155 #endif
156  return NULL;
157  }
158 
159  free(fileBuf);
160 
161  rsvg_handle_close(rsvgh, &err);
162  rsvg_handle_set_dpi(rsvgh, POINTS_PER_INCH);
163 
164  break;
165  default:
166  rsvgh = NULL;
167  }
168 
169  if (rsvgh) {
170  us->data = (void*)rsvgh;
171  us->datafree = gvloadimage_rsvg_free;
172  }
173 
175  }
176 
177  return rsvgh;
178 }
179 
180 static void gvloadimage_rsvg_cairo(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
181 {
182  RsvgHandle* rsvgh = gvloadimage_rsvg_load(job, us);
183 
184  cairo_t *cr = (cairo_t *) job->context; /* target context */
185  cairo_surface_t *surface; /* source surface */
186 
187  if (rsvgh) {
188  cairo_save(cr);
189 
190  surface = cairo_svg_surface_create(NUL_FILE, us->w, us->h);
191 
192  cairo_surface_reference(surface);
193 
194  cairo_set_source_surface(cr, surface, 0, 0);
195  cairo_translate(cr, b.LL.x, -b.UR.y);
196  cairo_scale(cr, (b.UR.x - b.LL.x)/(us->w), (b.UR.y - b.LL.y)/(us->h));
197  rsvg_handle_render_cairo(rsvgh, cr);
198 
199  cairo_paint (cr);
200  cairo_restore(cr);
201  }
202 }
203 
204 static gvloadimage_engine_t engine_cairo = {
205  gvloadimage_rsvg_cairo
206 };
207 #endif
208 #endif
209 
211 #ifdef HAVE_PANGOCAIRO
212 #ifdef HAVE_RSVG
213  {FORMAT_SVG_CAIRO, "svg:cairo", 1, &engine_cairo, NULL},
214 #endif
215 #endif
216  {0, NULL, 0, NULL, NULL}
217 };
void(* datafree)(usershape_t *us)
Definition: usershape.h:63
void * context
Definition: gvcjob.h:304
#define assert(x)
Definition: cghdr.h:47
void * data
Definition: usershape.h:61
Definition: gvcjob.h:271
#define POINTS_PER_INCH
Definition: geom.h:62
boolean gvusershape_file_access(usershape_t *us)
Definition: gvusershape.c:584
FILE * f
Definition: usershape.h:57
double y
Definition: geom.h:28
imagetype_t type
Definition: usershape.h:58
void gvusershape_file_release(usershape_t *us)
Definition: gvusershape.c:618
if(aagss+aagstacksize-1<=aagssp)
Definition: grammar.c:1332
format_type
#define NULL
Definition: logic.h:39
double x
Definition: geom.h:28
pointf LL
Definition: geom.h:35
const char * name
Definition: usershape.h:53
pointf UR
Definition: geom.h:35
gvplugin_installed_t gvloadimage_rsvg_types[]
Definition: geom.h:35
#define FALSE
Definition: cgraph.h:35