mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2024-12-29 11:36:01 +01:00
HiDPI: refactor handling of device scale factors
The document scale factors are now guaranteed to be non-zero. A new Cairo helper function get_safe_device_factors() and a type zathura_device_factors_t are introduced to simplify the code and avoid some #ifdef blocks.
This commit is contained in:
parent
9cf3239708
commit
4e9f8a7b1d
7 changed files with 85 additions and 62 deletions
|
@ -225,15 +225,16 @@ cb_scale_factor(GObject* object, GParamSpec* UNUSED(pspec), gpointer data)
|
|||
}
|
||||
|
||||
int new_factor = gtk_widget_get_scale_factor(GTK_WIDGET(object));
|
||||
if (new_factor == 0) {
|
||||
girara_debug("Ignoring new device scale factor = 0");
|
||||
return;
|
||||
}
|
||||
|
||||
double current_x;
|
||||
double current_y;
|
||||
zathura_document_get_device_scale(zathura->document, ¤t_x, ¤t_y);
|
||||
|
||||
if (new_factor != current_x || new_factor != current_y) {
|
||||
zathura_document_set_device_scale(zathura->document, new_factor,
|
||||
new_factor);
|
||||
girara_debug("New device scale: %d", new_factor);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,8 +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 */
|
||||
double device_scale_x; /**< x scale factor (for e.g. HiDPI) */
|
||||
double device_scale_y; /**< y scale factor (for e.g. HiDPI) */
|
||||
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 */
|
||||
|
@ -134,8 +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_scale_x = 0.0;
|
||||
document->device_scale_y = 0.0;
|
||||
document->device_factors.x = 1.0;
|
||||
document->device_factors.y = 1.0;
|
||||
document->position_x = 0.0;
|
||||
document->position_y = 0.0;
|
||||
|
||||
|
@ -505,23 +505,31 @@ zathura_document_get_viewport_size(zathura_document_t* document,
|
|||
}
|
||||
|
||||
void
|
||||
zathura_document_set_device_scale(zathura_document_t* document,
|
||||
double x_factor, double y_factor)
|
||||
zathura_document_set_device_factors(zathura_document_t* document,
|
||||
double x_factor, double y_factor)
|
||||
{
|
||||
if (document == NULL) {
|
||||
return;
|
||||
}
|
||||
document->device_scale_x = x_factor;
|
||||
document->device_scale_y = y_factor;
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
zathura_document_get_device_scale(zathura_document_t* document,
|
||||
double *x_factor, double* y_factor)
|
||||
zathura_device_factors_t
|
||||
zathura_document_get_device_factors(zathura_document_t* document)
|
||||
{
|
||||
g_return_if_fail(document != NULL && x_factor != NULL && y_factor != NULL);
|
||||
*x_factor = document->device_scale_x;
|
||||
*y_factor = document->device_scale_y;
|
||||
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
|
||||
|
|
|
@ -257,16 +257,15 @@ zathura_document_get_viewport_size(zathura_document_t* document,
|
|||
* @param[in] x_factor,yfactor The x and y scale factors
|
||||
*/
|
||||
void
|
||||
zathura_document_set_device_scale(zathura_document_t* document,
|
||||
zathura_document_set_device_factors(zathura_document_t* document,
|
||||
double x_factor, double y_factor);
|
||||
/**
|
||||
* Return the current device scale factors.
|
||||
* Return the current device scale factors (guaranteed to be non-zero).
|
||||
*
|
||||
* @param[out] x_factor,yfactor The x and y scale factors
|
||||
* @return The x and y device scale factors
|
||||
*/
|
||||
void
|
||||
zathura_document_get_device_scale(zathura_document_t* document,
|
||||
double *x_factor, double* y_factor);
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -448,15 +472,10 @@ zathura_page_widget_draw(GtkWidget* widget, cairo_t* cairo)
|
|||
unsigned int pheight = (rotation % 180 ? page_width : page_height);
|
||||
unsigned int pwidth = (rotation % 180 ? page_height : page_width);
|
||||
|
||||
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,14,0)
|
||||
double device_scale_x;
|
||||
double device_scale_y;
|
||||
cairo_surface_get_device_scale(priv->thumbnail, &device_scale_x, &device_scale_y);
|
||||
if (fabs(device_scale_x) >= DBL_EPSILON && fabs(device_scale_y) >= DBL_EPSILON) {
|
||||
pwidth *= device_scale_x;
|
||||
pheight *= device_scale_y;
|
||||
}
|
||||
#endif
|
||||
/* 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);
|
||||
|
|
|
@ -732,26 +732,20 @@ 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)
|
||||
double device_scale_x;
|
||||
double device_scale_y;
|
||||
zathura_document_get_device_scale(document, &device_scale_x, &device_scale_y);
|
||||
|
||||
gboolean scales_nonzero = (fabs(device_scale_x) >= DBL_EPSILON &&
|
||||
fabs(device_scale_y) >= DBL_EPSILON);
|
||||
|
||||
if (scales_nonzero) {
|
||||
page_width *= device_scale_x;
|
||||
page_height *= device_scale_y;
|
||||
}
|
||||
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,
|
||||
|
@ -759,21 +753,14 @@ render(render_job_t* job, ZathuraRenderRequest* request, ZathuraRenderer* render
|
|||
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;
|
||||
}
|
||||
|
||||
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,14,0)
|
||||
if (scales_nonzero) {
|
||||
cairo_surface_set_device_scale(surface, device_scale_x, device_scale_y);
|
||||
if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
|
||||
cairo_surface_destroy(surface);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cairo_t* cairo = cairo_create(surface);
|
||||
if (cairo == NULL) {
|
||||
cairo_surface_destroy(surface);
|
||||
|
@ -782,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
|
||||
|
|
|
@ -960,8 +960,8 @@ document_open(zathura_t* zathura, const char* path, const char* uri, const char*
|
|||
zathura_document_set_viewport_height(zathura->document, view_height);
|
||||
|
||||
/* get initial device scale */
|
||||
int device_scale = gtk_widget_get_scale_factor(zathura->ui.session->gtk.view);
|
||||
zathura_document_set_device_scale(zathura->document, device_scale, 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*));
|
||||
|
|
Loading…
Reference in a new issue