adjustment.c 6.31 KB
Newer Older
1 2 3 4
/* See LICENSE file for license and copyright information */

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


double
Sebastian Ramacher's avatar
CS  
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 17 18
  if (rotate && zathura_document_get_rotation(document) % 180) {
    *page_width  = round(height * scale);
    *page_height = round(width  * scale);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
19
    scale = MAX(*page_width / height, *page_height / width);
20 21 22
  } else {
    *page_width  = round(width  * scale);
    *page_height = round(height * scale);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
23
    scale = MAX(*page_width / width, *page_height / height);
24 25
  }

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

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

Sebastian Ramacher's avatar
CS  
Sebastian Ramacher committed
35
  const unsigned int rot = zathura_document_get_rotation(document);
36 37 38
  if (rot == 90) {
    *xn = 1 - y;
    *yn = x;
Sebastian Ramacher's avatar
CS  
Sebastian Ramacher committed
39
  } else if (rot == 180) {
40 41 42 43 44 45 46 47 48 49 50 51
    *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
CS  
Sebastian Ramacher committed
52 53 54
position_to_page_number(zathura_document_t* document, double pos_x,
                        double pos_y)
{
55 56 57 58 59 60 61 62 63 64 65
  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);
66
  unsigned int nrow = 0;
67 68
  unsigned int pad  = zathura_document_get_page_padding(document);

69 70 71 72 73 74 75 76
  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;
  }

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

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


void
page_number_to_position(zathura_document_t* document, unsigned int page_number,
Sebastian Ramacher's avatar
CS  
Sebastian Ramacher committed
91 92 93
                        double xalign, double yalign, double* pos_x,
                        double* pos_y)
{
94 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
  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
CS  
Sebastian Ramacher committed
132 133
page_is_visible(zathura_document_t *document, unsigned int page_number)
{
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
  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);
}
156 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

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

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