[evince] Switch to specifying rendered output in pixels, not as a scale
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince] Switch to specifying rendered output in pixels, not as a scale
- Date: Sat, 22 Mar 2014 12:54:08 +0000 (UTC)
commit 6b50ba7172d84de19f1215bed289698d82ea4187
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Mon Mar 3 15:22:30 2014 -0500
Switch to specifying rendered output in pixels, not as a scale
Passing a scale to the backend meant that we were implicitly counting
on the backend code and front-end code to do exactly the same calculation
to get the rendered size of a page. Instead switch to passing a
target size in pixels to the backend.
This, among other things, allows us to make sure that we render at a size
that is integer device pixels in both X and Y directions.
ev-render-context.[ch]: Add ev_render_context_set_target_size() and
three helper functions:
ev_render_context_compute_scaled_size(): get the pixel size to render at
ev_render_context_compute_transformed_size(): size including effect of rotation
ev_render_context_compute_scales(): get the corresponding xscale/yscale.
ev-jobs.[ch]: Add ev_job_thumbnail_new_with_target_size(), and pass the
target size for thumbnail and render jobs (which already had a target
size) to the backends.
backend/*: Use the helper functions rather than directly accessing
render_context->scale.
ev-pixbuf-cache.c ev-view.c ev-view-presentation.c ev-sidebar-thumbnails.c
ev-window.c: Switch to passing target sizes rather than scales when
rendering.
https://bugzilla.gnome.org/show_bug.cgi?id=723431
backend/comics/comics-document.c | 18 +++--
backend/djvu/djvu-document.c | 49 ++++++------
backend/dvi/cairo-device.c | 18 +++--
backend/dvi/cairo-device.h | 3 +-
backend/dvi/dvi-document.c | 13 ++-
backend/pdf/ev-poppler.cc | 71 +++++++----------
backend/ps/ev-spectre.c | 5 +-
backend/tiff/tiff-document.c | 12 ++-
backend/xps/xps-document.c | 17 ++--
.../libdocument/libevdocument-sections.txt | 4 +
help/reference/libview/libevview-sections.txt | 1 +
libdocument/ev-render-context.c | 83 +++++++++++++++++++-
libdocument/ev-render-context.h | 21 +++++-
libview/ev-jobs.c | 22 +++++
libview/ev-jobs.h | 7 ++
libview/ev-pixbuf-cache.c | 19 ++++-
libview/ev-view-presentation.c | 82 +++++++++-----------
libview/ev-view.c | 7 +-
shell/ev-sidebar-thumbnails.c | 30 +++++--
shell/ev-window.c | 12 ++-
20 files changed, 328 insertions(+), 166 deletions(-)
---
diff --git a/backend/comics/comics-document.c b/backend/comics/comics-document.c
index ae643c5..00f8258 100644
--- a/backend/comics/comics-document.c
+++ b/backend/comics/comics-document.c
@@ -677,7 +677,7 @@ comics_document_render_pixbuf (EvDocument *document,
loader = gdk_pixbuf_loader_new ();
g_signal_connect (loader, "size-prepared",
G_CALLBACK (render_pixbuf_size_prepared_cb),
- &rc->scale);
+ &rc);
while (outpipe >= 0) {
bytes = read (outpipe, buf, 4096);
@@ -698,17 +698,21 @@ comics_document_render_pixbuf (EvDocument *document,
g_spawn_close_pid (child_pid);
g_object_unref (loader);
} else {
+ int scaled_width, scaled_height;
+
filename =
g_build_filename (comics_document->dir,
(char *) comics_document->page_names->pdata[rc->page->index],
NULL);
gdk_pixbuf_get_file_info (filename, &width, &height);
+
+ ev_render_context_compute_scaled_size (rc, width, height,
+ &scaled_width, &scaled_height);
tmp_pixbuf =
gdk_pixbuf_new_from_file_at_size (
- filename, width * (rc->scale) + 0.5,
- height * (rc->scale) + 0.5, NULL);
+ filename, scaled_width, scaled_height, NULL);
rotated_pixbuf =
gdk_pixbuf_rotate_simple (tmp_pixbuf,
360 - rc->rotation);
@@ -738,11 +742,11 @@ render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
gint height,
gpointer data)
{
- double *scale = data;
- int w = (width * (*scale) + 0.5);
- int h = (height * (*scale) + 0.5);
+ EvRenderContext *rc = data;
+ int scaled_width, scaled_height;
- gdk_pixbuf_loader_set_size (loader, w, h);
+ ev_render_context_compute_scaled_size (rc, width, height, &scaled_width, &scaled_height);
+ gdk_pixbuf_loader_set_size (loader, scaled_width, scaled_height);
}
/**
diff --git a/backend/djvu/djvu-document.c b/backend/djvu/djvu-document.c
index 13402f6..9c30a22 100644
--- a/backend/djvu/djvu-document.c
+++ b/backend/djvu/djvu-document.c
@@ -340,7 +340,8 @@ djvu_document_render (EvDocument *document,
ddjvu_page_t *d_page;
ddjvu_page_rotation_t rotation;
gint buffer_modified;
- double page_width, page_height, tmp;
+ double page_width, page_height;
+ gint transformed_width, transformed_height;
d_page = ddjvu_page_create_by_pageno (djvu_document->d_document, rc->page->index);
@@ -350,15 +351,12 @@ djvu_document_render (EvDocument *document,
document_get_page_size (djvu_document, rc->page->index, &page_width, &page_height, NULL);
rotation = ddjvu_page_get_initial_rotation (d_page);
- page_width = page_width * rc->scale + 0.5;
- page_height = page_height * rc->scale + 0.5;
-
+ ev_render_context_compute_transformed_size (rc, page_width, page_height,
+ &transformed_width, &transformed_height);
+
switch (rc->rotation) {
case 90:
rotation += DDJVU_ROTATE_90;
- tmp = page_height;
- page_height = page_width;
- page_width = tmp;
break;
case 180:
@@ -367,9 +365,6 @@ djvu_document_render (EvDocument *document,
break;
case 270:
rotation += DDJVU_ROTATE_270;
- tmp = page_height;
- page_height = page_width;
- page_width = tmp;
break;
default:
@@ -378,15 +373,15 @@ djvu_document_render (EvDocument *document,
rotation = rotation % 4;
surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
- page_width, page_height);
+ transformed_width, transformed_height);
rowstride = cairo_image_surface_get_stride (surface);
pixels = (gchar *)cairo_image_surface_get_data (surface);
prect.x = 0;
prect.y = 0;
- prect.w = page_width;
- prect.h = page_height;
+ prect.w = transformed_width;
+ prect.h = transformed_height;
rrect = prect;
ddjvu_page_set_rotation (d_page, rotation);
@@ -447,8 +442,8 @@ djvu_document_get_thumbnail (EvDocument *document,
djvu_document_get_page_size (EV_DOCUMENT(djvu_document), rc->page,
&page_width, &page_height);
- thumb_width = (gint) (page_width * rc->scale);
- thumb_height = (gint) (page_height * rc->scale);
+ ev_render_context_compute_scaled_size (rc, page_width, page_height,
+ &thumb_width, &thumb_height);
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
thumb_width, thumb_height);
@@ -486,8 +481,8 @@ djvu_document_get_thumbnail_surface (EvDocument *document,
djvu_document_get_page_size (EV_DOCUMENT(djvu_document), rc->page,
&page_width, &page_height);
- thumb_width = (gint) (page_width * rc->scale + 0.5);
- thumb_height = (gint) (page_height * rc->scale + 0.5);
+ ev_render_context_compute_scaled_size (rc, page_width, page_height,
+ &thumb_width, &thumb_height);
surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
thumb_width, thumb_height);
@@ -632,7 +627,8 @@ djvu_selection_get_selection_rects (DjvuDocument *djvu_document,
static cairo_region_t *
djvu_get_selection_region (DjvuDocument *djvu_document,
gint page,
- gdouble scale,
+ gdouble scale_x,
+ gdouble scale_y,
EvRectangle *points)
{
double height, dpi;
@@ -654,10 +650,10 @@ djvu_get_selection_region (DjvuDocument *djvu_document,
r->y1 = height - r->y2 * 72 / dpi;
r->y2 = height - tmp * 72 / dpi;
- rect.x = (gint) ((r->x1 * scale) + 0.5);
- rect.y = (gint) ((r->y1 * scale) + 0.5);
- rect.width = (gint) (((r->x2 - r->x1) * scale) + 0.5);
- rect.height = (gint) (((r->y2 - r->y1) * scale) + 0.5);
+ rect.x = (gint) ((r->x1 * scale_x) + 0.5);
+ rect.y = (gint) ((r->y1 * scale_y) + 0.5);
+ rect.width = (gint) ((r->x2 * scale_x) + 0.5) - rect.x;
+ rect.height = (gint) ((r->y2 * scale_y) + 0.5) - rect.y;
cairo_region_union_rectangle (region, &rect);
ev_rectangle_free (r);
}
@@ -673,9 +669,14 @@ djvu_selection_get_selection_region (EvSelection *selection,
EvRectangle *points)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (selection);
+ gdouble page_width, page_height;
+ gdouble scale_x, scale_y;
+
+ document_get_page_size (djvu_document, rc->page->index, &page_width, &page_height, NULL);
+ ev_render_context_compute_scales (rc, page_width, page_height, &scale_x, &scale_y);
return djvu_get_selection_region (djvu_document, rc->page->index,
- rc->scale, points);
+ scale_x, scale_y, points);
}
static gchar *
@@ -720,7 +721,7 @@ djvu_document_text_get_text_mapping (EvDocumentText *document_text,
&points.x2, &points.y2, NULL);
return djvu_get_selection_region (djvu_document, page->index,
- 1.0, &points);
+ 1.0, 1.0, &points);
}
static gchar *
diff --git a/backend/dvi/cairo-device.c b/backend/dvi/cairo-device.c
index 9f4badb..f46da99 100644
--- a/backend/dvi/cairo-device.c
+++ b/backend/dvi/cairo-device.c
@@ -32,7 +32,8 @@ typedef struct {
gint xmargin;
gint ymargin;
- gdouble scale;
+ gdouble xscale;
+ gdouble yscale;
Ulong fg;
Ulong bg;
@@ -104,18 +105,17 @@ dvi_cairo_draw_rule (DviContext *dvi,
color = cairo_device->fg;
cairo_save (cairo_device->cr);
+ cairo_scale (cairo_device->cr, cairo_device->xscale, cairo_device->yscale);
- cairo_set_line_width (cairo_device->cr,
- cairo_get_line_width (cairo_device->cr) * cairo_device->scale);
cairo_set_source_rgb (cairo_device->cr,
((color >> 16) & 0xff) / 255.,
((color >> 8) & 0xff) / 255.,
((color >> 0) & 0xff) / 255.);
cairo_rectangle (cairo_device->cr,
- x + cairo_device->xmargin,
- y + cairo_device->ymargin,
- width, height);
+ (x + cairo_device->xmargin) / cairo_device->xscale,
+ (y + cairo_device->ymargin) / cairo_device->yscale,
+ width / cairo_device->xscale, height / cairo_device->yscale);
if (fill == 0) {
cairo_stroke (cairo_device->cr);
} else {
@@ -362,11 +362,13 @@ mdvi_cairo_device_set_margins (DviDevice *device,
void
mdvi_cairo_device_set_scale (DviDevice *device,
- gdouble scale)
+ gdouble xscale,
+ gdouble yscale)
{
DviCairoDevice *cairo_device;
cairo_device = (DviCairoDevice *) device->device_data;
- cairo_device->scale = scale;
+ cairo_device->xscale = xscale;
+ cairo_device->yscale = yscale;
}
diff --git a/backend/dvi/cairo-device.h b/backend/dvi/cairo-device.h
index bf76d2a..9ef6b6f 100644
--- a/backend/dvi/cairo-device.h
+++ b/backend/dvi/cairo-device.h
@@ -34,7 +34,8 @@ void mdvi_cairo_device_set_margins (DviDevice *device,
gint xmargin,
gint ymargin);
void mdvi_cairo_device_set_scale (DviDevice *device,
- gdouble scale);
+ gdouble xscale,
+ gdouble yscale);
G_END_DECLS
diff --git a/backend/dvi/dvi-document.c b/backend/dvi/dvi-document.c
index 74f91cb..cbb3f8a 100644
--- a/backend/dvi/dvi-document.c
+++ b/backend/dvi/dvi-document.c
@@ -164,6 +164,7 @@ dvi_document_render (EvDocument *document,
cairo_surface_t *surface;
cairo_surface_t *rotated_surface;
DviDocument *dvi_document = DVI_DOCUMENT(document);
+ gdouble xscale, yscale;
gint required_width, required_height;
gint proposed_width, proposed_height;
gint xmargin = 0, ymargin = 0;
@@ -176,12 +177,14 @@ dvi_document_render (EvDocument *document,
mdvi_setpage (dvi_document->context, rc->page->index);
+ ev_render_context_compute_scales (rc, dvi_document->base_width, dvi_document->base_height,
+ &xscale, &yscale);
mdvi_set_shrink (dvi_document->context,
- (int)((dvi_document->params->hshrink - 1) / rc->scale) + 1,
- (int)((dvi_document->params->vshrink - 1) / rc->scale) + 1);
+ (int)((dvi_document->params->hshrink - 1) / xscale) + 1,
+ (int)((dvi_document->params->vshrink - 1) / yscale) + 1);
- required_width = dvi_document->base_width * rc->scale + 0.5;
- required_height = dvi_document->base_height * rc->scale + 0.5;
+ ev_render_context_compute_scaled_size (rc, dvi_document->base_width, dvi_document->base_height,
+ &required_width, &required_height);
proposed_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv;
proposed_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv;
@@ -191,7 +194,7 @@ dvi_document_render (EvDocument *document,
ymargin = (required_height - proposed_height) / 2;
mdvi_cairo_device_set_margins (&dvi_document->context->device, xmargin, ymargin);
- mdvi_cairo_device_set_scale (&dvi_document->context->device, rc->scale);
+ mdvi_cairo_device_set_scale (&dvi_document->context->device, xscale, yscale);
mdvi_cairo_device_render (dvi_document->context);
surface = mdvi_cairo_device_get_surface (&dvi_document->context->device);
diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc
index b6e34e7..f418191 100644
--- a/backend/pdf/ev-poppler.cc
+++ b/backend/pdf/ev-poppler.cc
@@ -385,6 +385,8 @@ pdf_page_render (PopplerPage *page,
{
cairo_surface_t *surface;
cairo_t *cr;
+ double page_width, page_height;
+ double xscale, yscale;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
width, height);
@@ -403,7 +405,12 @@ pdf_page_render (PopplerPage *page,
default:
cairo_translate (cr, 0, 0);
}
- cairo_scale (cr, rc->scale, rc->scale);
+
+ poppler_page_get_size (page,
+ &page_width, &page_height);
+
+ ev_render_context_compute_scales (rc, page_width, page_height, &xscale, &yscale);
+ cairo_scale (cr, xscale, yscale);
cairo_rotate (cr, rc->rotation * G_PI / 180.0);
poppler_page_render (page, cr);
@@ -428,15 +435,9 @@ pdf_document_render (EvDocument *document,
poppler_page_get_size (poppler_page,
&width_points, &height_points);
-
- if (rc->rotation == 90 || rc->rotation == 270) {
- width = (int) ((height_points * rc->scale) + 0.5);
- height = (int) ((width_points * rc->scale) + 0.5);
- } else {
- width = (int) ((width_points * rc->scale) + 0.5);
- height = (int) ((height_points * rc->scale) + 0.5);
- }
-
+
+ ev_render_context_compute_transformed_size (rc, width_points, height_points,
+ &width, &height);
return pdf_page_render (poppler_page,
width, height, rc);
}
@@ -475,16 +476,8 @@ pdf_document_get_thumbnail (EvDocument *document,
poppler_page_get_size (poppler_page,
&page_width, &page_height);
- width = MAX ((gint)(page_width * rc->scale + 0.5), 1);
- height = MAX ((gint)(page_height * rc->scale + 0.5), 1);
-
- if (rc->rotation == 90 || rc->rotation == 270) {
- gint temp;
-
- temp = width;
- width = height;
- height = temp;
- }
+ ev_render_context_compute_transformed_size (rc, page_width, page_height,
+ &width, &height);
surface = poppler_page_get_thumbnail (poppler_page);
if (surface) {
@@ -533,16 +526,8 @@ pdf_document_get_thumbnail_surface (EvDocument *document,
poppler_page_get_size (poppler_page,
&page_width, &page_height);
- width = MAX ((gint)(page_width * rc->scale + 0.5), 1);
- height = MAX ((gint)(page_height * rc->scale + 0.5), 1);
-
- if (rc->rotation == 90 || rc->rotation == 270) {
- gint temp;
-
- temp = width;
- width = height;
- height = temp;
- }
+ ev_render_context_compute_transformed_size (rc, page_width, page_height,
+ &width, &height);
surface = poppler_page_get_thumbnail (poppler_page);
if (surface) {
@@ -2073,13 +2058,13 @@ pdf_selection_render_selection (EvSelection *selection,
PopplerColor text_color, base_color;
double width_points, height_points;
gint width, height;
+ double xscale, yscale;
poppler_page = POPPLER_PAGE (rc->page->backend_page);
poppler_page_get_size (poppler_page,
&width_points, &height_points);
- width = (int) ((width_points * rc->scale) + 0.5);
- height = (int) ((height_points * rc->scale) + 0.5);
+ ev_render_context_compute_scaled_size (rc, width_points, height_points, &width, &height);
text_color.red = text->red;
text_color.green = text->green;
@@ -2096,7 +2081,8 @@ pdf_selection_render_selection (EvSelection *selection,
}
cr = cairo_create (*surface);
- cairo_scale (cr, rc->scale, rc->scale);
+ ev_render_context_compute_scales (rc, width_points, height_points, &xscale, &yscale);
+ cairo_scale (cr, xscale, yscale);
cairo_surface_set_device_offset (*surface, 0, 0);
memset (cairo_image_surface_get_data (*surface), 0x00,
cairo_image_surface_get_height (*surface) *
@@ -2125,7 +2111,7 @@ pdf_selection_get_selected_text (EvSelection *selection,
}
static cairo_region_t *
-create_region_from_poppler_region (GList *region, gdouble scale)
+create_region_from_poppler_region (GList *region, gdouble xscale, gdouble yscale)
{
GList *l;
cairo_region_t *retval;
@@ -2138,10 +2124,10 @@ create_region_from_poppler_region (GList *region, gdouble scale)
rectangle = (PopplerRectangle *)l->data;
- rect.x = (gint) ((rectangle->x1 * scale) + 0.5);
- rect.y = (gint) ((rectangle->y1 * scale) + 0.5);
- rect.width = (gint) (((rectangle->x2 - rectangle->x1) * scale) + 0.5);
- rect.height = (gint) (((rectangle->y2 - rectangle->y1) * scale) + 0.5);
+ rect.x = (gint) ((rectangle->x1 * xscale) + 0.5);
+ rect.y = (gint) ((rectangle->y1 * yscale) + 0.5);
+ rect.width = (gint) ((rectangle->x2 * xscale) + 0.5) - rect.x;
+ rect.height = (gint) ((rectangle->y2 * yscale) + 0.5) - rect.y;
cairo_region_union_rectangle (retval, &rect);
poppler_rectangle_free (rectangle);
@@ -2159,13 +2145,18 @@ pdf_selection_get_selection_region (EvSelection *selection,
PopplerPage *poppler_page;
cairo_region_t *retval;
GList *region;
+ double page_width, page_height;
+ double xscale, yscale;
poppler_page = POPPLER_PAGE (rc->page->backend_page);
region = poppler_page_get_selection_region (poppler_page,
1.0,
(PopplerSelectionStyle)style,
(PopplerRectangle *) points);
- retval = create_region_from_poppler_region (region, rc->scale);
+ poppler_page_get_size (poppler_page,
+ &page_width, &page_height);
+ ev_render_context_compute_scales (rc, page_width, page_height, &xscale, &yscale);
+ retval = create_region_from_poppler_region (region, xscale, yscale);
g_list_free (region);
return retval;
@@ -2201,7 +2192,7 @@ pdf_document_text_get_text_mapping (EvDocumentText *document_text,
region = poppler_page_get_selection_region (poppler_page, 1.0,
POPPLER_SELECTION_GLYPH,
&points);
- retval = create_region_from_poppler_region (region, 1.0);
+ retval = create_region_from_poppler_region (region, 1.0, 1.0);
g_list_free (region);
return retval;
diff --git a/backend/ps/ev-spectre.c b/backend/ps/ev-spectre.c
index e47e5fb..265fed3 100644
--- a/backend/ps/ev-spectre.c
+++ b/backend/ps/ev-spectre.c
@@ -299,8 +299,9 @@ ps_document_render (EvDocument *document,
spectre_page_get_size (ps_page, &width_points, &height_points);
- width = (gint) ((width_points * rc->scale) + 0.5);
- height = (gint) ((height_points * rc->scale) + 0.5);
+ ev_render_context_compute_scaled_size (rc, width_points, height_points,
+ &width, &height);
+
rotation = (rc->rotation + get_page_rotation (ps_page)) % 360;
src = spectre_render_context_new ();
diff --git a/backend/tiff/tiff-document.c b/backend/tiff/tiff-document.c
index 7813eb8..80ac0f5 100644
--- a/backend/tiff/tiff-document.c
+++ b/backend/tiff/tiff-document.c
@@ -225,6 +225,7 @@ tiff_document_render (EvDocument *document,
{
TiffDocument *tiff_document = TIFF_DOCUMENT (document);
int width, height;
+ int scaled_width, scaled_height;
float x_res, y_res;
gint rowstride, bytes;
guchar *pixels = NULL;
@@ -323,9 +324,10 @@ tiff_document_render (EvDocument *document,
p += 4;
}
+ ev_render_context_compute_scaled_size (rc, width, height * (x_res / y_res),
+ &scaled_width, &scaled_height);
rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
- (width * rc->scale) + 0.5,
- (height * rc->scale * (x_res / y_res)) +
0.5,
+ scaled_width, scaled_height,
rc->rotation);
cairo_surface_destroy (surface);
@@ -338,6 +340,7 @@ tiff_document_get_thumbnail (EvDocument *document,
{
TiffDocument *tiff_document = TIFF_DOCUMENT (document);
int width, height;
+ int scaled_width, scaled_height;
float x_res, y_res;
gint rowstride, bytes;
guchar *pixels = NULL;
@@ -392,9 +395,10 @@ tiff_document_get_thumbnail (EvDocument *document,
ORIENTATION_TOPLEFT, 0);
pop_handlers ();
+ ev_render_context_compute_scaled_size (rc, width, height * (x_res / y_res),
+ &scaled_width, &scaled_height);
scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
- width * rc->scale,
- height * rc->scale * (x_res / y_res),
+ scaled_width, scaled_height,
GDK_INTERP_BILINEAR);
g_object_unref (pixbuf);
diff --git a/backend/xps/xps-document.c b/backend/xps/xps-document.c
index b759098..149705a 100644
--- a/backend/xps/xps-document.c
+++ b/backend/xps/xps-document.c
@@ -202,7 +202,8 @@ xps_document_render (EvDocument *document,
{
GXPSPage *xps_page;
gdouble page_width, page_height;
- guint width, height;
+ gint width, height;
+ double scale_x, scale_y;
cairo_surface_t *surface;
cairo_t *cr;
GError *error = NULL;
@@ -210,13 +211,8 @@ xps_document_render (EvDocument *document,
xps_page = GXPS_PAGE (rc->page->backend_page);
gxps_page_get_size (xps_page, &page_width, &page_height);
- if (rc->rotation == 90 || rc->rotation == 270) {
- width = (guint) ((page_height * rc->scale) + 0.5);
- height = (guint) ((page_width * rc->scale) + 0.5);
- } else {
- width = (guint) ((page_width * rc->scale) + 0.5);
- height = (guint) ((page_height * rc->scale) + 0.5);
- }
+ ev_render_context_compute_transformed_size (rc, page_width, page_height,
+ &width, &height);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
width, height);
@@ -239,7 +235,10 @@ xps_document_render (EvDocument *document,
cairo_translate (cr, 0, 0);
}
- cairo_scale (cr, rc->scale, rc->scale);
+ ev_render_context_compute_scales (rc, page_width, page_height,
+ &scale_x, &scale_y);
+ cairo_scale (cr, scale_x, scale_y);
+
cairo_rotate (cr, rc->rotation * G_PI / 180.0);
gxps_page_render (xps_page, cr, &error);
cairo_destroy (cr);
diff --git a/help/reference/libdocument/libevdocument-sections.txt
b/help/reference/libdocument/libevdocument-sections.txt
index f21c798..1ad8a85 100644
--- a/help/reference/libdocument/libevdocument-sections.txt
+++ b/help/reference/libdocument/libevdocument-sections.txt
@@ -248,6 +248,10 @@ ev_render_context_new
ev_render_context_set_page
ev_render_context_set_rotation
ev_render_context_set_scale
+ev_render_context_set_target_size
+ev_render_context_compute_scaled_size
+ev_render_context_compute_transformed_size
+ev_render_context_compute_scales
<SUBSECTION Standard>
EV_RENDER_CONTEXT
EV_IS_RENDER_CONTEXT
diff --git a/help/reference/libview/libevview-sections.txt b/help/reference/libview/libevview-sections.txt
index c9f7ac2..9a3e1a3 100644
--- a/help/reference/libview/libevview-sections.txt
+++ b/help/reference/libview/libevview-sections.txt
@@ -214,6 +214,7 @@ ev_job_render_new
ev_job_render_set_selection_info
ev_job_page_data_new
ev_job_thumbnail_new
+ev_job_thumbnail_new_with_target_size
ev_job_thumbnail_set_has_frame
ev_job_thumbnail_set_output_format
ev_job_fonts_new
diff --git a/libdocument/ev-render-context.c b/libdocument/ev-render-context.c
index 9e728a6..11bdf09 100644
--- a/libdocument/ev-render-context.c
+++ b/libdocument/ev-render-context.c
@@ -23,9 +23,10 @@
static void ev_render_context_init (EvRenderContext *rc);
static void ev_render_context_class_init (EvRenderContextClass *class);
-
G_DEFINE_TYPE (EvRenderContext, ev_render_context, G_TYPE_OBJECT);
+#define FLIP_DIMENSIONS(rc) ((rc)->rotation == 90 || (rc)->rotation == 270)
+
static void ev_render_context_init (EvRenderContext *rc) { /* Do Nothing */ }
static void
@@ -65,6 +66,8 @@ ev_render_context_new (EvPage *page,
rc->page = page ? g_object_ref (page) : NULL;
rc->rotation = rotation;
rc->scale = scale;
+ rc->target_width = -1;
+ rc->target_height = -1;
return rc;
}
@@ -99,3 +102,81 @@ ev_render_context_set_scale (EvRenderContext *rc,
rc->scale = scale;
}
+void
+ev_render_context_set_target_size (EvRenderContext *rc,
+ int target_width,
+ int target_height)
+{
+ g_return_if_fail (rc != NULL);
+
+ rc->target_width = target_width;
+ rc->target_height = target_height;
+}
+
+void
+ev_render_context_compute_scaled_size (EvRenderContext *rc,
+ double width_points,
+ double height_points,
+ int *scaled_width,
+ int *scaled_height)
+{
+ g_return_if_fail (rc != NULL);
+
+ if (scaled_width) {
+ if (rc->target_width >= 0) {
+ *scaled_width = FLIP_DIMENSIONS (rc) ? rc->target_height : rc->target_width;
+ } else {
+ *scaled_width = (int) (width_points * rc->scale + 0.5);
+ }
+ }
+
+ if (scaled_height) {
+ if (rc->target_height >= 0) {
+ *scaled_height = FLIP_DIMENSIONS (rc) ? rc->target_width : rc->target_height;
+ } else {
+ *scaled_height = (int) (height_points * rc->scale + 0.5);
+ }
+ }
+}
+
+void
+ev_render_context_compute_transformed_size (EvRenderContext *rc,
+ double width_points,
+ double height_points,
+ int *transformed_width,
+ int *transformed_height)
+{
+ int scaled_width, scaled_height;
+
+ g_return_if_fail (rc != NULL);
+
+ ev_render_context_compute_scaled_size (rc, width_points, height_points,
+ &scaled_width, &scaled_height);
+
+ if (transformed_width)
+ *transformed_width = FLIP_DIMENSIONS (rc) ? scaled_height : scaled_width;
+
+ if (transformed_height)
+ *transformed_height = FLIP_DIMENSIONS (rc) ? scaled_width : scaled_height;
+}
+
+void
+ev_render_context_compute_scales (EvRenderContext *rc,
+ double width_points,
+ double height_points,
+ double *scale_x,
+ double *scale_y)
+{
+ int scaled_width, scaled_height;
+
+ g_return_if_fail (rc != NULL);
+
+ ev_render_context_compute_scaled_size (rc, width_points, height_points,
+ &scaled_width, &scaled_height);
+
+ if (scale_x)
+ *scale_x = scaled_width / width_points;
+
+ if (scale_y)
+ *scale_y = scaled_height / height_points;
+}
diff --git a/libdocument/ev-render-context.h b/libdocument/ev-render-context.h
index 7091c49..76b3740 100644
--- a/libdocument/ev-render-context.h
+++ b/libdocument/ev-render-context.h
@@ -50,6 +50,8 @@ struct _EvRenderContext
EvPage *page;
gint rotation;
gdouble scale;
+ gint target_width;
+ gint target_height;
};
@@ -63,7 +65,24 @@ void ev_render_context_set_rotation (EvRenderContext *rc,
gint rotation);
void ev_render_context_set_scale (EvRenderContext *rc,
gdouble scale);
-
+void ev_render_context_set_target_size (EvRenderContext *rc,
+ int target_width,
+ int target_height);
+void ev_render_context_compute_scaled_size (EvRenderContext *rc,
+ double width_points,
+ double height_points,
+ int *scaled_width,
+ int *scaled_height);
+void ev_render_context_compute_transformed_size (EvRenderContext *rc,
+ double width_points,
+ double height_points,
+ int *transformed_width,
+ int *transformed_height);
+void ev_render_context_compute_scales (EvRenderContext *rc,
+ double width_points,
+ double height_points,
+ double *scale_x,
+ double *scale_y);
G_END_DECLS
diff --git a/libview/ev-jobs.c b/libview/ev-jobs.c
index 83c50d8..e118855 100644
--- a/libview/ev-jobs.c
+++ b/libview/ev-jobs.c
@@ -631,6 +631,8 @@ ev_job_render_run (EvJob *job)
ev_page = ev_document_get_page (job->document, job_render->page);
rc = ev_render_context_new (ev_page, job_render->rotation, job_render->scale);
+ ev_render_context_set_target_size (rc,
+ job_render->target_width, job_render->target_height);
g_object_unref (ev_page);
job_render->surface = ev_document_render (job->document, rc);
@@ -848,6 +850,8 @@ ev_job_thumbnail_run (EvJob *job)
page = ev_document_get_page (job->document, job_thumb->page);
rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ ev_render_context_set_target_size (rc,
+ job_thumb->target_width, job_thumb->target_height);
g_object_unref (page);
if (job_thumb->format == EV_JOB_THUMBNAIL_PIXBUF)
@@ -897,10 +901,28 @@ ev_job_thumbnail_new (EvDocument *document,
job->scale = scale;
job->has_frame = TRUE;
job->format = EV_JOB_THUMBNAIL_PIXBUF;
+ job->target_width = -1;
+ job->target_height = -1;
return EV_JOB (job);
}
+EvJob *
+ev_job_thumbnail_new_with_target_size (EvDocument *document,
+ gint page,
+ gint rotation,
+ gint target_width,
+ gint target_height)
+{
+ EvJob *job = ev_job_thumbnail_new (document, page, rotation, 1.);
+ EvJobThumbnail *job_thumb = EV_JOB_THUMBNAIL (job);
+
+ job_thumb->target_width = target_width;
+ job_thumb->target_height = target_height;
+
+ return job;
+}
+
/**
* ev_job_thumbnail_set_has_frame:
* @job:
diff --git a/libview/ev-jobs.h b/libview/ev-jobs.h
index 634b41b..057bdae 100644
--- a/libview/ev-jobs.h
+++ b/libview/ev-jobs.h
@@ -343,6 +343,8 @@ struct _EvJobThumbnail
gint page;
gint rotation;
gdouble scale;
+ gint target_width;
+ gint target_height;
GdkPixbuf *thumbnail;
gboolean has_frame;
@@ -542,6 +544,11 @@ EvJob *ev_job_thumbnail_new (EvDocument *document,
gint page,
gint rotation,
gdouble scale);
+EvJob *ev_job_thumbnail_new_with_target_size (EvDocument *document,
+ gint page,
+ gint rotation,
+ gint target_width,
+ gint target_height);
void ev_job_thumbnail_set_has_frame (EvJobThumbnail *job,
gboolean has_frame);
void ev_job_thumbnail_set_output_format (EvJobThumbnail *job,
diff --git a/libview/ev-pixbuf-cache.c b/libview/ev-pixbuf-cache.c
index 897d3de..4d0f876 100644
--- a/libview/ev-pixbuf-cache.c
+++ b/libview/ev-pixbuf-cache.c
@@ -652,7 +652,7 @@ add_job (EvPixbufCache *pixbuf_cache,
job_info->region = region ? cairo_region_reference (region) : NULL;
job_info->job = ev_job_render_new (pixbuf_cache->document,
- page, rotation, scale,
+ page, rotation, 0.,
width, height);
if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
@@ -1033,6 +1033,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
GdkColor text, base;
EvRenderContext *rc;
EvPage *ev_page;
+ gint width, height;
/* we need to get a new selection pixbuf */
ev_document_doc_mutex_lock ();
@@ -1044,7 +1045,12 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
}
ev_page = ev_document_get_page (pixbuf_cache->document, page);
- rc = ev_render_context_new (ev_page, 0, scale);
+ _get_page_size_for_scale_and_rotation (pixbuf_cache->document,
+ page, scale, 0,
+ &width, &height);
+
+ rc = ev_render_context_new (ev_page, 0, 0.);
+ ev_render_context_set_target_size (rc, width, height);
g_object_unref (ev_page);
get_selection_colors (EV_VIEW (pixbuf_cache->view), &text, &base);
@@ -1098,10 +1104,17 @@ ev_pixbuf_cache_get_selection_region (EvPixbufCache *pixbuf_cache,
if (ev_rect_cmp (&(job_info->target_points), &(job_info->selection_region_points))) {
EvRenderContext *rc;
EvPage *ev_page;
+ gint width, height;
ev_document_doc_mutex_lock ();
ev_page = ev_document_get_page (pixbuf_cache->document, page);
- rc = ev_render_context_new (ev_page, 0, scale);
+
+ _get_page_size_for_scale_and_rotation (pixbuf_cache->document,
+ page, scale, 0,
+ &width, &height);
+
+ rc = ev_render_context_new (ev_page, 0, 0.);
+ ev_render_context_set_target_size (rc, width, height);
g_object_unref (ev_page);
if (job_info->selection_region)
diff --git a/libview/ev-view-presentation.c b/libview/ev-view-presentation.c
index 7707b7c..3bdf4e6 100644
--- a/libview/ev-view-presentation.c
+++ b/libview/ev-view-presentation.c
@@ -65,7 +65,6 @@ struct _EvViewPresentation
guint rotation;
gboolean inverted_colors;
EvPresentationState state;
- gdouble scale;
gint monitor_width;
gint monitor_height;
@@ -168,25 +167,30 @@ ev_view_presentation_set_end (EvViewPresentation *pview)
gtk_widget_queue_draw (widget);
}
-static gdouble
-ev_view_presentation_get_scale_for_page (EvViewPresentation *pview,
- guint page)
+static void
+ev_view_presentation_get_view_size (EvViewPresentation *pview,
+ guint page,
+ int *view_width,
+ int *view_height)
{
- if (!ev_document_is_page_size_uniform (pview->document) || pview->scale == 0) {
- gdouble width, height;
+ gdouble width, height;
- ev_document_get_page_size (pview->document, page, &width, &height);
- if (pview->rotation == 90 || pview->rotation == 270) {
- gdouble tmp;
+ ev_document_get_page_size (pview->document, page, &width, &height);
+ if (pview->rotation == 90 || pview->rotation == 270) {
+ gdouble tmp;
- tmp = width;
- width = height;
- height = tmp;
- }
- pview->scale = MIN (pview->monitor_width / width, pview->monitor_height / height);
+ tmp = width;
+ width = height;
+ height = tmp;
}
- return pview->scale;
+ if (pview->monitor_width / width < pview->monitor_height / height) {
+ *view_width = pview->monitor_width;
+ *view_height = (int)((pview->monitor_width / width) * height + 0.5);
+ } else {
+ *view_width = (int)((pview->monitor_height / height) * width + 0.5);
+ *view_height = pview->monitor_height;
+ }
}
static void
@@ -195,22 +199,10 @@ ev_view_presentation_get_page_area (EvViewPresentation *pview,
{
GtkWidget *widget = GTK_WIDGET (pview);
GtkAllocation allocation;
- gdouble doc_width, doc_height;
gint view_width, view_height;
- gdouble scale;
- ev_document_get_page_size (pview->document,
- pview->current_page,
- &doc_width, &doc_height);
- scale = ev_view_presentation_get_scale_for_page (pview, pview->current_page);
-
- if (pview->rotation == 90 || pview->rotation == 270) {
- view_width = (gint)((doc_height * scale) + 0.5);
- view_height = (gint)((doc_width * scale) + 0.5);
- } else {
- view_width = (gint)((doc_width * scale) + 0.5);
- view_height = (gint)((doc_height * scale) + 0.5);
- }
+ ev_view_presentation_get_view_size (pview, pview->current_page,
+ &view_width, &view_height);
gtk_widget_get_allocation (widget, &allocation);
@@ -353,14 +345,15 @@ ev_view_presentation_schedule_new_job (EvViewPresentation *pview,
gint page,
EvJobPriority priority)
{
- EvJob *job;
- gdouble scale;
+ EvJob *job;
+ int view_width, view_height;
if (page < 0 || page >= ev_document_get_n_pages (pview->document))
return NULL;
- scale = ev_view_presentation_get_scale_for_page (pview, page);
- job = ev_job_render_new (pview->document, page, pview->rotation, scale, 0, 0);
+ ev_view_presentation_get_view_size (pview, page, &view_width, &view_height);
+ job = ev_job_render_new (pview->document, page, pview->rotation, 0.,
+ view_width, view_height);
g_signal_connect (job, "finished",
G_CALLBACK (job_finished_cb),
pview);
@@ -794,33 +787,31 @@ ev_view_presentation_get_link_at_location (EvViewPresentation *pview,
EvLink *link;
gdouble width, height;
gdouble new_x, new_y;
- gdouble scale;
if (!pview->page_cache)
return NULL;
ev_document_get_page_size (pview->document, pview->current_page, &width, &height);
ev_view_presentation_get_page_area (pview, &page_area);
- scale = ev_view_presentation_get_scale_for_page (pview, pview->current_page);
- x = (x - page_area.x) / scale;
- y = (y - page_area.y) / scale;
+ x = (x - page_area.x) / page_area.width;
+ y = (y - page_area.y) / page_area.height;
switch (pview->rotation) {
case 0:
case 360:
- new_x = x;
- new_y = y;
+ new_x = width * x;
+ new_y = height * y;
break;
case 90:
- new_x = y;
- new_y = height - x;
+ new_x = width * y;
+ new_y = height * (1 - x);
break;
case 180:
- new_x = width - x;
- new_y = height - y;
+ new_x = width * (1 - x);
+ new_y = height * (1 - y);
break;
case 270:
- new_x = width - y;
- new_y = x;
+ new_x = width * (1 - y);
+ new_y = height * x;
break;
default:
g_assert_not_reached ();
@@ -1601,7 +1592,6 @@ ev_view_presentation_set_rotation (EvViewPresentation *pview,
if (pview->is_constructing)
return;
- pview->scale = 0;
ev_view_presentation_reset_jobs (pview);
ev_view_presentation_update_current_page (pview, pview->current_page);
}
diff --git a/libview/ev-view.c b/libview/ev-view.c
index 7560084..acd9890 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -890,7 +890,10 @@ compute_scroll_increment (EvView *view,
cairo_region_get_rectangle (region, 0, &rect);
ev_page = ev_document_get_page (view->document, page);
- rc = ev_render_context_new (ev_page, view->rotation, view->scale);
+ rc = ev_render_context_new (ev_page, view->rotation, 0.);
+ ev_render_context_set_target_size (rc,
+ page_area.width - (border.left + border.right),
+ page_area.height - (border.left + border.right));
g_object_unref (ev_page);
/* Get the selection region to know the height of the line */
doc_rect.x1 = doc_rect.x2 = rect.x + 0.5;
@@ -6005,7 +6008,7 @@ draw_surface (cairo_t *cr,
scale_x = (gdouble)target_width / width;
scale_y = (gdouble)target_height / height;
cairo_pattern_set_filter (cairo_get_source (cr),
- CAIRO_FILTER_FAST);
+ CAIRO_FILTER_NEAREST);
cairo_scale (cr, scale_x, scale_y);
offset_x /= scale_x;
diff --git a/shell/ev-sidebar-thumbnails.c b/shell/ev-sidebar-thumbnails.c
index 8ab8fa8..38d71d9 100644
--- a/shell/ev-sidebar-thumbnails.c
+++ b/shell/ev-sidebar-thumbnails.c
@@ -453,16 +453,27 @@ clear_range (EvSidebarThumbnails *sidebar_thumbnails,
gtk_tree_path_free (path);
}
-static gdouble
-get_scale_for_page (EvSidebarThumbnails *sidebar_thumbnails,
- gint page)
+static void
+get_size_for_page (EvSidebarThumbnails *sidebar_thumbnails,
+ gint page,
+ gint *width_return,
+ gint *height_return)
{
EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
- gdouble width;
+ gdouble width, height;
+ gint thumbnail_height;
ev_document_get_page_size (priv->document, page, &width, NULL);
+ ev_document_get_page_size (priv->document, page, &width, &height);
+ thumbnail_height = (int)(THUMBNAIL_WIDTH * height / width + 0.5);
- return (gdouble)THUMBNAIL_WIDTH / width;
+ if (priv->rotation == 90 || priv->rotation == 270) {
+ *width_return = thumbnail_height;
+ *height_return = THUMBNAIL_WIDTH;
+ } else {
+ *width_return = THUMBNAIL_WIDTH;
+ *height_return = thumbnail_height;
+ }
}
static void
@@ -491,9 +502,12 @@ add_range (EvSidebarThumbnails *sidebar_thumbnails,
-1);
if (job == NULL && !thumbnail_set) {
- job = ev_job_thumbnail_new (priv->document,
- page, priv->rotation,
- get_scale_for_page (sidebar_thumbnails, page));
+ gint thumbnail_width, thumbnail_height;
+ get_size_for_page (sidebar_thumbnails, page, &thumbnail_width, &thumbnail_height);
+
+ job = ev_job_thumbnail_new_with_target_size (priv->document,
+ page, priv->rotation,
+ thumbnail_width, thumbnail_height);
ev_job_thumbnail_set_has_frame (EV_JOB_THUMBNAIL (job), FALSE);
ev_job_thumbnail_set_output_format (EV_JOB_THUMBNAIL (job),
EV_JOB_THUMBNAIL_SURFACE);
g_object_set_data_full (G_OBJECT (job), "tree_iter",
diff --git a/shell/ev-window.c b/shell/ev-window.c
index 978c55f..a4f8a8a 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -1396,8 +1396,8 @@ ev_window_set_icon_from_thumbnail (EvJobThumbnail *job,
static void
ev_window_refresh_window_thumbnail (EvWindow *ev_window)
{
- gdouble page_width;
- gdouble scale;
+ gdouble page_width, page_height;
+ gint width, height;
gint rotation;
EvDocument *document = ev_window->priv->document;
@@ -1408,11 +1408,13 @@ ev_window_refresh_window_thumbnail (EvWindow *ev_window)
ev_window_clear_thumbnail_job (ev_window);
- ev_document_get_page_size (document, 0, &page_width, NULL);
- scale = 128. / page_width;
+ ev_document_get_page_size (document, 0, &page_width, &page_height);
+ width = 128;
+ height = (int)(width * page_height / page_width + 0.5);
rotation = ev_document_model_get_rotation (ev_window->priv->model);
- ev_window->priv->thumbnail_job = ev_job_thumbnail_new (document, 0, rotation, scale);
+ ev_window->priv->thumbnail_job = ev_job_thumbnail_new_with_target_size (document, 0, rotation,
+ width, height);
g_signal_connect (ev_window->priv->thumbnail_job, "finished",
G_CALLBACK (ev_window_set_icon_from_thumbnail),
ev_window);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]