[eog/wip/baedert/gtkimageview: 62/75] Implement svg rendering
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [eog/wip/baedert/gtkimageview: 62/75] Implement svg rendering
- Date: Sat, 19 Mar 2016 17:09:54 +0000 (UTC)
commit bb14a910ca5de2d7dc0589be659794853a17f979
Author: Timm Bäder <mail baedert org>
Date: Sat Mar 19 10:07:53 2016 +0100
Implement svg rendering
src/eog-image-private.h | 7 ++-
src/eog-image.c | 146 ++++++++++++++++++++++++++++++-----------------
src/eog-image.h | 6 +-
src/eog-scroll-view.c | 22 +++++++
4 files changed, 125 insertions(+), 56 deletions(-)
---
diff --git a/src/eog-image-private.h b/src/eog-image-private.h
index 46823ac..d27d0a4 100644
--- a/src/eog-image-private.h
+++ b/src/eog-image-private.h
@@ -47,8 +47,11 @@ struct _EogImagePrivate {
GdkPixbuf *image;
GdkPixbuf *thumbnail;
- cairo_surface_t *surface;
- guint timeout_id;
+ cairo_surface_t *surface;
+ guint timeout_id;
+
+ double view_scale;
+ double current_scale;
#ifdef HAVE_RSVG
diff --git a/src/eog-image.c b/src/eog-image.c
index a3f2330..99c86a1 100644
--- a/src/eog-image.c
+++ b/src/eog-image.c
@@ -183,10 +183,10 @@ eog_image_dispose (GObject *object)
priv->file_type = NULL;
}
- if (priv->timeout_id != 0) {
- g_source_remove (priv->timeout_id);
- priv->timeout_id = 0;
- }
+ if (priv->timeout_id != 0) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
g_mutex_clear (&priv->status_mutex);
@@ -224,13 +224,17 @@ eog_image_finalize (GObject *object)
static int
__get_width (GtkAbstractImage *_image)
{
- return EOG_IMAGE (_image)->priv->width;
+ EogImagePrivate *priv = EOG_IMAGE (_image)->priv;
+
+ return priv->width;
}
static int
__get_height (GtkAbstractImage *_image)
{
- return EOG_IMAGE (_image)->priv->height;
+ EogImagePrivate *priv = EOG_IMAGE (_image)->priv;
+
+ return priv->height;
}
static int
@@ -244,6 +248,9 @@ __draw (GtkAbstractImage *_image, cairo_t *ct)
{
EogImagePrivate *priv = EOG_IMAGE (_image)->priv;
+ if (priv->svg)
+ cairo_scale (ct, 1.0 / priv->view_scale, 1.0 / priv->view_scale);
+
cairo_set_source_surface (ct, priv->surface, 0, 0);
}
@@ -259,12 +266,13 @@ eog_image_iter_advance (EogImage *img)
priv = img->priv;
- if ((new_frame = gdk_pixbuf_animation_iter_advance (img->priv->anim_iter, NULL)) == TRUE)
- {
+ new_frame = gdk_pixbuf_animation_iter_advance (priv->anim_iter, NULL);
+
+ if (new_frame) {
g_mutex_lock (&priv->status_mutex);
g_object_unref (priv->image);
priv->image = gdk_pixbuf_animation_iter_get_pixbuf (priv->anim_iter);
- g_object_ref (priv->image);
+ g_object_ref (priv->image);
/* keep the transformation over time */
if (EOG_IS_TRANSFORM (priv->trans)) {
GdkPixbuf* transformed = eog_transform_apply (priv->trans, priv->image, NULL);
@@ -277,8 +285,8 @@ eog_image_iter_advance (EogImage *img)
g_mutex_unlock (&priv->status_mutex);
- g_signal_emit_by_name (G_OBJECT (img), "changed", 0);
- }
+ g_signal_emit_by_name (G_OBJECT (img), "changed", 0);
+ }
return new_frame;
}
@@ -291,12 +299,14 @@ private_timeout (gpointer data)
if (eog_image_is_animation (img) &&
!g_source_is_destroyed (g_main_current_source ())) {
- while (eog_image_iter_advance (img) != TRUE) {}; /* cpu-sucking ? */
- g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (priv->anim_iter),
private_timeout, img);
- return G_SOURCE_CONTINUE;
+ int iter_delay = gdk_pixbuf_animation_iter_get_delay_time (priv->anim_iter);
+
+ while (eog_image_iter_advance (img) != TRUE) {}; /* cpu-sucking? */
+ priv->timeout_id = g_timeout_add (iter_delay, private_timeout, img);
}
- return G_SOURCE_REMOVE; /* stop playing */
+ return G_SOURCE_REMOVE;
}
+
static void
__start (GtkPlayable *playable)
{
@@ -310,34 +320,66 @@ __start (GtkPlayable *playable)
g_object_ref (priv->anim_iter);
g_mutex_unlock (&priv->status_mutex);
- g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (priv->anim_iter), private_timeout, img);
+ priv->timeout_id = g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (priv->anim_iter),
+ private_timeout,
+ img);
}
static void
__stop (GtkPlayable *playable)
{
- EogImagePrivate *priv = EOG_IMAGE (playable)->priv;
+ EogImagePrivate *priv = EOG_IMAGE (playable)->priv;
+
+ if (priv->timeout_id != 0) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+}
+
+static void
+render_svg_surface (EogImage *img)
+{
+ EogImagePrivate *priv = img->priv;
+ cairo_t *ct;
+ int w, h;
+
+ g_assert (priv->svg);
+
+ if (priv->surface)
+ cairo_surface_destroy (priv->surface);
+
+ w = (int)(priv->width * priv->view_scale);
+ h = (int)(priv->height * priv->view_scale);
+
+ priv->surface = gdk_window_create_similar_image_surface (NULL,
+ CAIRO_FORMAT_ARGB32,
+ w, h,
+ 1);
+ ct = cairo_create (priv->surface);
- if (priv->timeout_id != 0) {
- g_source_remove (priv->timeout_id);
- priv->timeout_id = 0;
- }
+ cairo_rectangle (ct, 0, 0, w, h);
+ cairo_set_source_rgba (ct, 0, 1, 0, 1);
+ cairo_stroke (ct);
+
+ cairo_scale (ct, priv->view_scale, priv->view_scale);
+ rsvg_handle_render_cairo (priv->svg, ct);
+ cairo_destroy (ct);
}
static void
eog_image_class_init (EogImageClass *klass)
{
GObjectClass *object_class = (GObjectClass*) klass;
- GtkAbstractImageClass *image_class = GTK_ABSTRACT_IMAGE_CLASS (klass);
- GtkPlayableClass *playable_class = GTK_PLAYABLE_CLASS (klass);
+ GtkAbstractImageClass *image_class = GTK_ABSTRACT_IMAGE_CLASS (klass);
+ GtkPlayableClass *playable_class = GTK_PLAYABLE_CLASS (klass);
- image_class->get_width = __get_width;
- image_class->get_height = __get_height;
- image_class->get_scale_factor = __get_scale_factor;
- image_class->draw = __draw;
+ image_class->get_width = __get_width;
+ image_class->get_height = __get_height;
+ image_class->get_scale_factor = __get_scale_factor;
+ image_class->draw = __draw;
- playable_class->start = __start;
- playable_class->stop = __stop;
+ playable_class->start = __start;
+ playable_class->stop = __stop;
object_class->dispose = eog_image_dispose;
object_class->finalize = eog_image_finalize;
@@ -386,11 +428,12 @@ eog_image_init (EogImage *img)
{
img->priv = eog_image_get_instance_private (img);
+ img->priv->view_scale = 1.0;
img->priv->file = NULL;
img->priv->image = NULL;
img->priv->anim = NULL;
img->priv->anim_iter = NULL;
- img->priv->timeout_id = 0;
+ img->priv->timeout_id = 0;
img->priv->thumbnail = NULL;
img->priv->width = -1;
img->priv->height = -1;
@@ -993,23 +1036,6 @@ eog_image_get_dimension_from_thumbnail (EogImage *image,
return (*width || *height);
}
-static void
-create_svg_surface (EogImage *img)
-{
- EogImagePrivate *priv = img->priv;
- cairo_t *ct;
-
- g_assert (priv->svg);
-
- priv->surface = gdk_window_create_similar_image_surface (NULL,
- CAIRO_FORMAT_ARGB32,
- priv->width,
- priv->height,
- 1);
- ct = cairo_create (priv->surface);
- rsvg_handle_render_cairo (priv->svg, ct);
- cairo_destroy (ct);
-}
static gboolean
eog_image_real_load (EogImage *img,
@@ -1296,7 +1322,7 @@ eog_image_real_load (EogImage *img,
if (use_rsvg) {
format = NULL;
priv->file_type = g_strdup ("svg");
- create_svg_surface (img);
+ render_svg_surface (img);
} else {
format = gdk_pixbuf_loader_get_format (loader);
priv->surface = gdk_cairo_surface_create_from_pixbuf (priv->image, 1, NULL);
@@ -2570,7 +2596,7 @@ eog_image_is_multipaged (EogImage *img)
if (img->priv->image != NULL)
{
const gchar* value = gdk_pixbuf_get_option (img->priv->image,
- "multipage");
+ "multipage");
result = (g_strcmp0 ("yes", value) == 0);
}
@@ -2581,8 +2607,24 @@ eog_image_is_multipaged (EogImage *img)
gboolean
eog_image_has_alpha (EogImage *img)
{
- EogImagePrivate *priv = img->priv;
+ EogImagePrivate *priv = img->priv;
- return priv->image != NULL &&
- gdk_pixbuf_get_has_alpha (priv->image);
+ return priv->image != NULL &&
+ gdk_pixbuf_get_has_alpha (priv->image);
+}
+
+void
+eog_image_set_view_scale (EogImage *img, double scale)
+{
+ EogImagePrivate *priv = img->priv;
+
+ if (scale == priv->view_scale)
+ return;
+
+ priv->view_scale = scale;
+
+ if (priv->svg) {
+ render_svg_surface (img);
+ g_signal_emit_by_name (G_OBJECT (img), "changed", 0);
+ }
}
diff --git a/src/eog-image.h b/src/eog-image.h
index ea9f905..729f41f 100644
--- a/src/eog-image.h
+++ b/src/eog-image.h
@@ -89,13 +89,13 @@ typedef enum {
} EogImageMetadataStatus;
struct _EogImage {
- GtkPlayable parent;
+ GtkPlayable parent;
EogImagePrivate *priv;
};
struct _EogImageClass {
- GtkPlayableClass parent_class;
+ GtkPlayableClass parent_class;
void (* size_prepared) (EogImage *img,
int width,
@@ -216,6 +216,8 @@ gboolean eog_image_is_multipaged (EogImage *img);
gboolean eog_image_has_alpha (EogImage *img);
+void eog_image_set_view_scale (EogImage *img, double view_scale);
+
G_END_DECLS
#endif /* __EOG_IMAGE_H__ */
diff --git a/src/eog-scroll-view.c b/src/eog-scroll-view.c
index e8a33af..4be2bea 100644
--- a/src/eog-scroll-view.c
+++ b/src/eog-scroll-view.c
@@ -943,6 +943,7 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
if (priv->transp_style != EOG_TRANSP_BACKGROUND)
cairo_rectangle (cr, MAX (0, xofs), MAX (0, yofs),
scaled_width, scaled_height);
+
if (priv->override_bg_color != NULL)
background_color = priv->override_bg_color;
else if (priv->use_bg_color)
@@ -1461,9 +1462,12 @@ eog_scroll_view_set_image (EogScrollView *view, EogImage *image)
}
priv->image = image;
+ gtk_image_view_set_angle (GTK_IMAGE_VIEW (priv->display), 0);
+ gtk_image_view_set_fit_allocation (GTK_IMAGE_VIEW (priv->display), TRUE);
gtk_image_view_set_abstract_image (GTK_IMAGE_VIEW (priv->display),
GTK_ABSTRACT_IMAGE (image));
+
g_object_notify (G_OBJECT (view), "image");
}
@@ -1616,6 +1620,20 @@ _motion_notify_cb (GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
}
static void
+display_scale_changed_cb (GtkImageView *display,
+ GParamSpec *param_spec,
+ gpointer user_data)
+{
+ double scale = gtk_image_view_get_scale (display);
+
+
+ /* Will recalculate the surface */
+ eog_image_set_view_scale (EOG_SCROLL_VIEW (user_data)->priv->image, scale);
+
+ /*gtk_image_view_set_scale (GTK_IMAGE_VIEW (EOG_SCROLL_VIEW (user_data)->priv->display), 1.0);*/
+}
+
+static void
eog_scroll_view_init (EogScrollView *view)
{
GSettings *settings;
@@ -1650,8 +1668,12 @@ eog_scroll_view_init (EogScrollView *view)
"can-focus", TRUE,
"hexpand", TRUE,
"vexpand", TRUE,
+ "fit-allocation", TRUE,
NULL);
+ g_signal_connect (priv->display, "notify::scale",
+ G_CALLBACK (display_scale_changed_cb), view);
+
gtk_widget_add_events (GTK_WIDGET (priv->display),
GDK_EXPOSURE_MASK
| GDK_TOUCHPAD_GESTURE_MASK
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]