Merge branch 'knuesel/zathura-feature/hidpi' into develop

This commit is contained in:
Sebastian Ramacher 2018-01-24 22:16:21 +01:00
commit 19645cf608
9 changed files with 152 additions and 6 deletions

View file

@ -26,7 +26,7 @@ GLIB_MIN_VERSION = 2.50
GLIB_PKG_CONFIG_NAME = glib-2.0
# GTK
GTK_VERSION_CHECK ?= 1
GTK_MIN_VERSION = 3.6
GTK_MIN_VERSION = 3.10
GTK_PKG_CONFIG_NAME = gtk+-3.0
# pkg-config binary

View file

@ -216,6 +216,29 @@ cb_refresh_view(GtkWidget* GIRARA_UNUSED(view), gpointer data)
statusbar_page_number_update(zathura);
}
void
cb_scale_factor(GObject* object, GParamSpec* UNUSED(pspec), gpointer data)
{
zathura_t* zathura = data;
if (zathura == NULL || zathura->document == NULL) {
return;
}
int new_factor = gtk_widget_get_scale_factor(GTK_WIDGET(object));
if (new_factor == 0) {
girara_debug("Ignoring new device scale factor = 0");
return;
}
zathura_device_factors_t current = zathura_document_get_device_factors(zathura->document);
if (fabs(new_factor - current.x) >= DBL_EPSILON ||
fabs(new_factor - current.y) >= DBL_EPSILON) {
zathura_document_set_device_factors(zathura->document, new_factor, new_factor);
girara_debug("New device scale factor: %d", new_factor);
render_all(zathura);
}
}
void
cb_page_layout_value_changed(girara_session_t* session, const char* name, girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
{

View file

@ -79,6 +79,18 @@ void cb_view_vadjustment_changed(GtkAdjustment *adjustment, gpointer data);
*/
void cb_refresh_view(GtkWidget* view, gpointer data);
/**
* This function gets called when the view widget scale factor changes (e.g.
* when moving from a regular to a HiDPI screen).
*
* It records the new value and triggers a re-rendering of the document.
*
* @param object The view widget
* @param pspec The GParamSpec for the scale-factor property
* @param gpointer The zathura instance
*/
void cb_scale_factor(GObject* object, GParamSpec* pspec, gpointer data);
/**
* This function gets called when the value of the "pages-per-row"
* variable changes

View file

@ -5,6 +5,7 @@
#include <limits.h>
#include <glib.h>
#include <gio/gio.h>
#include <math.h>
#include <girara/datastructures.h>
#include <girara/utils.h>
@ -36,6 +37,7 @@ struct zathura_document_s {
double cell_height; /**< height of a page cell in the document (not ransformed by scale and rotation) */
unsigned int view_width; /**< width of current viewport */
unsigned int view_height; /**< height of current viewport */
zathura_device_factors_t device_factors; /**< x and y device scale factors (for e.g. HiDPI) */
unsigned int pages_per_row; /**< number of pages in a row */
unsigned int first_page_column; /**< column of the first page */
unsigned int page_padding; /**< padding between pages */
@ -132,6 +134,8 @@ zathura_document_open(zathura_t* zathura, const char* path, const char* uri,
document->cell_height = 0.0;
document->view_height = 0;
document->view_width = 0;
document->device_factors.x = 1.0;
document->device_factors.y = 1.0;
document->position_x = 0.0;
document->position_y = 0.0;
@ -500,6 +504,34 @@ zathura_document_get_viewport_size(zathura_document_t* document,
*width = document->view_width;
}
void
zathura_document_set_device_factors(zathura_document_t* document,
double x_factor, double y_factor)
{
if (document == NULL) {
return;
}
if (fabs(x_factor) < DBL_EPSILON || fabs(y_factor) < DBL_EPSILON) {
girara_debug("Ignoring new device factors %f and %f: too small",
x_factor, y_factor);
return;
}
document->device_factors.x = x_factor;
document->device_factors.y = y_factor;
}
zathura_device_factors_t
zathura_document_get_device_factors(zathura_document_t* document)
{
if (document == NULL) {
/* The function is guaranteed to not return zero values */
return (zathura_device_factors_t){1.0, 1.0};
}
return document->device_factors;
}
void
zathura_document_get_cell_size(zathura_document_t* document,
unsigned int* height, unsigned int* width)

View file

@ -249,6 +249,24 @@ void
zathura_document_get_viewport_size(zathura_document_t* document,
unsigned int *height, unsigned int* width);
/**
* Set the device scale factors (e.g. for HiDPI). These are generally integers
* and equal for x and y. These scaling factors are only used when rendering to
* the screen.
*
* @param[in] x_factor,yfactor The x and y scale factors
*/
void
zathura_document_set_device_factors(zathura_document_t* document,
double x_factor, double y_factor);
/**
* Return the current device scale factors (guaranteed to be non-zero).
*
* @return The x and y device scale factors
*/
zathura_device_factors_t
zathura_document_get_device_factors(zathura_document_t* document);
/**
* Return the size of a cell from the document's layout table in pixels. Assumes
* that the table is homogeneous (i.e. every cell has the same dimensions). It

View file

@ -409,6 +409,30 @@ zathura_page_widget_get_property(GObject* object, guint prop_id, GValue* value,
}
}
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,14,0)
static zathura_device_factors_t
get_safe_device_factors(cairo_surface_t* surface)
{
zathura_device_factors_t factors;
cairo_surface_get_device_scale(surface, &factors.x, &factors.y);
if (fabs(factors.x) < DBL_EPSILON) {
factors.x = 1.0;
}
if (fabs(factors.y) < DBL_EPSILON) {
factors.y = 1.0;
}
return factors;
}
#else
static zathura_device_factors_t
get_safe_device_factors(cairo_surface_t* UNUSED(surface))
{
return (zathura_device_factors_t){1.0, 1.0};
}
#endif
static gboolean
zathura_page_widget_draw(GtkWidget* widget, cairo_t* cairo)
{
@ -445,8 +469,13 @@ zathura_page_widget_draw(GtkWidget* widget, cairo_t* cairo)
} else {
const unsigned int height = cairo_image_surface_get_height(priv->thumbnail);
const unsigned int width = cairo_image_surface_get_width(priv->thumbnail);
const unsigned int pheight = (rotation % 180 ? page_width : page_height);
const unsigned int pwidth = (rotation % 180 ? page_height : page_width);
unsigned int pheight = (rotation % 180 ? page_width : page_height);
unsigned int pwidth = (rotation % 180 ? page_height : page_width);
/* note: this always returns 1 and 1 if Cairo too old for device scale API */
zathura_device_factors_t device = get_safe_device_factors(priv->thumbnail);
pwidth *= device.x;
pheight *= device.y;
cairo_scale(cairo, pwidth / (double)width, pheight / (double)height);
cairo_set_source_surface(cairo, priv->thumbnail, 0, 0);
@ -625,8 +654,14 @@ draw_thumbnail_image(cairo_surface_t* surface, size_t max_size)
width = width * scale;
height = height * scale;
/* note: this always returns 1 and 1 if Cairo too old for device scale API */
zathura_device_factors_t device = get_safe_device_factors(surface);
const unsigned int user_width = width / device.x;
const unsigned int user_height = height / device.y;
/* create thumbnail surface, taking width and height as device sizes */
cairo_surface_t *thumbnail;
thumbnail = cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR, width, height);
thumbnail = cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR, user_width, user_height);
if (thumbnail == NULL) {
return NULL;
}

View file

@ -732,20 +732,30 @@ render(render_job_t* job, ZathuraRenderRequest* request, ZathuraRenderer* render
unsigned int page_width = 0;
unsigned int page_height = 0;
/* page size in points */
zathura_document_t* document = zathura_page_get_document(page);
const double height = zathura_page_get_height(page);
const double width = zathura_page_get_width(page);
/* page size in user pixels base on document zoom: 100% results in 1 pixel per point */
const double real_scale = page_calc_height_width(document, height, width,
&page_height, &page_width,
false);
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,14,0)
zathura_device_factors_t device_factors = zathura_document_get_device_factors(document);
page_width *= device_factors.x;
page_height *= device_factors.y;
#endif
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
page_width, page_height);
if (surface == NULL) {
return false;
}
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,14,0)
cairo_surface_set_device_scale(surface, device_factors.x, device_factors.y);
#endif
if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy(surface);
return false;
@ -759,11 +769,11 @@ render(render_job_t* job, ZathuraRenderRequest* request, ZathuraRenderer* render
cairo_save(cairo);
cairo_set_source_rgb(cairo, 1, 1, 1);
cairo_rectangle(cairo, 0, 0, page_width, page_height);
cairo_fill(cairo);
cairo_paint(cairo);
cairo_restore(cairo);
cairo_save(cairo);
/* apply scale (used by e.g. Poppler as pixels per point) */
if (fabs(real_scale - 1.0f) > FLT_EPSILON) {
cairo_scale(cairo, real_scale, real_scale);
}

View file

@ -271,4 +271,13 @@ void zathura_document_information_entry_free(zathura_document_information_entry_
*/
typedef struct zathura_content_type_context_s zathura_content_type_context_t;
/**
* Device scaling structure.
*/
typedef struct zathura_device_factors_s
{
double x;
double y;
} zathura_device_factors_t;
#endif // TYPES_H

View file

@ -153,6 +153,9 @@ init_ui(zathura_t* zathura)
g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view",
G_CALLBACK(cb_refresh_view), zathura);
g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view),
"notify::scale-factor", G_CALLBACK(cb_scale_factor), zathura);
/* page view */
zathura->ui.page_widget = gtk_grid_new();
gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
@ -956,6 +959,10 @@ document_open(zathura_t* zathura, const char* path, const char* uri, const char*
const unsigned int view_height = (unsigned int)floor(gtk_adjustment_get_page_size(vadjustment));
zathura_document_set_viewport_height(zathura->document, view_height);
/* get initial device scale */
int device_factor = gtk_widget_get_scale_factor(zathura->ui.session->gtk.view);
zathura_document_set_device_factors(zathura->document, device_factor, device_factor);
/* create blank pages */
zathura->pages = calloc(number_of_pages, sizeof(GtkWidget*));
if (zathura->pages == NULL) {