adjustment.c 6.3 KB
Newer Older
1
/* SPDX-License-Identifier: Zlib */
2 3 4

#include "adjustment.h"
#include "utils.h"
5 6 7 8
#include <math.h>


double
Sebastian Ramacher's avatar
Sebastian Ramacher committed
9 10 11
page_calc_height_width(zathura_document_t* document, double height,
                       double width, unsigned int* page_height,
                       unsigned int* page_width, bool rotate)
12 13 14
{
  g_return_val_if_fail(document != NULL && page_height != NULL && page_width != NULL, 0.0);

Sebastian Ramacher's avatar
Sebastian Ramacher committed
15
  double scale = zathura_document_get_scale(document);
16

Sebastian Ramacher's avatar
Sebastian Ramacher committed
17
  if (rotate == true && zathura_document_get_rotation(document) % 180 != 0) {
18 19
    *page_width  = round(height * scale);
    *page_height = round(width  * scale);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
20
    scale = MAX(*page_width / height, *page_height / width);
21 22 23
  } else {
    *page_width  = round(width  * scale);
    *page_height = round(height * scale);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
24
    scale = MAX(*page_width / width, *page_height / height);
25 26
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
27
  return scale;
28 29 30
}

void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
31 32 33
page_calc_position(zathura_document_t* document, double x, double y, double* xn,
                   double* yn)
{
34 35
  g_return_if_fail(document != NULL && xn != NULL && yn != NULL);

Sebastian Ramacher's avatar
Sebastian Ramacher committed
36
  const unsigned int rot = zathura_document_get_rotation(document);
37 38 39
  if (rot == 90) {
    *xn = 1 - y;
    *yn = x;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
40
  } else if (rot == 180) {
41 42 43 44 45 46 47 48 49 50 51 52
    *xn = 1 - x;
    *yn = 1 - y;
  } else if (rot == 270) {
    *xn = y;
    *yn = 1 - x;
  } else {
    *xn = x;
    *yn = y;
  }
}

unsigned int
Sebastian Ramacher's avatar
Sebastian Ramacher committed
53 54 55
position_to_page_number(zathura_document_t* document, double pos_x,
                        double pos_y)
{
56 57 58 59 60 61 62 63 64 65 66
  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);
67
  unsigned int nrow = 0;
68 69
  unsigned int pad  = zathura_document_get_page_padding(document);

70 71 72 73 74 75 76 77
  if (c0 == 1) {
    /* There is no offset, so this is easy. */
    nrow = (npag + ncol - 1) / ncol;
  } else {
    /* If there is a offset, we handle the first row extra. */
    nrow = 1 + (npag - (ncol - c0 - 1) + (ncol - 1)) / ncol;
  }

78 79 80
  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));

81 82 83 84
  unsigned int page = ncol * (row % nrow) + (col % ncol);
  if (page < c0 - 1) {
    return 0;
  } else {
85
    return MIN(page - (c0 - 1), npag - 1);
86
  }
87 88 89 90 91
}


void
page_number_to_position(zathura_document_t* document, unsigned int page_number,
Sebastian Ramacher's avatar
Sebastian Ramacher committed
92 93 94
                        double xalign, double yalign, double* pos_x,
                        double* pos_y)
{
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
  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
Sebastian Ramacher's avatar
Sebastian Ramacher committed
133 134
page_is_visible(zathura_document_t *document, unsigned int page_number)
{
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
  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);
}
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

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)
{
Sebastian Ramacher's avatar
Sebastian Ramacher committed
183
  if (ratio == 0.0) {
184
    return;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
185
  }
186 187 188 189 190 191 192 193 194

  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);
}