mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2024-12-29 11:36:01 +01:00
Merge branch 'knuesel/zathura-feature/hidpi' into develop
This commit is contained in:
commit
19645cf608
9 changed files with 152 additions and 6 deletions
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue