[gtk+/wip/baedert/gtkimageview: 38/96] GtkImageView: Fix HiDPI drawing
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/baedert/gtkimageview: 38/96] GtkImageView: Fix HiDPI drawing
- Date: Mon, 25 Jan 2016 17:57:24 +0000 (UTC)
commit 44913c63753429b4ffcf1115406c7ce4ffd1e684
Author: Timm Bäder <mail baedert org>
Date: Sat Aug 15 17:20:38 2015 +0200
GtkImageView: Fix HiDPI drawing
demos/gtk-demo/image_view.c | 15 +++++
demos/gtk-demo/image_view.ui | 34 ++++++++----
gtk/gtkimageview.c | 121 +++++++++++++++++++++++------------------
3 files changed, 107 insertions(+), 63 deletions(-)
---
diff --git a/demos/gtk-demo/image_view.c b/demos/gtk-demo/image_view.c
index d27e672..2aca214 100644
--- a/demos/gtk-demo/image_view.c
+++ b/demos/gtk-demo/image_view.c
@@ -138,6 +138,21 @@ load_pixbuf_button_clicked_cb ()
void
+load_hidpi_pixbuf_button_clicked_cb ()
+{
+ GdkPixbuf *pixbuf;
+
+ /* I really hope you have this. */
+ pixbuf = gdk_pixbuf_new_from_file ("/usr/share/backgrounds/gnome/adwaita-day.jpg",
+ NULL);
+
+ g_assert (pixbuf != NULL);
+ gtk_image_view_set_pixbuf (GTK_IMAGE_VIEW (image_view), pixbuf, 2);
+
+ g_object_unref (G_OBJECT (pixbuf));
+}
+
+void
load_surface_button_clicked_cb ()
{
GdkPixbuf *pixbuf;
diff --git a/demos/gtk-demo/image_view.ui b/demos/gtk-demo/image_view.ui
index 2493ed6..c107057 100644
--- a/demos/gtk-demo/image_view.ui
+++ b/demos/gtk-demo/image_view.ui
@@ -80,12 +80,26 @@
<child>
<object class="GtkButton">
<property name="visible">true</property>
+ <property name="label" translatable="yes">Load HiDPI Pixbuf</property>
+ <signal name="clicked" handler="load_hidpi_pixbuf_button_clicked_cb" object="image_view"/>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+
+
+ <child>
+ <object class="GtkButton">
+ <property name="visible">true</property>
<property name="label" translatable="yes">Load Surface</property>
<signal name="clicked" handler="load_surface_button_clicked_cb" />
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">3</property>
+ <property name="top_attach">4</property>
<property name="width">2</property>
</packing>
</child>
@@ -113,7 +127,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">5</property>
+ <property name="top_attach">6</property>
<property name="width">2</property>
</packing>
</child>
@@ -127,7 +141,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">6</property>
+ <property name="top_attach">7</property>
<property name="width">2</property>
</packing>
</child>
@@ -142,7 +156,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">7</property>
+ <property name="top_attach">8</property>
<property name="width">2</property>
</packing>
</child>
@@ -157,7 +171,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">8</property>
+ <property name="top_attach">9</property>
<property name="width">2</property>
</packing>
</child>
@@ -170,7 +184,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">9</property>
+ <property name="top_attach">10</property>
<property name="width">2</property>
</packing>
</child>
@@ -184,7 +198,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">10</property>
+ <property name="top_attach">11</property>
<property name="width">2</property>
</packing>
</child>
@@ -227,7 +241,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">11</property>
+ <property name="top_attach">12</property>
<property name="width">2</property>
</packing>
</child>
@@ -242,7 +256,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
<property name="width">2</property>
</packing>
</child>
@@ -256,7 +270,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
<property name="width">2</property>
</packing>
</child>
diff --git a/gtk/gtkimageview.c b/gtk/gtkimageview.c
index 0dcb0ae..4755f6f 100644
--- a/gtk/gtkimageview.c
+++ b/gtk/gtkimageview.c
@@ -222,7 +222,7 @@ gesture_angle_changed_cb (GtkGestureRotate *gesture,
double delta,
GtkWidget *widget)
{
- GtkImageViewPrivate *priv = gtk_image_view_get_instance_private ((GtkImageView *)widget);
+ GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (GTK_IMAGE_VIEW (widget));
double new_angle;
double hupper_before;
double vupper_before;
@@ -231,7 +231,7 @@ gesture_angle_changed_cb (GtkGestureRotate *gesture,
if (!priv->rotate_gesture_enabled)
{
- gtk_gesture_set_state ((GtkGesture *)gesture, GTK_EVENT_SEQUENCE_DENIED);
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
return;
}
@@ -252,17 +252,17 @@ gesture_angle_changed_cb (GtkGestureRotate *gesture,
/* Don't notify */
priv->angle = new_angle;
- gtk_image_view_update_adjustments ((GtkImageView *)widget);
+ gtk_image_view_update_adjustments (GTK_IMAGE_VIEW (widget));
if (priv->fit_allocation)
gtk_widget_queue_draw (widget);
else
gtk_widget_queue_resize (widget);
- gtk_gesture_get_bounding_box_center ((GtkGesture *)gesture, &bb_x, &bb_y);
+ gtk_gesture_get_bounding_box_center (GTK_GESTURE (gesture), &bb_x, &bb_y);
if (priv->hadjustment && priv->vadjustment)
- gtk_image_view_fix_point_rotate ((GtkImageView *)widget,
+ gtk_image_view_fix_point_rotate (GTK_IMAGE_VIEW (widget),
hupper_before,
vupper_before,
bb_x,
@@ -289,6 +289,11 @@ gtk_image_view_compute_bounding_box (GtkImageView *image_view,
double scale;
+ /* XXX
+ * Cache the current bounding box and only recompute if scale/rotation changed
+ */
+
+
if (!priv->image_surface)
{
*width = 0;
@@ -296,7 +301,8 @@ gtk_image_view_compute_bounding_box (GtkImageView *image_view,
return;
}
- gtk_widget_get_allocation ((GtkWidget *)image_view, &alloc);
+ gtk_widget_get_allocation (GTK_WIDGET (image_view), &alloc);
+
image_width = cairo_image_surface_get_width (priv->image_surface);
image_height = cairo_image_surface_get_height (priv->image_surface);
@@ -314,7 +320,7 @@ gtk_image_view_compute_bounding_box (GtkImageView *image_view,
bb_width = MAX (fabs (upper_right_x), fabs (upper_left_x)) * 2;
bb_height = MAX (fabs (upper_right_y), fabs (upper_left_y)) * 2;
-
+ /* XXX The bounding box is 2px too small when fit-allocation is set */
if (priv->scale_set)
@@ -344,15 +350,15 @@ gtk_image_view_compute_bounding_box (GtkImageView *image_view,
// XXX We probably don't want to do that here since it will be called fairly often.
priv->scale = scale;
- g_object_notify_by_pspec ((GObject *)image_view,
+ g_object_notify_by_pspec (G_OBJECT (image_view),
widget_props[PROP_SCALE]);
- *width = bb_width * scale;
+ *width = bb_width * scale;
*height = bb_height * scale;
}
else
{
- *width = bb_width * scale;
+ *width = bb_width * scale;
*height = bb_height * scale;
}
}
@@ -378,8 +384,8 @@ static void
gtk_image_view_update_adjustments (GtkImageView *image_view)
{
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
- int widget_width = gtk_widget_get_allocated_width ((GtkWidget *)image_view);
- int widget_height = gtk_widget_get_allocated_height ((GtkWidget *)image_view);
+ int widget_width = gtk_widget_get_allocated_width (GTK_WIDGET (image_view));
+ int widget_height = gtk_widget_get_allocated_height (GTK_WIDGET (image_view));
if (!priv->hadjustment && !priv->vadjustment)
@@ -449,27 +455,27 @@ gtk_image_view_set_scale_internal (GtkImageView *image_view,
scale = MAX (0, scale);
priv->scale = scale;
- g_object_notify_by_pspec ((GObject *)image_view,
+ g_object_notify_by_pspec (G_OBJECT (image_view),
widget_props[PROP_SCALE]);
if (!priv->scale_set)
{
priv->scale_set = TRUE;
- g_object_notify_by_pspec ((GObject *)image_view,
+ g_object_notify_by_pspec (G_OBJECT (image_view),
widget_props[PROP_SCALE_SET]);
}
if (priv->fit_allocation)
{
priv->fit_allocation = FALSE;
- g_object_notify_by_pspec ((GObject *)image_view,
+ g_object_notify_by_pspec (G_OBJECT (image_view),
widget_props[PROP_FIT_ALLOCATION]);
}
gtk_image_view_update_adjustments (image_view);
- gtk_widget_queue_resize ((GtkWidget *)image_view);
+ gtk_widget_queue_resize (GTK_WIDGET (image_view));
}
static void
@@ -504,7 +510,7 @@ gesture_scale_changed_cb (GtkGestureZoom *gesture,
double delta,
GtkWidget *widget)
{
- GtkImageViewPrivate *priv = gtk_image_view_get_instance_private ((GtkImageView *)widget);
+ GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (GTK_IMAGE_VIEW (widget));
double bb_x;
double bb_y;
double new_scale;
@@ -512,7 +518,7 @@ gesture_scale_changed_cb (GtkGestureZoom *gesture,
if (!priv->rotate_gesture_enabled)
{
- gtk_gesture_set_state ((GtkGesture *)gesture, GTK_EVENT_SEQUENCE_DENIED);
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
return;
}
@@ -522,19 +528,19 @@ gesture_scale_changed_cb (GtkGestureZoom *gesture,
priv->gesture_start_scale = priv->scale;
}
- gtk_gesture_get_bounding_box_center ((GtkGesture *)gesture, &bb_x, &bb_y);
+ gtk_gesture_get_bounding_box_center (GTK_GESTURE (gesture), &bb_x, &bb_y);
new_scale = priv->gesture_start_scale * delta;
/* Don't emit */
priv->scale = new_scale;
- gtk_image_view_update_adjustments ((GtkImageView *)widget);
+ gtk_image_view_update_adjustments (GTK_IMAGE_VIEW (widget));
- /*gtk_image_view_set_scale_internal ((GtkImageView *)widget,*/
- /*new_scale);*/
+ gtk_image_view_set_scale_internal (GTK_IMAGE_VIEW (widget),
+ new_scale);
if (priv->hadjustment || priv->vadjustment)
- gtk_image_view_fix_point ((GtkImageView *)widget,
+ gtk_image_view_fix_point (GTK_IMAGE_VIEW (widget),
old_scale,
bb_x,
bb_y);
@@ -546,9 +552,10 @@ gtk_image_view_init (GtkImageView *image_view)
{
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
GtkStyleContext *sc = gtk_widget_get_style_context ((GtkWidget *)image_view);
+ GtkWidget *widget = GTK_WIDGET (image_view);
- gtk_widget_set_can_focus ((GtkWidget *)image_view, TRUE);
- gtk_widget_set_has_window ((GtkWidget *)image_view, FALSE);
+ gtk_widget_set_can_focus (widget, TRUE);
+ gtk_widget_set_has_window (widget, FALSE);
priv->scale = 1.0;
priv->angle = 0.0;
@@ -557,14 +564,14 @@ gtk_image_view_init (GtkImageView *image_view)
priv->scale_set = FALSE;
priv->rotate_gesture_enabled = TRUE;
priv->zoom_gesture_enabled = TRUE;
- priv->rotate_gesture = gtk_gesture_rotate_new ((GtkWidget *)image_view);
- gtk_event_controller_set_propagation_phase ((GtkEventController *)priv->rotate_gesture,
+ priv->rotate_gesture = gtk_gesture_rotate_new (widget);
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->rotate_gesture),
GTK_PHASE_CAPTURE);
g_signal_connect (priv->rotate_gesture, "angle-changed", (GCallback)gesture_angle_changed_cb, image_view);
g_signal_connect (priv->rotate_gesture, "end", (GCallback)gesture_rotate_end_cb, image_view);
g_signal_connect (priv->rotate_gesture, "cancel", (GCallback)gesture_rotate_cancel_cb, image_view);
- priv->zoom_gesture = gtk_gesture_zoom_new ((GtkWidget *)image_view);
+ priv->zoom_gesture = gtk_gesture_zoom_new (widget);
g_signal_connect (priv->zoom_gesture, "scale-changed", (GCallback)gesture_scale_changed_cb, image_view);
g_signal_connect (priv->zoom_gesture, "end", (GCallback)gesture_zoom_end_cb, image_view);
g_signal_connect (priv->zoom_gesture, "cancel", (GCallback)gesture_zoom_cancel_cb, image_view);
@@ -637,7 +644,7 @@ frameclock_cb (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
- GtkImageViewPrivate *priv = gtk_image_view_get_instance_private ((GtkImageView *)widget);
+ GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (GTK_IMAGE_VIEW (widget));
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
double t = (now - priv->angle_transition_start) / TRANSITION_DURATION;
@@ -670,8 +677,8 @@ gtk_image_view_animate_to_angle (GtkImageView *image_view,
priv->transition_start_angle = start_angle;
priv->transition_end_angle = priv->angle;
- priv->angle_transition_start = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock ((GtkWidget
*)image_view));
- gtk_widget_add_tick_callback ((GtkWidget *)image_view, frameclock_cb, NULL, NULL);
+ priv->angle_transition_start = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (GTK_WIDGET
(image_view)));
+ gtk_widget_add_tick_callback (GTK_WIDGET (image_view), frameclock_cb, NULL, NULL);
}
static void
@@ -701,7 +708,7 @@ gtk_image_view_do_snapping (GtkImageView *image_view,
static gboolean
gtk_image_view_draw (GtkWidget *widget, cairo_t *ct)
{
- GtkImageView *image_view = (GtkImageView *)widget;
+ GtkImageView *image_view = GTK_IMAGE_VIEW (widget);
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
GtkStyleContext *sc = gtk_widget_get_style_context (widget);
int draw_x;
@@ -732,7 +739,9 @@ gtk_image_view_draw (GtkWidget *widget, cairo_t *ct)
if (!priv->image_surface)
return GDK_EVENT_PROPAGATE;
- gtk_image_view_compute_bounding_box (image_view, &draw_width, &draw_height, &scale);
+ gtk_image_view_compute_bounding_box (image_view,
+ &draw_width, &draw_height,
+ &scale);
if (draw_width == 0 || draw_height == 0)
@@ -742,6 +751,7 @@ gtk_image_view_draw (GtkWidget *widget, cairo_t *ct)
int image_width = cairo_image_surface_get_width (priv->image_surface) * scale;
int image_height = cairo_image_surface_get_height (priv->image_surface) * scale;
+
if (priv->hadjustment && priv->vadjustment)
{
draw_x = (gtk_adjustment_get_page_size (priv->hadjustment) - image_width) / 2;
@@ -749,7 +759,7 @@ gtk_image_view_draw (GtkWidget *widget, cairo_t *ct)
}
else
{
- draw_x = (widget_width - image_width) / 2;
+ draw_x = (widget_width - image_width) / 2;
draw_y = (widget_height - image_height) / 2;
}
@@ -773,15 +783,21 @@ gtk_image_view_draw (GtkWidget *widget, cairo_t *ct)
}
-
/* Rotate around the center */
- cairo_translate (ct, draw_x + (image_width / 2.0), draw_y + (image_height / 2.0));
+ cairo_translate (ct,
+ draw_x + (image_width / 2.0),
+ draw_y + (image_height / 2.0));
cairo_rotate (ct, DEG_TO_RAD (priv->angle));
- cairo_translate (ct, -draw_x - (image_width / 2.0), -draw_y - (image_height / 2.0));
+ cairo_translate (ct,
+ - draw_x - (image_width / 2.0),
+ - draw_y - (image_height / 2.0));
- cairo_scale (ct, scale, scale);
- cairo_set_source_surface (ct, priv->image_surface, draw_x / scale, draw_y / scale);
+ cairo_scale (ct, scale * priv->scale_factor, scale * priv->scale_factor);
+ cairo_set_source_surface (ct,
+ priv->image_surface,
+ draw_x / scale / priv->scale_factor,
+ draw_y / scale / priv->scale_factor);
cairo_pattern_set_filter (cairo_get_source (ct), CAIRO_FILTER_FAST);
cairo_fill (ct);
cairo_restore (ct);
@@ -1587,25 +1603,25 @@ gtk_image_view_update_surface (GtkImageView *image_view,
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
int new_width = gdk_pixbuf_get_width (frame);
int new_height = gdk_pixbuf_get_height (frame);
- int widget_scale = gtk_widget_get_scale_factor ((GtkWidget *)image_view);
+ int widget_scale = gtk_widget_get_scale_factor (GTK_WIDGET (image_view));
gboolean resize = TRUE;
int real_width = (new_width * scale_factor) / widget_scale;
int real_height = (new_height * scale_factor) / widget_scale;
if (!priv->image_surface ||
cairo_image_surface_get_width (priv->image_surface) != real_width ||
- cairo_image_surface_get_height (priv->image_surface) != real_height)
+ cairo_image_surface_get_height (priv->image_surface) != real_height ||
+ priv->scale_factor != scale_factor)
{
- GdkWindow *window = gtk_widget_get_window ((GtkWidget *)image_view);
- int surface_scale = gtk_widget_get_scale_factor ((GtkWidget *)image_view);
+ GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (image_view));
cairo_surface_t *new_surface = gdk_cairo_surface_create_from_pixbuf (frame,
- surface_scale,
+ scale_factor,
window);
g_assert (new_surface != NULL);
/* replace_surface will emit prepare-image */
gtk_image_view_replace_surface (image_view,
new_surface,
- surface_scale);
+ scale_factor);
}
else
{
@@ -1615,11 +1631,10 @@ gtk_image_view_update_surface (GtkImageView *image_view,
}
g_assert (priv->image_surface != NULL);
-
if (resize)
- gtk_widget_queue_resize ((GtkWidget *)image_view);
+ gtk_widget_queue_resize (GTK_WIDGET (image_view));
else
- gtk_widget_queue_draw ((GtkWidget *)image_view);
+ gtk_widget_queue_draw (GTK_WIDGET (image_view));
}
static void
@@ -1688,7 +1703,7 @@ gtk_image_view_load_image_contents (GTask *task,
{
GtkImageView *image_view = source_object;
LoadTaskData *data = task_data;
- GFile *file = (GFile *)data->source;
+ GFile *file = G_FILE (data->source);
GError *error = NULL;
GFileInputStream *in_stream;
@@ -1719,7 +1734,7 @@ gtk_image_view_load_from_input_stream (GTask *task,
{
GtkImageView *image_view = source_object;
LoadTaskData *data = task_data;
- GInputStream *in_stream = (GInputStream *)data->source;
+ GInputStream *in_stream = G_INPUT_STREAM (data->source);
GError *error = NULL;
gtk_image_view_load_image_from_stream (image_view,
@@ -1860,7 +1875,7 @@ gtk_image_view_set_surface (GtkImageView *image_view,
else
{
priv->scale = 1.0;
- g_object_notify_by_pspec ((GObject *)image_view,
+ g_object_notify_by_pspec (G_OBJECT (image_view),
widget_props[PROP_SCALE]);
}
@@ -1880,9 +1895,9 @@ gtk_image_view_set_surface (GtkImageView *image_view,
gtk_image_view_update_adjustments (image_view);
if (priv->fit_allocation)
- gtk_widget_queue_draw ((GtkWidget *)image_view);
+ gtk_widget_queue_draw (GTK_WIDGET (image_view));
else
- gtk_widget_queue_resize ((GtkWidget *)image_view);
+ gtk_widget_queue_resize (GTK_WIDGET (image_view));
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]