Lumiera  0.pre.03
»edit your freedom«
rsvg-convert.c
Go to the documentation of this file.
1 /*
2  rsvg-convert.c - Command line utility for exercising rsvg with cairo.
3 
4  Copyright (C) Red Hat, Inc.
5  2005, Carl Worth <cworth@cworth.org>
6  Caleb Moore <c.moore@student.unsw.edu.au>
7  Dom Lachowicz <cinamod@hotmail.com>
8  2008, Joel Holdsworth <joel@airwebreathe.org.uk>
9 
10  This program is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License as
12  published by the Free Software Foundation; either version 2 of
13  the License, or (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 
24 * *****************************************************/
25 
26 
35 #ifndef N_
36 #define N_(X) X
37 #endif
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <locale.h>
43 
44 #include <librsvg/rsvg.h>
45 #include <librsvg/rsvg-cairo.h>
46 
47 
48 #ifdef CAIRO_HAS_PS_SURFACE
49  #include <cairo-ps.h>
50 #endif
51 
52 #ifdef CAIRO_HAS_PDF_SURFACE
53  #include <cairo-pdf.h>
54 #endif
55 
56 #ifdef CAIRO_HAS_SVG_SURFACE
57  #include <cairo-svg.h>
58 #endif
59 
60 #ifndef _
61  #define _(X) X
62 #endif
63 
64 
66  {
67  gint width;
68  gint height;
69  };
70 
72  {
73  double left;
74  double top;
75  double width;
76  double height;
77  };
78 
79 
80 static void
81 display_error (GError * err)
82 {
83  if (err)
84  {
85  g_print ("%s\n", err->message);
86  g_error_free (err);
87  }
88 }
89 
90 
91 static void
92 rsvg_cairo_size_callback (int *width, int *height, gpointer data)
93 {
94  RsvgDimensionData *dimensions = data;
95  *width = dimensions->width;
96  *height = dimensions->height;
97 }
98 
99 
100 static cairo_status_t
101 rsvg_cairo_write_func (void *closure, const unsigned char *data, unsigned int length)
102 {
103  if (fwrite (data, 1, length, (FILE *) closure) == length)
104  return CAIRO_STATUS_SUCCESS;
105  return CAIRO_STATUS_WRITE_ERROR;
106 }
107 
108 
109 int
110 main (int argc, char **argv)
111 {
112  GOptionContext *g_option_context;
113  int width = -1;
114  int height = -1;
115  char *source_rect_string = NULL;
116  char *output = NULL;
117  GError *error = NULL;
118  char *filename = NULL;
119 
120  char **args = NULL;
121  RsvgHandle *rsvg;
122  cairo_surface_t *surface = NULL;
123  cairo_t *cr = NULL;
124  RsvgDimensionData dimensions;
125  FILE *output_file = stdout;
126 
127  struct RsvgSourceRectangle source_rect = {0, 0, 0, 0};
128 
129  GOptionEntry options_table[] = {
130  {"width", 'w', 0, G_OPTION_ARG_INT, &width,
131  N_("width [optional; defaults to the SVG's width]"), N_("<int>")},
132  {"height", 'h', 0, G_OPTION_ARG_INT, &height,
133  N_("height [optional; defaults to the SVG's height]"), N_("<int>")},
134  {"source-rect", 'r', 0, G_OPTION_ARG_STRING, &source_rect_string,
135  N_("source rectangle [optional; defaults to rectangle of the SVG document]"), N_("left:top:width:height")},
136  {"output", 'o', 0, G_OPTION_ARG_STRING, &output,
137  N_("output filename"), NULL},
138  {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &args, NULL, N_("FILE")},
139  {NULL}
140  };
141 
142  /* Set the locale so that UTF-8 filenames work */
143  setlocale (LC_ALL, "");
144 
145  g_option_context = g_option_context_new (_("- SVG Converter"));
146  g_option_context_add_main_entries (g_option_context, options_table, NULL);
147  g_option_context_set_help_enabled (g_option_context, TRUE);
148  if (!g_option_context_parse (g_option_context, &argc, &argv, &error))
149  {
150  display_error (error);
151  exit (1);
152  }
153 
154  g_option_context_free (g_option_context);
155 
156  if (output != NULL)
157  {
158  output_file = fopen (output, "wb");
159  if (!output_file)
160  {
161  fprintf (stderr, _("Error saving to file: %s\n"), output);
162  exit (1);
163  }
164  }
165 
166  if (args[0] != NULL)
167  filename = args[0];
168 
169  /* Parse the source rect */
170  if(source_rect_string != NULL)
171  {
172  const int n = sscanf(source_rect_string, "%lg:%lg:%lg:%lg",
173  &source_rect.left, &source_rect.top,
174  &source_rect.width, &source_rect.height);
175  if (n != 4 || source_rect.width <= 0.0 || source_rect.height < 0.0)
176  {
177  fprintf (stderr, _("Invalid source rect: %s\n"), source_rect_string);
178  exit(1);
179  }
180  }
181 
182  rsvg_init ();
183 
184  rsvg = rsvg_handle_new_from_file (filename, &error);
185 
186  if (!rsvg)
187  {
188  fprintf (stderr, _("Error reading SVG:"));
189  display_error (error);
190  fprintf (stderr, "\n");
191  exit (1);
192  }
193 
194  /* if the user did not specify a source rectangle, get the page size from the SVG */
195  if(source_rect_string == NULL)
196  {
197  rsvg_handle_set_size_callback (rsvg, rsvg_cairo_size_callback, &dimensions, NULL);
198  source_rect.left = 0;
199  source_rect.top = 0;
200  source_rect.width = dimensions.width;
201  source_rect.height = dimensions.height;
202  }
203 
204  rsvg_handle_get_dimensions (rsvg, &dimensions);
205 
206  if (width != -1 && height != -1)
207  {
208  dimensions.width = width;
209  dimensions.height = height;
210  }
211  else if(source_rect_string != NULL)
212  {
213  dimensions.width = source_rect.width;
214  dimensions.height = source_rect.height;
215  }
216 
217  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
218  dimensions.width,
219  dimensions.height);
220 
221  cr = cairo_create (surface);
222 
223  cairo_translate (cr, -source_rect.left, -source_rect.top);
224 
225  if (width != -1 && height != -1 && source_rect_string != NULL)
226  {
227  cairo_scale (cr,
228  (double)dimensions.width / (double)source_rect.width,
229  (double)dimensions.height / (double)source_rect.height);
230  }
231 
232  rsvg_handle_render_cairo (rsvg, cr);
233 
234  cairo_surface_write_to_png_stream (surface, rsvg_cairo_write_func, output_file);
235 
236  g_object_unref (G_OBJECT (rsvg));
237 
238  cairo_destroy (cr);
239  cairo_surface_destroy (surface);
240 
241  fclose (output_file);
242 
243  rsvg_term ();
244 
245  return 0;
246 }
int main(int argc, const char *argv[])
run all tests or any single test specified in the first command line argument.
Definition: testrunner.cpp:47