[gnome-photos/gnome-3-18] gegl-gtk-view, gegl-gtk-view-helper: Fix HiDpi rendering



commit dea5c9f8ee75d5e6636dfd92c9b5d9e91a58b2d4
Author: Debarshi Ray <debarshir gnome org>
Date:   Mon Nov 2 11:17:33 2015 +0100

    gegl-gtk-view, gegl-gtk-view-helper: Fix HiDpi rendering
    
    Unlike Cairo and GTK+, GEGL is unaware of the scale factor and only
    deals in device pixels. We should take the scale factor into account
    so that we can exploit the higher DPI to render sharper images by
    pumping in more pixels.
    
    Since the GdkWindow that we are drawing on has a scale factor, we
    set up our Cairo image surface to have the same. Otherwise, the pixels
    will be upsampled when drawing to the window.
    
    We use the allocation in device pixels when calculating the scaling
    factor so that GEGL can pump in more pixels to make it look sharper.
    Same for calculating the co-ordinates of the rectangle to render from
    the GeglNode.
    
    We use the widget's allocation in device pixels to decide whether an
    image is big enough to be downscaled. Therefore, if it is small enough
    to fit on a HiDpi display, but not on LoDpi, it is not considered as
    'big'. It isn't scaled, and will look sharper and smaller on HiDpi as
    compared to LoDpi. The other option would be to upscale it to take up
    the extra pixels, but I think a sharper render is a better default.
    Plus we don't want to optimize for tiny images where the smaller size
    would make them unrecognizable. We can let users adjust the zoom if it
    proves to be an issue.
    
    This makes HiDpi screenshots render at the same sharpness and size as
    the real widgets on a similar display. However, LoDpi screenshots will
    look smaller on HiDpi, just as HiDpi screenshots will look larger on
    LoDpi. Since it is more common to view screenshots taken on the same
    computer, this is an acceptable trade-off for the time being.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=747446

 src/gegl-gtk-view-helper.c |   25 +++++++++++++++----------
 src/gegl-gtk-view-helper.h |    3 ++-
 src/gegl-gtk-view.c        |    5 ++++-
 3 files changed, 21 insertions(+), 12 deletions(-)
---
diff --git a/src/gegl-gtk-view-helper.c b/src/gegl-gtk-view-helper.c
index 895cd0b..0013007 100644
--- a/src/gegl-gtk-view-helper.c
+++ b/src/gegl-gtk-view-helper.c
@@ -83,6 +83,7 @@ view_helper_init(ViewHelper *self)
     self->x           = 0;
     self->y           = 0;
     self->scale       = 1.0;
+    self->scale_factor = 1;
     self->autoscale_policy = GEGL_GTK_VIEW_AUTOSCALE_CONTENT;
     self->block = FALSE;
 
@@ -137,10 +138,12 @@ update_autoscale(ViewHelper *self)
         float delta_x;
         float delta_y;
         float scale = 1.0;
+        const gint real_viewport_height = viewport.height * self->scale_factor;
+        const gint real_viewport_width = viewport.width * self->scale_factor;
 
-        if (bbox.width > viewport.width || bbox.height > viewport.height) {
-            float width_ratio = bbox.width / (float)viewport.width;
-            float height_ratio = bbox.height / (float)viewport.height;
+        if (bbox.width > real_viewport_width || bbox.height > real_viewport_height) {
+            float width_ratio = bbox.width / (float)real_viewport_width;
+            float height_ratio = bbox.height / (float)real_viewport_height;
             float max_ratio = width_ratio >= height_ratio ? width_ratio : height_ratio;
 
             scale = 1.0 / max_ratio;
@@ -152,8 +155,8 @@ update_autoscale(ViewHelper *self)
         self->scale = scale;
 
         /* At this point, viewport is definitely bigger than bbox. */
-        delta_x = (viewport.width - bbox.width) / 2.0;
-        delta_y = (viewport.height - bbox.height) / 2.0;
+        delta_x = (real_viewport_width - bbox.width) / 2.0;
+        delta_y = (real_viewport_height - bbox.height) / 2.0;
         self->x = -delta_x;
         self->y = -delta_y;
     }
@@ -194,10 +197,10 @@ view_helper_draw(ViewHelper *self, cairo_t *cr, GdkRectangle *rect)
     gint64          end;
     gint64          start;
 
-    roi.x = (gint) self->x + rect->x;
-    roi.y = (gint) self->y + rect->y;
-    roi.width  = rect->width;
-    roi.height = rect->height;
+    roi.x = (gint) self->x + rect->x * self->scale_factor;
+    roi.y = (gint) self->y + rect->y * self->scale_factor;
+    roi.width  = rect->width * self->scale_factor;
+    roi.height = rect->height * self->scale_factor;
 
     stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, roi.width);
     buf = g_malloc0(stride * roi.height);
@@ -219,6 +222,7 @@ view_helper_draw(ViewHelper *self, cairo_t *cr, GdkRectangle *rect)
               CAIRO_FORMAT_ARGB32,
               roi.width, roi.height,
               stride);
+    cairo_surface_set_device_scale (surface, (gdouble) self->scale_factor, (gdouble) self->scale_factor);
     cairo_set_source_surface(cr, surface, rect->x, rect->y);
     cairo_paint(cr);
 
@@ -228,9 +232,10 @@ view_helper_draw(ViewHelper *self, cairo_t *cr, GdkRectangle *rect)
 }
 
 void
-view_helper_set_allocation(ViewHelper *self, GdkRectangle *allocation)
+view_helper_set_allocation(ViewHelper *self, GdkRectangle *allocation, gint scale_factor)
 {
     self->widget_allocation = *allocation;
+    self->scale_factor = scale_factor;
     update_autoscale(self);
 }
 
diff --git a/src/gegl-gtk-view-helper.h b/src/gegl-gtk-view-helper.h
index 583abee..19af9ae 100644
--- a/src/gegl-gtk-view-helper.h
+++ b/src/gegl-gtk-view-helper.h
@@ -45,6 +45,7 @@ struct _ViewHelper {
     gfloat         x;
     gfloat         y;
     gdouble        scale;
+    gint           scale_factor;
     gboolean       block;    /* blocking render */
     GeglGtkViewAutoscale autoscale_policy;
 
@@ -63,7 +64,7 @@ GType view_helper_get_type(void) G_GNUC_CONST;
 ViewHelper *view_helper_new(void);
 
 void view_helper_draw(ViewHelper *self, cairo_t *cr, GdkRectangle *rect);
-void view_helper_set_allocation(ViewHelper *self, GdkRectangle *allocation);
+void view_helper_set_allocation(ViewHelper *self, GdkRectangle *allocation, gint scale_factor);
 
 void view_helper_set_node(ViewHelper *self, GeglNode *node);
 GeglNode *view_helper_get_node(ViewHelper *self);
diff --git a/src/gegl-gtk-view.c b/src/gegl-gtk-view.c
index 8f1d471..0b1dcdc 100644
--- a/src/gegl-gtk-view.c
+++ b/src/gegl-gtk-view.c
@@ -363,7 +363,10 @@ static void
 size_allocate(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data)
 {
     GeglGtkView *self = GEGL_GTK_VIEW(widget);
-    view_helper_set_allocation(GET_PRIVATE(self), allocation);
+    gint scale_factor;
+
+    scale_factor = gtk_widget_get_scale_factor (widget);
+    view_helper_set_allocation(GET_PRIVATE(self), allocation, scale_factor);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]