summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac17
-rw-r--r--libview/ev-pixbuf-cache.c64
-rw-r--r--libview/ev-view.c32
3 files changed, 91 insertions, 22 deletions
diff --git a/configure.ac b/configure.ac
index ba57b81c..36c7fe26 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,6 +123,23 @@ PKG_CHECK_MODULES(GMODULE, gmodule-2.0 >= $GLIB_REQUIRED)
PKG_CHECK_MODULES([SHELL_CORE],[libxml-2.0 >= $LIBXML_REQUIRED gtk+-3.0 >= $GTK_REQUIRED gio-2.0 >= $GLIB_REQUIRED gthread-2.0 x11])
+# Although GTK+ 3.10 includes hi-dpi functionality, it does not require a cairo with
+# cairo_surface_set_device_scale(), which we also need if we're to support hi-dpi,
+# so we need check for that explicity.
+
+atril_save_LIBS=$LIBS
+LIBS="$LIBS $LIBVIEW_LIBS"
+AC_CHECK_FUNCS(cairo_surface_set_device_scale)
+LIBS=$atril_save_LIBS
+
+AC_MSG_CHECKING([for hi-dpi support])
+if test "$ac_cv_func_cairo_surface_set_device_scale" = yes ; then
+ AC_DEFINE([HAVE_HIDPI_SUPPORT], [1], [Define if cairo and GTK+ have necessary functions for hi-dpi])
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
dnl
dnl zlib support
dnl
diff --git a/libview/ev-pixbuf-cache.c b/libview/ev-pixbuf-cache.c
index 409b9c39..506d1316 100644
--- a/libview/ev-pixbuf-cache.c
+++ b/libview/ev-pixbuf-cache.c
@@ -14,6 +14,9 @@ typedef struct _CacheJobInfo
/* Data we get from rendering */
cairo_surface_t *surface;
+ /* Device scale factor of target widget */
+ int device_scale;
+
/* Selection data.
* Selection_points are the coordinates encapsulated in selection.
* target_points is the target selection size. */
@@ -235,6 +238,27 @@ ev_pixbuf_cache_set_max_size (EvPixbufCache *pixbuf_cache,
pixbuf_cache->max_size = max_size;
}
+static int
+get_device_scale (EvPixbufCache *pixbuf_cache)
+{
+#ifdef HAVE_HIDPI_SUPPORT
+ return gtk_widget_get_scale_factor (pixbuf_cache->view);
+#else
+ return 1;
+#endif
+}
+
+static void
+set_device_scale_on_surface (cairo_surface_t *surface,
+ int device_scale)
+{
+#ifdef HAVE_HIDPI_SUPPORT
+ cairo_surface_set_device_scale (surface, device_scale, device_scale);
+#else
+ g_return_if_fail (device_scale != 1);
+#endif
+}
+
static void
copy_job_to_job_info (EvJobRender *job_render,
CacheJobInfo *job_info,
@@ -244,6 +268,7 @@ copy_job_to_job_info (EvJobRender *job_render,
cairo_surface_destroy (job_info->surface);
}
job_info->surface = cairo_surface_reference (job_render->surface);
+ set_device_scale_on_surface (job_info->surface, job_info->device_scale);
if (pixbuf_cache->inverted_colors) {
ev_document_misc_invert_surface (job_info->surface);
}
@@ -262,6 +287,7 @@ copy_job_to_job_info (EvJobRender *job_render,
job_info->selection_points = job_render->selection_points;
job_info->selection_region = cairo_region_reference (job_render->selection_region);
job_info->selection = cairo_surface_reference (job_render->selection);
+ set_device_scale_on_surface (job_info->selection, job_info->device_scale);
g_assert (job_info->selection_points.x1 >= 0);
job_info->points_set = TRUE;
}
@@ -307,20 +333,24 @@ check_job_size_and_unref (EvPixbufCache *pixbuf_cache,
gfloat scale)
{
gint width, height;
+ gint device_scale;
g_assert (job_info);
if (job_info->job == NULL)
return;
- _get_page_size_for_scale_and_rotation (job_info->job->document,
- EV_JOB_RENDER (job_info->job)->page,
- scale,
- EV_JOB_RENDER (job_info->job)->rotation,
- &width, &height);
- if (width == EV_JOB_RENDER (job_info->job)->target_width &&
- height == EV_JOB_RENDER (job_info->job)->target_height)
- return;
+ device_scale = get_device_scale (pixbuf_cache);
+ if (job_info->device_scale == device_scale) {
+ _get_page_size_for_scale_and_rotation (job_info->job->document,
+ EV_JOB_RENDER (job_info->job)->page,
+ scale,
+ EV_JOB_RENDER (job_info->job)->rotation,
+ &width, &height);
+ if (width * device_scale == EV_JOB_RENDER (job_info->job)->target_width &&
+ height * device_scale == EV_JOB_RENDER (job_info->job)->target_height)
+ return;
+ }
g_signal_handlers_disconnect_by_func (job_info->job,
G_CALLBACK (job_finished_cb),
@@ -634,6 +664,7 @@ add_job (EvPixbufCache *pixbuf_cache,
gfloat scale,
EvJobPriority priority)
{
+ job_info->device_scale = get_device_scale (pixbuf_cache);
job_info->page_ready = FALSE;
if (job_info->region)
@@ -641,8 +672,10 @@ add_job (EvPixbufCache *pixbuf_cache,
job_info->region = region ? cairo_region_reference (region) : NULL;
job_info->job = ev_job_render_new (pixbuf_cache->document,
- page, rotation, scale,
- width, height);
+ page, rotation,
+ scale * job_info->device_scale,
+ width * job_info->device_scale,
+ height * job_info->device_scale);
if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
GdkColor text, base;
@@ -667,6 +700,7 @@ add_job_if_needed (EvPixbufCache *pixbuf_cache,
gfloat scale,
EvJobPriority priority)
{
+ gint device_scale = get_device_scale (pixbuf_cache);
gint width, height;
if (job_info->job)
@@ -677,8 +711,9 @@ add_job_if_needed (EvPixbufCache *pixbuf_cache,
&width, &height);
if (job_info->surface &&
- cairo_image_surface_get_width (job_info->surface) == width &&
- cairo_image_surface_get_height (job_info->surface) == height)
+ job_info->device_scale == device_scale &&
+ cairo_image_surface_get_width (job_info->surface) == width * device_scale &&
+ cairo_image_surface_get_height (job_info->surface) == height * device_scale)
return;
/* Free old surfaces for non visible pages */
@@ -949,7 +984,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
/* Now, lets see if we need to resize the image. If we do, we clear the
* old one. */
- clear_selection_if_needed (pixbuf_cache, job_info, page, scale);
+ clear_selection_if_needed (pixbuf_cache, job_info, page, scale * job_info->device_scale);
/* Finally, we see if the two scales are the same, and get a new pixbuf
* if needed. We do this synchronously for now. At some point, we
@@ -973,7 +1008,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
}
ev_page = ev_document_get_page (pixbuf_cache->document, page);
- rc = ev_render_context_new (ev_page, 0, scale);
+ rc = ev_render_context_new (ev_page, 0, scale * job_info->device_scale);
g_object_unref (ev_page);
if (job_info->selection_region)
@@ -991,6 +1026,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
old_points,
job_info->selection_style,
&text, &base);
+ set_device_scale_on_surface (job_info->selection, job_info->device_scale);
job_info->selection_points = job_info->target_points;
g_object_unref (rc);
ev_document_doc_mutex_unlock ();
diff --git a/libview/ev-view.c b/libview/ev-view.c
index b7410d87..4584bd46 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -4463,6 +4463,7 @@ draw_one_page (EvView *view,
cairo_surface_t *page_surface = NULL;
gint selection_width, selection_height;
cairo_surface_t *selection_surface = NULL;
+ double device_scale_x = 1, device_scale_y = 1;
page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
@@ -4475,6 +4476,10 @@ draw_one_page (EvView *view,
return;
}
+#ifdef HAVE_HIDPI_SUPPORT
+ cairo_surface_get_device_scale (page_surface, &device_scale_x, &device_scale_y);
+#endif
+
if (page == current_page)
hide_loading_window (view);
@@ -4490,13 +4495,13 @@ draw_one_page (EvView *view,
cairo_pattern_set_filter (cairo_get_source (cr),
CAIRO_FILTER_FAST);
cairo_scale (cr,
- (gdouble)width / page_width,
- (gdouble)height / page_height);
+ (gdouble)width / page_width * device_scale_x,
+ (gdouble)height / page_height * device_scale_y);
}
cairo_surface_set_device_offset (page_surface,
- overlap.x - real_page_area.x,
- overlap.y - real_page_area.y);
+ (overlap.x - real_page_area.x) * device_scale_x,
+ (overlap.y - real_page_area.y) * device_scale_y);
cairo_set_source_surface (cr, page_surface, 0, 0);
cairo_paint (cr);
cairo_restore (cr);
@@ -4525,13 +4530,13 @@ draw_one_page (EvView *view,
cairo_pattern_set_filter (cairo_get_source (cr),
CAIRO_FILTER_FAST);
cairo_scale (cr,
- (gdouble)width / selection_width,
- (gdouble)height / selection_height);
+ (gdouble)width / selection_width * device_scale_x,
+ (gdouble)height / selection_height * device_scale_y);
}
cairo_surface_set_device_offset (selection_surface,
- overlap.x - real_page_area.x,
- overlap.y - real_page_area.y);
+ (overlap.x - real_page_area.x) * device_scale_x,
+ (overlap.y - real_page_area.y) * device_scale_y);
cairo_set_source_surface (cr, selection_surface, 0, 0);
cairo_paint (cr);
@@ -4873,6 +4878,14 @@ ev_view_class_init (EvViewClass *class)
}
static void
+on_notify_scale_factor (EvView *view,
+ GParamSpec *pspec)
+{
+ if (view->document)
+ view_update_range_and_current_page (view);
+}
+
+static void
ev_view_init (EvView *view)
{
GtkStyleContext *context;
@@ -4918,6 +4931,9 @@ ev_view_init (EvView *view)
view->pending_scroll = SCROLL_TO_KEEP_POSITION;
view->jump_to_find_result = TRUE;
view->highlight_find_results = FALSE;
+
+ g_signal_connect (view, "notify::scale-factor",
+ G_CALLBACK (on_notify_scale_factor), NULL);
}
/*** Callbacks ***/