summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Persch <chpe@gnome.org>2011-12-17 00:20:11 +0100
committerChristian Persch <chpe@gnome.org>2011-12-19 20:21:43 +0100
commit2c2917c3c19fbc51503ef19300e09a0da457b1fe (patch)
tree182c5d12f33ebe10b202f5044f679ed61929535d
parentaf4e05f890cbe93d61d4e4a52f037e375d3126c4 (diff)
downloadlibrsvg-2c2917c3c19fbc51503ef19300e09a0da457b1fe.tar.gz
Rework rsvg-view
Drop gtk2, use cairo surfaces instead of pixbuf, use GIO, load the SVG just once instead of every time we zoom or print, and remove some unused or unnecessary options.
-rw-r--r--Makefile.am26
-rw-r--r--librsvg.def1
-rw-r--r--test-display.c706
3 files changed, 281 insertions, 452 deletions
diff --git a/Makefile.am b/Makefile.am
index 5aca4aad..e53d5692 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,9 +11,6 @@ endif
lib_LTLIBRARIES = librsvg-@RSVG_API_MAJOR_VERSION@.la
bin_PROGRAMS = rsvg-convert
-if HAVE_GTK_2
-bin_PROGRAMS += rsvg-view
-endif
if HAVE_GTK_3
bin_PROGRAMS += rsvg-view-3
endif
@@ -130,29 +127,6 @@ rsvg_convert_LDADD = \
$(GTHREAD_LIBS) \
$(LIBM)
-rsvg_view_SOURCES = \
- test-display.c
-
-rsvg_view_CPPFLAGS = \
- -I$(top_srcdir) \
- -I$(top_builddir) \
- -DLIBRSVG_DATADIR="\"$(datadir)\"" \
- $(AM_CPPFLAGS)
-
-rsvg_view_CFLAGS =\
- $(GTK2_CFLAGS) \
- $(LIBRSVG_CFLAGS) \
- $(AM_CFLAGS)
-
-rsvg_view_LDFLAGS =
-
-rsvg_view_LDADD = \
- $(top_builddir)/librsvg-@RSVG_API_MAJOR_VERSION@.la \
- $(GTK2_LIBS) \
- $(LIBRSVG_LIBS) \
- $(GTHREAD_LIBS) \
- $(LIBM)
-
rsvg_view_3_SOURCES = \
test-display.c
diff --git a/librsvg.def b/librsvg.def
index 37b30b3a..79373eee 100644
--- a/librsvg.def
+++ b/librsvg.def
@@ -35,7 +35,6 @@ rsvg_handle_render_cairo
rsvg_handle_render_cairo_sub
rsvg_handle_get_type
_rsvg_size_callback
-_rsvg_acquire_xlink_href_resource
_rsvg_register_types
rsvg_defs_lookup
rsvg_pixbuf_from_data_with_size_data
diff --git a/test-display.c b/test-display.c
index 0231ac03..a71ad0f7 100644
--- a/test-display.c
+++ b/test-display.c
@@ -30,147 +30,188 @@
#include <gtk/gtk.h>
#include <gdk/gdk.h>
-#if GTK_CHECK_VERSION(2,90,7)
-#define GDK_KEY(symbol) GDK_KEY_##symbol
-#else
-#include <gdk/gdkkeysyms.h>
-#define GDK_KEY(symbol) GDK_##symbol
+#if 0 // defined (G_OS_UNIX)
+#include <gio/gunixinputstream.h>
#endif
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
-static char *
-_rsvg_basename (const char *file)
-{
- if (file && *file)
- return g_path_get_basename (file);
+/* RsvgImage */
- return NULL;
-}
+#define RSVG_TYPE_IMAGE (rsvg_image_get_type ())
+#define RSVG_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RSVG_TYPE_IMAGE, RsvgImage))
-typedef struct _ViewerCbInfo ViewerCbInfo;
-struct _ViewerCbInfo {
- GtkWidget *window;
- GtkWidget *popup_menu;
- GtkWidget *image; /* the image widget */
+typedef struct _RsvgImage RsvgImage;
+typedef struct _RsvgImageClass RsvgImageClass;
- GdkPixbuf *pixbuf;
- GByteArray *svg_bytes;
- GtkAccelGroup *accel_group;
- char *base_uri;
- char *id;
- gdouble x_zoom;
- gdouble y_zoom;
+struct _RsvgImage {
+ GtkWidget parent_instance;
+
+ cairo_surface_t *surface; /* a cairo image surface */
};
-static gboolean
-get_image_size_from_data (ViewerCbInfo *info,
- gint *width,
- gint *height,
- GError **error)
+struct _RsvgImageClass {
+ GtkWidgetClass parent_class;
+};
+
+static GType rsvg_image_get_type (void);
+
+static void
+rsvg_image_take_surface (RsvgImage *image,
+ cairo_surface_t *surface)
{
- RsvgHandle *handle;
- RsvgDimensionData dimensions;
+ if (image->surface == surface)
+ return;
+ if (image->surface)
+ cairo_surface_destroy (image->surface);
+ image->surface = surface; /* adopted */
- handle = rsvg_handle_new ();
+ gtk_widget_queue_resize (GTK_WIDGET (image));
+}
- if (!handle) {
- g_set_error (error, rsvg_error_quark (), 0, _("Error creating SVG reader"));
- return FALSE;
- }
+G_DEFINE_TYPE (RsvgImage, rsvg_image, GTK_TYPE_WIDGET);
- rsvg_handle_set_base_uri (handle, info->base_uri);
+static void
+rsvg_image_init (RsvgImage *image)
+{
+ gtk_widget_set_has_window (GTK_WIDGET (image), FALSE);
+}
- if (!rsvg_handle_write (handle, info->svg_bytes->data, info->svg_bytes->len, error)) {
- g_object_unref (handle);
- return FALSE;
- }
+static void
+rsvg_image_finalize (GObject *object)
+{
+ RsvgImage *image = RSVG_IMAGE (object);
- if (!rsvg_handle_close (handle, error)) {
- g_object_unref (handle);
- return FALSE;
- }
+ rsvg_image_take_surface (image, NULL);
+}
+
+static void
+rsvg_image_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ RsvgImage *image = RSVG_IMAGE (widget);
- (void) rsvg_handle_get_dimensions_sub (handle, &dimensions, info->id);
- g_object_unref (handle);
+ *minimum = *natural = image->surface ? cairo_image_surface_get_width (image->surface) : 1;
+}
- if (width)
- *width = dimensions.width;
- if (height)
- *height = dimensions.height;
+static void
+rsvg_image_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ RsvgImage *image = RSVG_IMAGE (widget);
- return TRUE;
+ *minimum = *natural = image->surface ? cairo_image_surface_get_height (image->surface) : 1;
}
static gboolean
-calculate_zoom_ratio (ViewerCbInfo *info,
- struct RsvgSizeCallbackData *size_data,
- GError **error)
+rsvg_image_draw (GtkWidget *widget,
+ cairo_t *cr)
{
- GdkScreen *screen;
- gint image_width, image_height;
- gint screen_width, screen_height;
- gdouble x_zoom = 1.0, y_zoom = 1.0, zoom;
+ RsvgImage *image = RSVG_IMAGE (widget);
+
+ if (image->surface == NULL)
+ return FALSE;
- if (!get_image_size_from_data (info, &image_width, &image_height, error))
- return FALSE;
+ cairo_save (cr);
+ cairo_set_source_surface (cr, image->surface, 0, 0);
+ cairo_paint (cr);
+ cairo_restore (cr);
- screen = gdk_screen_get_default ();
- screen_width = gdk_screen_get_width (screen);
- screen_height = gdk_screen_get_height (screen);
+ return FALSE;
+}
- if (image_width > screen_width)
- x_zoom = (gdouble) screen_width / image_width * 0.8;
+static void
+rsvg_image_class_init (RsvgImageClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- if (image_height > screen_height)
- y_zoom = (gdouble) screen_height / image_height * 0.8;
+ gobject_class->finalize = rsvg_image_finalize;
+ widget_class->get_preferred_width = rsvg_image_get_preferred_width;
+ widget_class->get_preferred_height = rsvg_image_get_preferred_height;
+ widget_class->draw = rsvg_image_draw;
+}
- zoom = MAX (x_zoom, y_zoom);
+static RsvgImage *
+rsvg_image_new_take_surface (cairo_surface_t *surface)
+{
+ RsvgImage *image;
- info->x_zoom = zoom;
- info->y_zoom = zoom;
- size_data->x_zoom = zoom;
- size_data->y_zoom = zoom;
+ image = g_object_new (RSVG_TYPE_IMAGE, NULL);
+ rsvg_image_take_surface (image, surface);
- return TRUE;
+ return image;
}
-static GdkPixbuf *
-pixbuf_from_data_with_size_data (const guchar * buff,
- size_t len,
- struct RsvgSizeCallbackData *data,
- const char *base_uri,
- const char *id,
- GError ** error)
+static cairo_surface_t *
+rsvg_image_get_surface (RsvgImage *image)
{
- RsvgHandle *handle;
- GdkPixbuf *retval;
+ return image->surface;
+}
- handle = rsvg_handle_new ();
+/* Main */
- if (!handle) {
- g_set_error (error, rsvg_error_quark (), 0, _("Error creating SVG reader"));
- return NULL;
- }
+static char *
+_rsvg_basename (const char *file)
+{
+ if (file && *file)
+ return g_path_get_basename (file);
+
+ return NULL;
+}
- rsvg_handle_set_size_callback (handle, _rsvg_size_callback, data, NULL);
- rsvg_handle_set_base_uri (handle, base_uri);
+typedef struct _ViewerCbInfo ViewerCbInfo;
+struct _ViewerCbInfo {
+ GtkWidget *window;
+ GtkWidget *popup_menu;
+ RsvgImage *image;
+ RsvgHandle *handle;
+ GtkAccelGroup *accel_group;
+ char *base_uri;
+ char *id;
+ RsvgDimensionData dimensions;
+ gdouble x_zoom;
+ gdouble y_zoom;
+};
- if (!rsvg_handle_write (handle, buff, len, error)) {
- g_object_unref (handle);
+static cairo_surface_t *
+render_to_surface (ViewerCbInfo *info)
+{
+ RsvgDimensionData dimensions;
+ int width, height;
+ cairo_matrix_t matrix;
+ GdkPixbuf *output = NULL;
+ guint8 *pixels;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ int rowstride, minimum;
+
+ width = ceil ((double) info->dimensions.width * info->x_zoom);
+ height = ceil ((double) info->dimensions.height * info->y_zoom);
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
+ cairo_surface_destroy (surface);
return NULL;
}
- if (!rsvg_handle_close (handle, error)) {
- g_object_unref (handle);
+ cr = cairo_create (surface);
+
+ cairo_matrix_init_scale (&matrix, info->x_zoom, info->y_zoom);
+ cairo_transform (cr, &matrix);
+
+ if (!rsvg_handle_render_cairo_sub (info->handle, cr, info->id)) {
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
return NULL;
}
- retval = rsvg_handle_get_pixbuf_sub (handle, id);
- g_object_unref (handle);
+ cairo_destroy (cr);
- return retval;
+ return surface;
}
static void
@@ -207,79 +248,26 @@ set_window_title (ViewerCbInfo * info)
static void
zoom_image (ViewerCbInfo * info, gdouble factor)
{
- struct RsvgSizeCallbackData size_data;
- GdkPixbuf *save_pixbuf = info->pixbuf;
-
info->x_zoom *= factor;
info->y_zoom *= factor;
- size_data.type = RSVG_SIZE_WH;
- size_data.width = gdk_pixbuf_get_width (info->pixbuf) * factor;
- size_data.height = gdk_pixbuf_get_height (info->pixbuf) * factor;
- size_data.keep_aspect_ratio = FALSE;
-
- info->pixbuf =
- pixbuf_from_data_with_size_data (info->svg_bytes->data, info->svg_bytes->len,
- &size_data, info->base_uri, info->id, NULL);
- gtk_image_set_from_pixbuf (GTK_IMAGE (info->image), info->pixbuf);
+ rsvg_image_take_surface (info->image, render_to_surface (info));
set_window_title (info);
-
- if (save_pixbuf)
- g_object_unref (save_pixbuf);
}
static void
zoom_in (GObject * ignored, ViewerCbInfo * info)
{
- if (!info->pixbuf)
- return;
- zoom_image (info, 1.25);
+ zoom_image (info, sqrt (G_SQRT2));
}
static void
zoom_out (GObject * ignored, ViewerCbInfo * info)
{
- if (!info->pixbuf)
- return;
- zoom_image (info, 1. / 1.25);
-}
-
-static void
-rsvg_window_set_default_icon (GtkWindow * window, GdkPixbuf * src)
-{
- GList *list;
- GdkPixbuf *icon;
- gint width, height;
-
- width = gdk_pixbuf_get_width (src);
- height = gdk_pixbuf_get_height (src);
-
- if (width > 128 || height > 128) {
- /* sending images greater than 128x128 has this nasty tendency to
- cause broken pipe errors X11 Servers */
- if (width > height) {
- width = 0.5 + width * 128. / height;
- height = 128;
- } else {
- height = 0.5 + height * 128. / width;
- width = 128;
- }
-
- icon = gdk_pixbuf_scale_simple (src, width, height, GDK_INTERP_BILINEAR);
- } else {
- icon = g_object_ref (src);
- }
-
- list = g_list_prepend (NULL, icon);
- gtk_window_set_icon_list (window, list);
- g_list_free (list);
-
- g_object_unref (icon);
+ zoom_image (info, 1. / sqrt (G_SQRT2));
}
-#if GTK_CHECK_VERSION(2,10,0)
-
static void
begin_print (GtkPrintOperation *operation,
GtkPrintContext *context,
@@ -295,48 +283,40 @@ draw_page (GtkPrintOperation *operation,
gpointer user_data)
{
ViewerCbInfo *info = (ViewerCbInfo *) user_data;
+ cairo_t *cr;
+ gdouble page_width, page_height, page_aspect;
+ gdouble width, height, aspect;
+ cairo_matrix_t matrix;
+
+ cr = gtk_print_context_get_cairo_context (context);
+ page_width = gtk_print_context_get_width (context);
+ page_height = gtk_print_context_get_height (context);
+ page_aspect = page_width / page_height;
+
+ // FIXMEchpe
+ rsvg_handle_set_dpi_x_y (info->handle,
+ gtk_print_context_get_dpi_x(context),
+ gtk_print_context_get_dpi_y(context));
+
+ width = info->dimensions.width;
+ height = info->dimensions.height;
+ aspect = width / height;
+
+ if (aspect <= page_aspect) {
+ width = page_height * aspect;
+ height = page_height;
+ } else {
+ width = page_width;
+ height = page_width / aspect;
+ }
- cairo_t *cr;
- gdouble page_width, page_height;
-
- cr = gtk_print_context_get_cairo_context (context);
- page_width = gtk_print_context_get_width (context);
- page_height = gtk_print_context_get_height (context);
-
- {
- RsvgHandle *handle;
- RsvgDimensionData svg_dimensions;
- struct RsvgSizeCallbackData size_data;
-
- /* should not fail */
- handle = rsvg_handle_new_from_data(info->svg_bytes->data, info->svg_bytes->len, NULL);
- rsvg_handle_set_base_uri (handle, info->base_uri);
- rsvg_handle_set_dpi_x_y (handle, gtk_print_context_get_dpi_x(context),
- gtk_print_context_get_dpi_y(context));
- rsvg_handle_get_dimensions(handle, &svg_dimensions);
-
- if (svg_dimensions.width > page_width || svg_dimensions.height > page_height) {
- /* scale down the image to the page's size, while preserving the aspect ratio */
-
- if ((double) svg_dimensions.height * (double) page_width > (double) svg_dimensions.width * (double) page_height) {
- svg_dimensions.width = 0.5 + (double) svg_dimensions.width *(double) page_height / (double) svg_dimensions.height;
- svg_dimensions.height = page_height;
- } else {
- svg_dimensions.height = 0.5 + (double) svg_dimensions.height *(double) page_width / (double) svg_dimensions.width;
- svg_dimensions.width = page_width;
- }
- }
-
- size_data.type = RSVG_SIZE_WH;
- size_data.width = svg_dimensions.width;
- size_data.height = svg_dimensions.height;
- size_data.keep_aspect_ratio = FALSE;
- rsvg_handle_set_size_callback (handle, _rsvg_size_callback, &size_data, NULL);
-
- rsvg_handle_render_cairo(handle, cr);
-
- g_object_unref (handle);
- }
+ cairo_save (cr);
+ cairo_matrix_init_scale (&matrix,
+ width / info->dimensions.width,
+ height / info->dimensions.height);
+ cairo_transform (cr, &matrix);
+ rsvg_handle_render_cairo (info->handle, cr);
+ cairo_restore (cr);
}
static void
@@ -356,8 +336,6 @@ print_pixbuf (GObject * ignored, gpointer user_data)
g_object_unref (print);
}
-#endif /* HAVE_GNOME_PRINT */
-
static char *
save_file (const char *title, const char *suggested_filename, GtkWidget * parent, int *success)
{
@@ -391,6 +369,7 @@ save_pixbuf (GObject * ignored, gpointer user_data)
ViewerCbInfo *info = (ViewerCbInfo *) user_data;
char *filename, *base_name, *filename_suggestion;
int success = 0;
+ cairo_surface_t *surface;
base_name = _rsvg_basename (info->base_uri);
if (base_name)
@@ -403,92 +382,18 @@ save_pixbuf (GObject * ignored, gpointer user_data)
g_free (filename_suggestion);
if (filename) {
- GError *err = NULL;
-
- if (!gdk_pixbuf_save (info->pixbuf, filename, "png", &err, NULL)) {
- if (err) {
+ surface = rsvg_image_get_surface (info->image);
+ if (cairo_surface_write_to_png (surface, filename) != CAIRO_STATUS_SUCCESS) {
GtkWidget *errmsg;
errmsg = gtk_message_dialog_new (GTK_WINDOW (info->window),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING,
- GTK_BUTTONS_CLOSE, "%s", err->message);
+ GTK_BUTTONS_CLOSE, "Failed to save");
gtk_dialog_run (GTK_DIALOG (errmsg));
- g_error_free (err);
gtk_widget_destroy (errmsg);
- }
- }
-
- g_free (filename);
- } else if (success) {
- GtkWidget *errmsg;
-
- errmsg = gtk_message_dialog_new (GTK_WINDOW (info->window),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_CLOSE, _("No filename given"));
- gtk_window_set_transient_for (GTK_WINDOW (errmsg), GTK_WINDOW (info->window));
-
- gtk_dialog_run (GTK_DIALOG (errmsg));
- gtk_widget_destroy (errmsg);
- }
-}
-
-static void
-save_svg (GObject * ignored, gpointer user_data)
-{
- ViewerCbInfo *info = (ViewerCbInfo *) user_data;
- char *filename, *base_name;
- int success = 0;
-
- base_name = _rsvg_basename (info->base_uri);
- filename = save_file (_("Save SVG"), base_name, info->window, &success);
- g_free (base_name);
-
- if (filename) {
- FILE *fp;
-
- /* todo: make this support gnome vfs */
- fp = fopen (filename, "wb");
- if (!fp) {
- GtkWidget *errmsg;
-
- errmsg = gtk_message_dialog_new (GTK_WINDOW (info->window),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_CLOSE, _("Couldn't save %s"), filename);
- gtk_window_set_transient_for (GTK_WINDOW (errmsg), GTK_WINDOW (info->window));
-
- gtk_dialog_run (GTK_DIALOG (errmsg));
- gtk_widget_destroy (errmsg);
- } else {
- size_t written = 0, remaining = info->svg_bytes->len;
- const unsigned char *buffer = info->svg_bytes->data;
-
- while (remaining > 0) {
- written = fwrite (buffer + (info->svg_bytes->len - remaining), 1, remaining, fp);
- if ((written < remaining) && ferror (fp) != 0) {
- GtkWidget *errmsg;
-
- errmsg = gtk_message_dialog_new (GTK_WINDOW (info->window),
- GTK_DIALOG_MODAL |
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
- _("Couldn't save %s"), filename);
- gtk_window_set_transient_for (GTK_WINDOW (errmsg), GTK_WINDOW (info->window));
-
- gtk_dialog_run (GTK_DIALOG (errmsg));
- gtk_widget_destroy (errmsg);
-
- break;
- }
-
- remaining -= written;
- }
-
- fclose (fp);
}
g_free (filename);
@@ -536,17 +441,10 @@ create_popup_menu (ViewerCbInfo * info)
g_signal_connect (menu_item, "activate", G_CALLBACK (copy_svg_location), info);
gtk_widget_show (menu_item);
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), menu_item);
- gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY(C),
+ gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY_C,
GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
}
- menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE, NULL);
- g_signal_connect (menu_item, "activate", G_CALLBACK (save_svg), info);
- gtk_widget_show (menu_item);
- gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), menu_item);
- gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY(S), GDK_CONTROL_MASK,
- GTK_ACCEL_VISIBLE);
-
menu_item = gtk_image_menu_item_new_with_label (_("Save as PNG"));
stock = gtk_image_new_from_stock (GTK_STOCK_SAVE_AS, GTK_ICON_SIZE_MENU);
gtk_widget_show (stock);
@@ -554,30 +452,28 @@ create_popup_menu (ViewerCbInfo * info)
g_signal_connect (menu_item, "activate", G_CALLBACK (save_pixbuf), info);
gtk_widget_show (menu_item);
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), menu_item);
- gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY(S),
+ gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY_S,
GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
-#if GTK_CHECK_VERSION(2,10,0)
menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_PRINT, NULL);
g_signal_connect (menu_item, "activate", G_CALLBACK (print_pixbuf), info);
gtk_widget_show (menu_item);
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), menu_item);
- gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY(P), GDK_CONTROL_MASK,
+ gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY_P, GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
-#endif
menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_ZOOM_IN, NULL);
g_signal_connect (menu_item, "activate", G_CALLBACK (zoom_in), info);
gtk_widget_show (menu_item);
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), menu_item);
- gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY(plus),
+ gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY_plus,
GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_ZOOM_OUT, NULL);
g_signal_connect (menu_item, "activate", G_CALLBACK (zoom_out), info);
gtk_widget_show (menu_item);
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), menu_item);
- gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY(minus),
+ gtk_widget_add_accelerator (menu_item, "activate", info->accel_group, GDK_KEY_minus,
GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
info->popup_menu = popup_menu;
@@ -605,10 +501,17 @@ quit_cb (GtkWidget * win, gpointer unused)
}
static void
-populate_window (GtkWidget * win, ViewerCbInfo * info, int xid, gint win_width, gint win_height)
+populate_window (GtkWidget * win,
+ ViewerCbInfo * info,
+ cairo_surface_t *surface /* adopted */,
+ gint win_width,
+ gint win_height)
{
GtkWidget *vbox;
GtkWidget *scroll;
+ GtkWidget *toolbar;
+ GtkToolItem *toolitem;
+ GtkRequisition requisition;
gint img_width, img_height;
#if GTK_CHECK_VERSION (3, 2, 0)
@@ -618,56 +521,44 @@ populate_window (GtkWidget * win, ViewerCbInfo * info, int xid, gint win_width,
#endif
gtk_container_add (GTK_CONTAINER (win), vbox);
- /* create a new image */
- info->image = gtk_image_new_from_pixbuf (info->pixbuf);
-
/* pack the window with the image */
- img_width = gdk_pixbuf_get_width (info->pixbuf);
- img_height = gdk_pixbuf_get_height (info->pixbuf);
+ img_width = cairo_image_surface_get_width (surface);
+ img_height = cairo_image_surface_get_height (surface);
- if (xid <= 0) {
- GtkWidget *toolbar;
- GtkToolItem *toolitem;
- GtkRequisition requisition;
-
- toolbar = gtk_toolbar_new ();
- gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
+ /* create a new image */
+ info->image = rsvg_image_new_take_surface (surface);
- toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_IN);
- gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, 0);
- g_signal_connect (toolitem, "clicked", G_CALLBACK (zoom_in), info);
+ toolbar = gtk_toolbar_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
- toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_OUT);
- gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, 1);
- g_signal_connect (toolitem, "clicked", G_CALLBACK (zoom_out), info);
+ toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_IN);
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, 0);
+ g_signal_connect (toolitem, "clicked", G_CALLBACK (zoom_in), info);
- gtk_widget_size_request(toolbar, &requisition);
+ toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_OUT);
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, 1);
+ g_signal_connect (toolitem, "clicked", G_CALLBACK (zoom_out), info);
- /* HACK: adjust for frame width & height + packing borders */
- img_height += requisition.height + 30;
- win_height += requisition.height + 30;
- img_width += 20;
- win_width += 20;
- }
+ gtk_widget_size_request(toolbar, &requisition);
- if ((xid > 0 && (img_width > win_width || img_height > win_height))
- || (xid <= 0)) {
- gtk_window_set_default_size (GTK_WINDOW (win), MIN (img_width, win_width),
- MIN (img_height, win_height));
+ /* HACK: adjust for frame width & height + packing borders */
+ img_height += requisition.height + 30;
+ win_height += requisition.height + 30;
+ img_width += 20;
+ win_width += 20;
- scroll = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll), info->image);
- gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
- } else {
- gtk_box_pack_start (GTK_BOX (vbox), info->image, TRUE, TRUE, 0);
- gtk_window_set_default_size (GTK_WINDOW (win), img_width, img_height);
- }
+ scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll),
+ GTK_WIDGET (info->image));
+ gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
}
static void
-view_pixbuf (ViewerCbInfo * info, int xid, const char *color)
+view_surface (ViewerCbInfo * info,
+ cairo_surface_t *surface /* adopted */,
+ const char *color)
{
GtkWidget *win;
GdkColor bg_color;
@@ -680,9 +571,7 @@ view_pixbuf (ViewerCbInfo * info, int xid, const char *color)
win_width = DEFAULT_WIDTH;
win_height = DEFAULT_HEIGHT;
- populate_window (win, info, xid, win_width, win_height);
-
- rsvg_window_set_default_icon (GTK_WINDOW (win), info->pixbuf);
+ populate_window (win, info, surface, win_width, win_height);
/* exit when 'X' is clicked */
g_signal_connect (win, "destroy", G_CALLBACK (quit_cb), NULL);
@@ -690,17 +579,9 @@ view_pixbuf (ViewerCbInfo * info, int xid, const char *color)
if (color && strcmp (color, "none") != 0) {
if (gdk_color_parse (color, &bg_color)) {
- GtkWidget *parent_widget = gtk_widget_get_parent (info->image);
+ GtkWidget *parent_widget = gtk_widget_get_parent (GTK_WIDGET (info->image));
-#if GTK_CHECK_VERSION (2, 90, 8)
gtk_widget_modify_bg (parent_widget, GTK_STATE_NORMAL, &bg_color);
-#else
- if (gdk_colormap_alloc_color
- (gtk_widget_get_colormap (parent_widget), &bg_color, FALSE, TRUE))
- gtk_widget_modify_bg (parent_widget, GTK_STATE_NORMAL, &bg_color);
- else
- g_warning (_("Couldn't allocate color '%s'"), color);
-#endif
} else
g_warning (_("Couldn't parse color '%s'"), color);
}
@@ -732,10 +613,12 @@ main (int argc, char **argv)
int bVersion = 0;
char *bg_color = NULL;
char *base_uri = NULL;
- int bKeepAspect = 0;
+ gboolean keep_aspect_ratio = FALSE;
char *id = NULL;
+ GInputStream *input;
+ GFile *file, *base_file;
+ cairo_surface_t *surface;
- int xid = -1;
int from_stdin = 0;
ViewerCbInfo info;
@@ -763,7 +646,7 @@ main (int argc, char **argv)
N_("<string>")},
{"id", 0, 0, G_OPTION_ARG_STRING, &id, N_("Only show one node (default: all)"),
N_("<string>")},
- {"keep-aspect", 'k', 0, G_OPTION_ARG_NONE, &bKeepAspect,
+ {"keep-aspect", 'k', 0, G_OPTION_ARG_NONE, &keep_aspect_ratio,
N_("Preserve the image's aspect ratio"), NULL},
{"version", 'v', 0, G_OPTION_ARG_NONE, &bVersion, N_("Show version information"), NULL},
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &args, NULL, N_("[FILE...]")},
@@ -775,8 +658,6 @@ main (int argc, char **argv)
g_type_init ();
- info.pixbuf = NULL;
- info.svg_bytes = NULL;
info.window = NULL;
info.popup_menu = NULL;
@@ -795,10 +676,10 @@ main (int argc, char **argv)
return 0;
}
- if (args) {
- while (args[n_args] != NULL)
- n_args++;
- }
+ if (args)
+ n_args = g_strv_length (args);
+ else
+ n_args = 0;
if ((!from_stdin) && (n_args != 1)) {
g_print (_("No files specified, and not using --stdin\n"));
@@ -807,94 +688,70 @@ main (int argc, char **argv)
rsvg_set_default_dpi_x_y (dpi_x, dpi_y);
- /* if both are unspecified, assume user wants to zoom the pixbuf in at least 1 dimension */
- if (width == -1 && height == -1) {
- size_data.type = RSVG_SIZE_ZOOM;
- size_data.x_zoom = x_zoom;
- size_data.y_zoom = y_zoom;
- }
- /* if both are unspecified, assume user wants to resize pixbuf in at least 1 dimension */
- else if (x_zoom == 1.0 && y_zoom == 1.0) {
- size_data.type = RSVG_SIZE_WH;
- size_data.width = width;
- size_data.height = height;
- }
- /* assume the user wants to zoom the pixbuf, but cap the maximum size */
- else {
- size_data.type = RSVG_SIZE_ZOOM_MAX;
- size_data.x_zoom = x_zoom;
- size_data.y_zoom = y_zoom;
- size_data.width = width;
- size_data.height = height;
- }
-
- size_data.keep_aspect_ratio = bKeepAspect;
-
- if (!from_stdin) {
- if (base_uri == NULL)
- base_uri = (char *) args[0];
-
- info.svg_bytes = _rsvg_acquire_xlink_href_resource (args[0], base_uri, NULL);
+ if (from_stdin) {
+#if 0 // defined (G_OS_UNIX)
+ input = g_unix_input_stream_new (STDIN_FILENO, FALSE);
+#else
+ input = NULL;
+ g_set_error_literal (&err, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Reading from stdin not supported");
+#endif
+ base_file = NULL;
} else {
- info.svg_bytes = g_byte_array_new ();
+ file = g_file_new_for_commandline_arg (args[0]);
+ input = (GInputStream *) g_file_read (file, NULL, &err);
- for (;;) {
- unsigned char buf[1024 * 8];
- size_t nread = fread (buf, 1, sizeof (buf), stdin);
+ if (base_uri)
+ base_file = g_file_new_for_uri (base_uri);
+ else
+ base_file = g_object_ref (file);
- if (nread > 0)
- g_byte_array_append (info.svg_bytes, buf, nread);
-
- if (nread < sizeof (buf)) {
- if (ferror (stdin)) {
- g_print (_("Error reading\n"));
- g_byte_array_free (info.svg_bytes, TRUE);
- fclose (stdin);
-
- return 1;
- } else if (feof (stdin))
- break;
- }
- }
-
- fclose (stdin);
+ g_object_unref (file);
}
- if (!info.svg_bytes || !info.svg_bytes->len) {
- g_print (_("Couldn't open %s\n"), args[0]);
+ g_strfreev (args);
+
+ if (input == NULL) {
+ g_printerr ("Failed to read input: %s\n", err->message);
+ g_error_free (err);
return 1;
}
- info.base_uri = base_uri;
+ info.base_uri = base_file ? g_file_get_uri (base_file) : g_strdup ("");
info.id = id;
info.x_zoom = x_zoom;
info.y_zoom = y_zoom;
- if (size_data.type == RSVG_SIZE_ZOOM &&
- x_zoom == 1.0 && y_zoom == 1.0) {
- if (!calculate_zoom_ratio (&info, &size_data, &err)) {
- if (err) {
- g_print (": %s\n", err->message);
- g_error_free (err);
- }
- return 1;
- }
+ info.handle = rsvg_handle_new_from_stream_sync (input,
+ base_file,
+ RSVG_HANDLE_FLAGS_NONE,
+ NULL /* cancellable */,
+ &err);
+ g_object_unref (base_file);
+
+ if (info.handle == NULL) {
+ g_printerr ("Failed to load SVG: %s\n", err->message);
+ g_error_free (err);
+ g_object_unref (info.handle);
+ return 1;
}
- info.pixbuf =
- pixbuf_from_data_with_size_data (info.svg_bytes->data, info.svg_bytes->len, &size_data,
- base_uri, id, &err);
+ rsvg_handle_get_dimensions (info.handle, &info.dimensions);
- if (!info.pixbuf) {
- g_print (_("Error displaying image"));
-
- if (err) {
- g_print (": %s", err->message);
- g_error_free (err);
- }
-
- g_print ("\n");
+ if (width != -1) {
+ info.x_zoom = (double) width / info.dimensions.width;
+ } else {
+ info.x_zoom = x_zoom;
+ }
+ if (height != -1) {
+ info.y_zoom = (double) height / info.dimensions.height;
+ } else {
+ info.y_zoom = y_zoom;
+ }
+ surface = render_to_surface (&info);
+ if (surface == NULL) {
+ g_printerr (_("Error displaying image"));
goto done;
}
@@ -902,16 +759,15 @@ main (int argc, char **argv)
info.accel_group = gtk_accel_group_new ();
- view_pixbuf (&info, xid, bg_color);
+ view_surface (&info, surface, bg_color);
/* run the gtk+ main loop */
gtk_main ();
- g_object_unref (info.pixbuf);
-
done:
- g_byte_array_free (info.svg_bytes, TRUE);
- g_strfreev (args);
+
+ g_free (info.base_uri);
+ g_object_unref (info.handle);
rsvg_cleanup ();