mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2024-12-28 21:26:01 +01:00
030a8c65c1
The plan is to put in adjustment.c every piece of code that has to do with document positioning, either computing it from data on the document side, or talking to GTK. We want to have at our disposal functions to compute sizes and positions without having to ask for it to a GTK widget. The new functions are: - move page_calc_height_width to adjustment.c - add page_calc_position that rotates a position relative to a page according to the rotation settings. - add position_to_page_number that computes the number of a page sitting at a given position (given in document-relative coordinates) - add page_number_to_position that computes the position (in document relative coordinates) that will be placed at the center of the viewport. - add page_is_visible that checks whether the given page intersects the viewport.
194 lines
6.6 KiB
C
194 lines
6.6 KiB
C
/* See LICENSE file for license and copyright information */
|
|
|
|
#include "adjustment.h"
|
|
#include "utils.h"
|
|
#include <math.h>
|
|
|
|
|
|
double
|
|
page_calc_height_width(zathura_document_t* document, double height, double width,
|
|
unsigned int* page_height, unsigned int* page_width, bool rotate)
|
|
{
|
|
g_return_val_if_fail(document != NULL && page_height != NULL && page_width != NULL, 0.0);
|
|
|
|
double scale = zathura_document_get_scale(document);
|
|
double real_scale;
|
|
|
|
if (rotate && zathura_document_get_rotation(document) % 180) {
|
|
*page_width = round(height * scale);
|
|
*page_height = round(width * scale);
|
|
real_scale = MAX(*page_width / height, *page_height / width);
|
|
} else {
|
|
*page_width = round(width * scale);
|
|
*page_height = round(height * scale);
|
|
real_scale = MAX(*page_width / width, *page_height / height);
|
|
}
|
|
|
|
return real_scale;
|
|
}
|
|
|
|
void
|
|
page_calc_position(zathura_document_t* document, double x, double y,
|
|
double *xn, double *yn) {
|
|
|
|
g_return_if_fail(document != NULL && xn != NULL && yn != NULL);
|
|
|
|
unsigned int rot = zathura_document_get_rotation(document);
|
|
|
|
if (rot == 90) {
|
|
*xn = 1 - y;
|
|
*yn = x;
|
|
}else if (rot == 180) {
|
|
*xn = 1 - x;
|
|
*yn = 1 - y;
|
|
} else if (rot == 270) {
|
|
*xn = y;
|
|
*yn = 1 - x;
|
|
} else {
|
|
*xn = x;
|
|
*yn = y;
|
|
}
|
|
}
|
|
|
|
|
|
unsigned int
|
|
position_to_page_number(zathura_document_t* document,
|
|
double pos_x, double pos_y){
|
|
|
|
g_return_val_if_fail(document != NULL, 0);
|
|
|
|
unsigned int doc_width, doc_height;
|
|
zathura_document_get_document_size(document, &doc_height, &doc_width);
|
|
|
|
unsigned int cell_width, cell_height;
|
|
zathura_document_get_cell_size(document, &cell_height, &cell_width);
|
|
|
|
unsigned int c0 = zathura_document_get_first_page_column(document);
|
|
unsigned int npag = zathura_document_get_number_of_pages(document);
|
|
unsigned int ncol = zathura_document_get_pages_per_row(document);
|
|
unsigned int nrow = (npag + c0 - 1 + ncol - 1) / ncol; /* number of rows */
|
|
unsigned int pad = zathura_document_get_page_padding(document);
|
|
|
|
unsigned int col = floor(pos_x * (double)doc_width / (double)(cell_width + pad));
|
|
unsigned int row = floor(pos_y * (double)doc_height / (double)(cell_height + pad));
|
|
|
|
return ncol * (row % nrow) + (col % ncol) - (c0 - 1);
|
|
}
|
|
|
|
|
|
void
|
|
page_number_to_position(zathura_document_t* document, unsigned int page_number,
|
|
double xalign, double yalign, double *pos_x, double *pos_y) {
|
|
g_return_if_fail(document != NULL);
|
|
|
|
unsigned int c0 = zathura_document_get_first_page_column(document);
|
|
unsigned int npag = zathura_document_get_number_of_pages(document);
|
|
unsigned int ncol = zathura_document_get_pages_per_row(document);
|
|
unsigned int nrow = (npag + c0 - 1 + ncol - 1) / ncol; /* number of rows */
|
|
|
|
/* row and column for page_number indexed from 0 */
|
|
unsigned int row = (page_number + c0 - 1) / ncol;
|
|
unsigned int col = (page_number + c0 - 1) % ncol;
|
|
|
|
/* sizes of page cell, viewport and document */
|
|
unsigned int cell_height = 0, cell_width = 0;
|
|
zathura_document_get_cell_size(document, &cell_height, &cell_width);
|
|
|
|
unsigned int view_height = 0, view_width = 0;
|
|
zathura_document_get_viewport_size(document, &view_height, &view_width);
|
|
|
|
unsigned int doc_height = 0, doc_width = 0;
|
|
zathura_document_get_document_size(document, &doc_height, &doc_width);
|
|
|
|
/* compute the shift to align to the viewport. If the page fits to viewport, just center it. */
|
|
double shift_x = 0.5, shift_y = 0.5;
|
|
if (cell_width > view_width) {
|
|
shift_x = 0.5 + (xalign - 0.5) * ((double)cell_width - (double)view_width) / (double)cell_width;
|
|
}
|
|
|
|
if (cell_height > view_height) {
|
|
shift_y = 0.5 + (yalign - 0.5) * ((double)cell_height - (double)view_height) / (double)cell_height;
|
|
}
|
|
|
|
/* compute the position */
|
|
*pos_x = ((double)col + shift_x) / (double)ncol;
|
|
*pos_y = ((double)row + shift_y) / (double)nrow;
|
|
}
|
|
|
|
|
|
bool
|
|
page_is_visible(zathura_document_t *document, unsigned int page_number) {
|
|
g_return_val_if_fail(document != NULL, false);
|
|
|
|
/* position at the center of the viewport */
|
|
double pos_x = zathura_document_get_position_x(document);
|
|
double pos_y = zathura_document_get_position_y(document);
|
|
|
|
/* get the center of page page_number */
|
|
double page_x, page_y;
|
|
page_number_to_position(document, page_number, 0.5, 0.5, &page_x, &page_y);
|
|
|
|
unsigned int cell_width, cell_height;
|
|
zathura_document_get_cell_size(document, &cell_height, &cell_width);
|
|
|
|
unsigned int doc_width, doc_height;
|
|
zathura_document_get_document_size(document, &doc_height, &doc_width);
|
|
|
|
unsigned int view_width, view_height;
|
|
zathura_document_get_viewport_size(document, &view_height, &view_width);
|
|
|
|
return ( fabs(pos_x - page_x) < 0.5 * (double)(view_width + cell_width) / (double)doc_width &&
|
|
fabs(pos_y - page_y) < 0.5 * (double)(view_height + cell_height) / (double)doc_height);
|
|
}
|
|
|
|
GtkAdjustment*
|
|
zathura_adjustment_clone(GtkAdjustment* adjustment)
|
|
{
|
|
gdouble value = gtk_adjustment_get_value(adjustment);
|
|
gdouble lower = gtk_adjustment_get_lower(adjustment);
|
|
gdouble upper = gtk_adjustment_get_upper(adjustment);
|
|
gdouble step_increment = gtk_adjustment_get_step_increment(adjustment);
|
|
gdouble page_increment = gtk_adjustment_get_page_increment(adjustment);
|
|
gdouble page_size = gtk_adjustment_get_page_size(adjustment);
|
|
|
|
return GTK_ADJUSTMENT(gtk_adjustment_new(value, lower, upper, step_increment,
|
|
page_increment, page_size));
|
|
}
|
|
|
|
void
|
|
zathura_adjustment_set_value(GtkAdjustment* adjustment, gdouble value)
|
|
{
|
|
gtk_adjustment_set_value(adjustment,
|
|
MAX(gtk_adjustment_get_lower(adjustment),
|
|
MIN(gtk_adjustment_get_upper(adjustment) -
|
|
gtk_adjustment_get_page_size(adjustment),
|
|
value)));
|
|
}
|
|
|
|
gdouble
|
|
zathura_adjustment_get_ratio(GtkAdjustment* adjustment)
|
|
{
|
|
gdouble lower = gtk_adjustment_get_lower(adjustment);
|
|
gdouble upper = gtk_adjustment_get_upper(adjustment);
|
|
gdouble page_size = gtk_adjustment_get_page_size(adjustment);
|
|
gdouble value = gtk_adjustment_get_value(adjustment);
|
|
|
|
return (value - lower + page_size / 2.0) / (upper - lower);
|
|
}
|
|
|
|
void
|
|
zathura_adjustment_set_value_from_ratio(GtkAdjustment* adjustment,
|
|
gdouble ratio)
|
|
{
|
|
if (ratio == 0.0) {
|
|
return;
|
|
}
|
|
|
|
gdouble lower = gtk_adjustment_get_lower(adjustment);
|
|
gdouble upper = gtk_adjustment_get_upper(adjustment);
|
|
gdouble page_size = gtk_adjustment_get_page_size(adjustment);
|
|
|
|
gdouble value = (upper - lower) * ratio + lower - page_size / 2.0;
|
|
|
|
zathura_adjustment_set_value(adjustment, value);
|
|
}
|