double uniform_width;
double uniform_height;
- double max_width_page_width;
- double max_width_page_height;
- double max_height_page_width;
- double max_height_page_height;
+ double max_width;
+ double max_height;
+ double* height_to_page;
+ double* dual_height_to_page;
EvPageCacheInfo *size_cache;
EvDocumentInfo *page_info;
g_free (page_cache->title);
g_free (page_cache->size_cache);
+ g_free (page_cache->height_to_page);
+ g_free (page_cache->dual_height_to_page);
+
ev_document_info_free (page_cache->page_info);
}
EvPageCache *page_cache;
EvPageCacheInfo *info;
gint i;
+ double saved_height;
page_cache = (EvPageCache *) g_object_new (EV_TYPE_PAGE_CACHE, NULL);
page_cache->has_labels = FALSE;
page_cache->n_pages = ev_document_get_n_pages (document);
page_cache->page_labels = g_new0 (char *, page_cache->n_pages);
- page_cache->max_width_page_width = 0;
- page_cache->max_width_page_height = 0;
- page_cache->max_height_page_width = 0;
- page_cache->max_height_page_height = 0;
+ page_cache->max_width = 0;
+ page_cache->max_height = 0;
doc_info = ev_document_get_info (document);
if (doc_info->fields_mask & EV_DOCUMENT_INFO_TITLE) {
}
}
- if (page_width > page_cache->max_width_page_width) {
- page_cache->max_width_page_width = page_width;
- page_cache->max_width_page_height = page_height;
+ if (page_width > page_cache->max_width) {
+ page_cache->max_width = page_width;
}
- if (page_height > page_cache->max_height_page_height) {
- page_cache->max_height_page_width = page_width;
- page_cache->max_height_page_height = page_height;
+ if (page_height > page_cache->max_height) {
+ page_cache->max_height = page_height;
}
-
+
if (i == 0) {
page_cache->uniform_width = page_width;
page_cache->uniform_height = page_height;
}
}
+ page_cache->height_to_page = g_new0(double, page_cache->n_pages);
+ page_cache->dual_height_to_page = g_new0(double, page_cache->n_pages / 2 + 1);
+
+ saved_height = 0;
+ for (i = 0; i < page_cache->n_pages; i++) {
+
+ if (page_cache->uniform) {
+ page_cache->height_to_page [i] = (i + 1) * page_cache->uniform_height;
+ } else {
+ page_cache->height_to_page [i] = saved_height + page_cache->size_cache [i].height;
+ saved_height = page_cache->height_to_page [i];
+ }
+ }
+
+ saved_height = 0;
+ for (i = 0; i < page_cache->n_pages; i += 2) {
+
+ if (page_cache->uniform) {
+ page_cache->dual_height_to_page [i / 2] = (i / 2 + 1) * page_cache->uniform_height;
+ } else {
+ if (i == page_cache->n_pages - 1) {
+ page_cache->dual_height_to_page [i / 2] =
+ saved_height + page_cache->size_cache [i].height;
+ }
+ else {
+ page_cache->dual_height_to_page [i / 2] = saved_height +
+ MAX(page_cache->size_cache [i].height,
+ page_cache->size_cache [i + 1].height);
+ saved_height = page_cache->dual_height_to_page [i / 2];
+ }
+ }
+ }
+
page_cache->page_info = ev_document_get_info (document);
/* make some sanity check assertions */
}
-/* Note that these aren't necessarily from the same page.
- */
void
-ev_page_cache_get_max_width_size (EvPageCache *page_cache,
+ev_page_cache_get_max_width (EvPageCache *page_cache,
gfloat scale,
- gint *width,
- gint *height)
+ gint *width)
{
g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
if (width)
- *width = page_cache->max_width_page_width * scale;
- if (height)
- *height = page_cache->max_width_page_height * scale;
+ *width = page_cache->max_width * scale;
}
void
-ev_page_cache_get_max_height_size (EvPageCache *page_cache,
+ev_page_cache_get_max_height (EvPageCache *page_cache,
gfloat scale,
- gint *width,
gint *height)
{
g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
- if (width)
- *width = page_cache->max_height_page_width * scale;
if (height)
- *height = page_cache->max_height_page_height * scale;
+ *height = page_cache->max_height * scale;
+}
+
+void
+ev_page_cache_get_height_to_page (EvPageCache *page_cache,
+ gint page,
+ gfloat scale,
+ gint *height,
+ gint *dual_height)
+{
+ double result = 0.0;
+ double dual_result = 0.0;
+
+ g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
+
+ if (page > 0)
+ result = page_cache->height_to_page [page - 1];
+
+ if (height)
+ *height = result * scale;
+
+ if (page > 1)
+ dual_result = page_cache->dual_height_to_page [page / 2 - 1];
+
+ if (dual_height)
+ *dual_height = dual_result * scale;
}
gint
int spacing;
double scale;
- GtkBorder border;
gboolean continuous;
gboolean dual_page;
};
/*** Scrolling ***/
+static void scroll_to_current_page (EvView *view,
+ GtkOrientation orientation);
static void ev_view_set_scroll_adjustments (EvView *view,
GtkAdjustment *hadjustment,
GtkAdjustment *vadjustment);
int width,
int height,
GtkBorder *border);
+static void get_page_y_offset (EvView *view,
+ int page,
+ double zoom,
+ int *y_offset);
static gboolean get_page_extents (EvView *view,
gint page,
GdkRectangle *page_area,
int page,
EvRectangle *doc_rect,
GdkRectangle *view_rect);
-static void get_bounding_box_size (EvView *view,
- int *max_width,
- int *max_height);
static void find_page_at_location (EvView *view,
gdouble x,
gdouble y,
static void
scroll_to_current_page (EvView *view, GtkOrientation orientation)
{
- int max_width, max_height, n_rows;
-
- get_bounding_box_size (view, &max_width, &max_height);
-
+ GdkRectangle page_area;
+ GtkBorder border;
+
+ get_page_extents (view, view->current_page, &page_area, &border);
+
if (orientation == GTK_ORIENTATION_VERTICAL) {
if (view->continuous) {
- n_rows = view->dual_page ? view->current_page / 2 : view->current_page;
-
gtk_adjustment_clamp_page (view->vadjustment,
- (max_height + view->spacing) * n_rows,
- (max_height + view->spacing) * n_rows +
- view->vadjustment->page_size);
+ page_area.y - view->spacing,
+ page_area.y + view->vadjustment->page_size);
} else {
gtk_adjustment_set_value (view->vadjustment,
view->vadjustment->lower);
}
} else {
if (view->dual_page) {
- if (view->current_page % 2 == 0) {
- gtk_adjustment_set_value (view->hadjustment,
- view->hadjustment->lower);
- } else {
- gtk_adjustment_clamp_page (view->hadjustment,
- view->hadjustment->lower +
- max_width + view->spacing,
- view->hadjustment->lower +
- max_width + view->spacing +
- view->hadjustment->page_size);
- }
+ gtk_adjustment_clamp_page (view->hadjustment,
+ page_area.x,
+ page_area.x + view->hadjustment->page_size);
} else {
gtk_adjustment_set_value (view->hadjustment,
CLAMP (view->hadjustment->value,
view->end_page = view->current_page;
} else if (view->continuous) {
GdkRectangle current_area, unused, page_area;
+ GtkBorder border;
gint current_page;
gboolean found = FALSE;
int i;
- get_bounding_box_size (view, &(page_area.width), &(page_area.height));
- page_area.x = view->spacing;
- page_area.y = view->spacing;
-
- if (view->hadjustment) {
- current_area.x = view->hadjustment->value;
- current_area.width = view->hadjustment->page_size;
- } else {
- current_area.x = page_area.x;
- current_area.width = page_area.width;
- }
-
- if (view->vadjustment) {
- current_area.y = view->vadjustment->value;
- current_area.height = view->vadjustment->page_size;
- } else {
- current_area.y = page_area.y;
- current_area.height = page_area.height;
- }
+ if (!(view->vadjustment && view->hadjustment))
+ return;
+
+ current_area.x = view->hadjustment->value;
+ current_area.width = view->hadjustment->upper;
+ current_area.y = view->vadjustment->value;
+ current_area.height = view->vadjustment->page_size;
for (i = 0; i < ev_page_cache_get_n_pages (view->page_cache); i++) {
+
+ get_page_extents (view, i, &page_area, &border);
+
if (gdk_rectangle_intersect (¤t_area, &page_area, &unused)) {
if (! found) {
view->start_page = i;
} else if (found) {
break;
}
- if (view->dual_page) {
- if (i % 2 == 0) {
- page_area.x += page_area.width + view->spacing;
- } else {
- page_area.x = view->spacing;
- page_area.y += page_area.height + view->spacing;
- }
- } else {
- page_area.y += page_area.height + view->spacing;
- }
}
-
+
current_page = ev_page_cache_get_current_page (view->page_cache);
if (current_page < view->start_page || current_page > view->end_page) {
}
}
+static void get_page_y_offset (EvView *view,
+ int page,
+ double zoom,
+ int *y_offset)
+{
+ int max_width, offset;
+ GtkBorder border;
+
+ g_return_if_fail (y_offset != NULL);
+
+ ev_page_cache_get_max_width (view->page_cache, zoom, &max_width);
+
+ compute_border (view, max_width, max_width, &border);
+
+ if (view->dual_page) {
+ ev_page_cache_get_height_to_page (view->page_cache, page, zoom, NULL, &offset);
+ offset += (page / 2 + 1) * view->spacing + (page / 2) * (border.top + border.bottom);
+ } else {
+ ev_page_cache_get_height_to_page (view->page_cache, page, zoom, &offset, NULL);
+ offset += (page + 1) * view->spacing + page * (border.top + border.bottom);
+ }
+
+ *y_offset = offset;
+ return;
+}
+
static gboolean
get_page_extents (EvView *view,
gint page,
widget = GTK_WIDGET (view);
- /* Quick sanity check */
- if (view->presentation) {
- if (view->current_page != page)
- return FALSE;
- } else if (view->continuous) {
- if (page < view->start_page ||
- page > view->end_page)
- return FALSE;
- } else if (view->dual_page) {
- if (ABS (page - view->current_page) > 1)
- return FALSE;
- } else {
- if (view->current_page != page)
- return FALSE;
- }
-
/* Get the size of the page */
ev_page_cache_get_size (view->page_cache, page,
view->scale,
page_area->x = (MAX (0, widget->allocation.width - width))/2;
page_area->y = (MAX (0, widget->allocation.height - height))/2;
} else if (view->continuous) {
- gint max_width, max_height;
+ gint max_width;
gint x, y;
- get_bounding_box_size (view, &max_width, &max_height);
+ ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
+ max_width = max_width + border->left + border->right;
/* Get the location of the bounding box */
if (view->dual_page) {
x = view->spacing + (page % 2) * (max_width + view->spacing);
- y = view->spacing + (page / 2) * (max_height + view->spacing);
- x = x + MAX (0, widget->allocation.width - (max_width * 2 + view->spacing * 3))/2;
+ x = x + MAX (0, widget->allocation.width - (max_width * 2 + view->spacing * 3)) / 2;
+ if (page % 2 == 0)
+ x = x + (max_width - width - border->left - border->right);
} else {
x = view->spacing;
- y = view->spacing + page * (max_height + view->spacing);
- x = x + MAX (0, widget->allocation.width - (max_width + view->spacing * 2))/2;
+ x = x + MAX (0, widget->allocation.width - (width + view->spacing * 2)) / 2;
}
+
+ get_page_y_offset (view, page, view->scale, &y);
+
page_area->x = x;
page_area->y = y;
} else {
view_rect->height = ceil (height * view->scale);
}
-static void
-get_bounding_box_size (EvView *view, int *max_width, int *max_height)
-{
- GtkBorder border;
- int width, height;
-
- if (max_width) {
- ev_page_cache_get_max_width_size (view->page_cache,
- view->scale,
- &width, &height);
- compute_border (view, width, height, &border);
- *max_width = width + border.left + border.right;
- }
-
-
- if (max_height) {
- ev_page_cache_get_max_height_size (view->page_cache,
- view->scale,
- &width, &height);
- compute_border (view, width, height, &border);
- *max_height = height + border.top + border.bottom;
- }
-}
-
static void
find_page_at_location (EvView *view,
gdouble x,
static void
ev_view_size_request_continuous_dual_page (EvView *view,
- GtkRequisition *requisition)
+ GtkRequisition *requisition)
{
- int max_width, max_height;
- int n_rows;
+ int max_width;
+ gint n_pages;
+ GtkBorder border;
- get_bounding_box_size (view, &max_width, &max_height);
+ ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
+ compute_border (view, max_width, max_width, &border);
- n_rows = (1 + ev_page_cache_get_n_pages (view->page_cache)) / 2;
+ n_pages = ev_page_cache_get_n_pages (view->page_cache) + 1;
- requisition->width = (max_width * 2) + (view->spacing * 3);
- requisition->height = max_height * n_rows + (view->spacing * (n_rows + 1));
+ requisition->width = (max_width + border.left + border.right) * 2 + (view->spacing * 3);
+ get_page_y_offset (view, n_pages, view->scale, &requisition->height);
if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
requisition->width = 1;
ev_view_size_request_continuous (EvView *view,
GtkRequisition *requisition)
{
- int max_width, max_height;
+ int max_width;
int n_pages;
+ GtkBorder border;
- get_bounding_box_size (view, &max_width, &max_height);
+ ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
n_pages = ev_page_cache_get_n_pages (view->page_cache);
+ compute_border (view, max_width, max_width, &border);
- requisition->width = max_width + (view->spacing * 2);
- requisition->height = max_height * n_pages + (view->spacing * (n_pages + 1));
+ requisition->width = max_width + (view->spacing * 2) + border.left + border.right;
+ get_page_y_offset (view, n_pages, view->scale, &requisition->height);
if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
requisition->width = 1;
GtkBorder border;
gdouble scale;
- ev_page_cache_get_max_width_size (view->page_cache,
- 1.0,
- &doc_width, NULL);
- ev_page_cache_get_max_height_size (view->page_cache,
- 1.0,
- NULL, &doc_height);
+ ev_page_cache_get_max_width (view->page_cache,
+ 1.0,
+ &doc_width);
+ ev_page_cache_get_max_height (view->page_cache,
+ 1.0,
+ &doc_height);
compute_border (view, doc_width, doc_height, &border);
doc_width = doc_width * 2;
GtkBorder border;
gdouble scale;
- ev_page_cache_get_max_width_size (view->page_cache,
- 1.0,
- &doc_width, NULL);
- ev_page_cache_get_max_height_size (view->page_cache,
- 1.0,
- NULL, &doc_height);
+ ev_page_cache_get_max_width (view->page_cache,
+ 1.0,
+ &doc_width);
+ ev_page_cache_get_max_height (view->page_cache,
+ 1.0,
+ &doc_height);
compute_border (view, doc_width, doc_height, &border);
width -= (border.left + border.right + 2 * view->spacing);