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   **Lumiera** is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2 of the License, or (at your
13   option) any later version. See the file COPYING for further details.
14 
15 * *****************************************************************/
16 
17 
26 #ifndef N_
27 #define N_(X) X
28 #endif
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <locale.h>
34 
35 #include <librsvg/rsvg.h>
36 #include <librsvg/rsvg-cairo.h>
37 
38 
39 #ifdef CAIRO_HAS_PS_SURFACE
40  #include <cairo-ps.h>
41 #endif
42 
43 #ifdef CAIRO_HAS_PDF_SURFACE
44  #include <cairo-pdf.h>
45 #endif
46 
47 #ifdef CAIRO_HAS_SVG_SURFACE
48  #include <cairo-svg.h>
49 #endif
50 
51 #ifndef _
52  #define _(X) X
53 #endif
54 
55 
57  {
58  gint width;
59  gint height;
60  };
61 
63  {
64  double left;
65  double top;
66  double width;
67  double height;
68  };
69 
70 
71 static void
72 display_error (GError * err)
73 {
74  if (err)
75  {
76  g_print ("%s\n", err->message);
77  g_error_free (err);
78  }
79 }
80 
81 
82 static void
83 rsvg_cairo_size_callback (int *width, int *height, gpointer data)
84 {
85  RsvgDimensionData *dimensions = data;
86  *width = dimensions->width;
87  *height = dimensions->height;
88 }
89 
90 
91 static cairo_status_t
92 rsvg_cairo_write_func (void *closure, const unsigned char *data, unsigned int length)
93 {
94  if (fwrite (data, 1, length, (FILE *) closure) == length)
95  return CAIRO_STATUS_SUCCESS;
96  return CAIRO_STATUS_WRITE_ERROR;
97 }
98 
99 
100 int
101 main (int argc, char **argv)
102 {
103  GOptionContext *g_option_context;
104  int width = -1;
105  int height = -1;
106  char *source_rect_string = NULL;
107  char *output = NULL;
108  GError *error = NULL;
109  char *filename = NULL;
110 
111  char **args = NULL;
112  RsvgHandle *rsvg;
113  cairo_surface_t *surface = NULL;
114  cairo_t *cr = NULL;
115  RsvgDimensionData dimensions;
116  FILE *output_file = stdout;
117 
118  struct RsvgSourceRectangle source_rect = {0, 0, 0, 0};
119 
120  GOptionEntry options_table[] = {
121  {"width", 'w', 0, G_OPTION_ARG_INT, &width,
122  N_("width [optional; defaults to the SVG's width]"), N_("<int>")},
123  {"height", 'h', 0, G_OPTION_ARG_INT, &height,
124  N_("height [optional; defaults to the SVG's height]"), N_("<int>")},
125  {"source-rect", 'r', 0, G_OPTION_ARG_STRING, &source_rect_string,
126  N_("source rectangle [optional; defaults to rectangle of the SVG document]"), N_("left:top:width:height")},
127  {"output", 'o', 0, G_OPTION_ARG_STRING, &output,
128  N_("output filename"), NULL},
129  {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &args, NULL, N_("FILE")},
130  {NULL}
131  };
132 
133  /* Set the locale so that UTF-8 filenames work */
134  setlocale (LC_ALL, "");
135 
136  g_option_context = g_option_context_new (_("- SVG Converter"));
137  g_option_context_add_main_entries (g_option_context, options_table, NULL);
138  g_option_context_set_help_enabled (g_option_context, TRUE);
139  if (!g_option_context_parse (g_option_context, &argc, &argv, &error))
140  {
141  display_error (error);
142  exit (1);
143  }
144 
145  g_option_context_free (g_option_context);
146 
147  if (output != NULL)
148  {
149  output_file = fopen (output, "wb");
150  if (!output_file)
151  {
152  fprintf (stderr, _("Error saving to file: %s\n"), output);
153  exit (1);
154  }
155  }
156 
157  if (args[0] != NULL)
158  filename = args[0];
159 
160  /* Parse the source rect */
161  if(source_rect_string != NULL)
162  {
163  const int n = sscanf(source_rect_string, "%lg:%lg:%lg:%lg",
164  &source_rect.left, &source_rect.top,
165  &source_rect.width, &source_rect.height);
166  if (n != 4 || source_rect.width <= 0.0 || source_rect.height < 0.0)
167  {
168  fprintf (stderr, _("Invalid source rect: %s\n"), source_rect_string);
169  exit(1);
170  }
171  }
172 
173  rsvg_init ();
174 
175  rsvg = rsvg_handle_new_from_file (filename, &error);
176 
177  if (!rsvg)
178  {
179  fprintf (stderr, _("Error reading SVG:"));
180  display_error (error);
181  fprintf (stderr, "\n");
182  exit (1);
183  }
184 
185  /* if the user did not specify a source rectangle, get the page size from the SVG */
186  if(source_rect_string == NULL)
187  {
188  rsvg_handle_set_size_callback (rsvg, rsvg_cairo_size_callback, &dimensions, NULL);
189  source_rect.left = 0;
190  source_rect.top = 0;
191  source_rect.width = dimensions.width;
192  source_rect.height = dimensions.height;
193  }
194 
195  rsvg_handle_get_dimensions (rsvg, &dimensions);
196 
197  if (width != -1 && height != -1)
198  {
199  dimensions.width = width;
200  dimensions.height = height;
201  }
202  else if(source_rect_string != NULL)
203  {
204  dimensions.width = source_rect.width;
205  dimensions.height = source_rect.height;
206  }
207 
208  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
209  dimensions.width,
210  dimensions.height);
211 
212  cr = cairo_create (surface);
213 
214  cairo_translate (cr, -source_rect.left, -source_rect.top);
215 
216  if (width != -1 && height != -1 && source_rect_string != NULL)
217  {
218  cairo_scale (cr,
219  (double)dimensions.width / (double)source_rect.width,
220  (double)dimensions.height / (double)source_rect.height);
221  }
222 
223  rsvg_handle_render_cairo (rsvg, cr);
224 
225  cairo_surface_write_to_png_stream (surface, rsvg_cairo_write_func, output_file);
226 
227  g_object_unref (G_OBJECT (rsvg));
228 
229  cairo_destroy (cr);
230  cairo_surface_destroy (surface);
231 
232  fclose (output_file);
233 
234  rsvg_term ();
235 
236  return 0;
237 }
int main(int argc, const char *argv[])
run all tests or any single test specified in the first command line argument.
Definition: testrunner.cpp:37