+ev_view_get_offsets (EvView *view, int *x_offset, int *y_offset)
+{
+ EvDocument *document = view->document;
+ GtkWidget *widget = GTK_WIDGET (view);
+ int width, height, target_width, target_height;
+
+ g_return_if_fail (EV_IS_DOCUMENT (document));
+
+ ev_page_cache_get_size (view->page_cache,
+ view->current_page,
+ view->scale,
+ &width, &height);
+
+ *x_offset = view->spacing;
+ *y_offset = view->spacing;
+ target_width = width + view->border.left +
+ view->border.right + view->spacing * 2;
+ target_height = height + view->border.top +
+ view->border.bottom + view->spacing * 2;
+ *x_offset += MAX (0, (widget->allocation.width - target_width) / 2);
+ *y_offset += MAX (0, (widget->allocation.height - target_height) / 2);
+}
+
+static void
+view_rect_to_doc_rect (EvView *view, GdkRectangle *view_rect, EvRectangle *doc_rect)
+{
+ int x_offset, y_offset;
+
+ ev_view_get_offsets (view, &x_offset, &y_offset);
+ doc_rect->x1 = (double) (view_rect->x - x_offset) / view->scale;
+ doc_rect->y1 = (double) (view_rect->y - y_offset) / view->scale;
+ doc_rect->x2 = doc_rect->x1 + (double) view_rect->width / view->scale;
+ doc_rect->y2 = doc_rect->y1 + (double) view_rect->height / view->scale;
+}
+
+static void
+doc_rect_to_view_rect (EvView *view, EvRectangle *doc_rect, GdkRectangle *view_rect)
+{
+ int x_offset, y_offset;
+
+ ev_view_get_offsets (view, &x_offset, &y_offset);
+ view_rect->x = floor (doc_rect->x1 * view->scale) + x_offset;
+ view_rect->y = floor (doc_rect->y1 * view->scale) + y_offset;
+ view_rect->width = ceil (doc_rect->x2 * view->scale) + x_offset - view_rect->x;
+ view_rect->height = ceil (doc_rect->y2 * view->scale) + y_offset - view_rect->y;
+}
+
+static void
+compute_border (EvView *view, int width, int height, GtkBorder *border)
+{
+ if (view->show_border) {
+ ev_document_misc_get_page_border_size (width, height, border);
+ } else {
+ border->left = 0;
+ border->right = 0;
+ border->top = 0;
+ border->bottom = 0;
+ }
+}
+
+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
+ev_view_size_request_continuous_and_dual_page (EvView *view,
+ GtkRequisition *requisition)
+{
+ int max_width, max_height;
+ int n_rows;
+
+ get_bounding_box_size (view, &max_width, &max_height);
+
+ n_rows = (1 + ev_page_cache_get_n_pages (view->page_cache)) / 2;
+
+ requisition->width = (max_width * 2) + (view->spacing * 3);
+ requisition->height = max_height * n_rows + (view->spacing * (n_rows + 1));
+
+ if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
+ requisition->width = 1;
+ } else if (view->sizing_mode == EV_SIZING_BEST_FIT) {
+ requisition->width = 1;
+ /* FIXME: This could actually be set on one page docs or docs
+ * with a strange aspect ratio. */
+ /* requisition->height = 1;*/
+ }
+}
+
+static void
+ev_view_size_request_continuous (EvView *view,
+ GtkRequisition *requisition)
+{
+ int max_width, max_height;
+ int n_pages;
+
+ get_bounding_box_size (view, &max_width, &max_height);
+
+ n_pages = ev_page_cache_get_n_pages (view->page_cache);
+
+ requisition->width = max_width + (view->spacing * 2);
+ requisition->height = max_height * n_pages + (view->spacing * (n_pages + 1));
+
+ if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
+ requisition->width = 1;
+ } else if (view->sizing_mode == EV_SIZING_BEST_FIT) {
+ requisition->width = 1;
+ /* FIXME: This could actually be set on one page docs or docs
+ * with a strange aspect ratio. */
+ /* requisition->height = 1;*/
+ }
+}
+
+static void
+ev_view_size_request_dual_page (EvView *view,
+ GtkRequisition *requisition)