+2007-06-13 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * backend/dvi/dvi-document.c: (dvi_document_render),
+ (dvi_document_render_pixbuf), (dvi_document_document_iface_init):
+ * backend/impress/impress-document.c:
+ (imp_render_get_from_drawable), (impress_document_render_pixbuf),
+ (impress_document_render), (impress_document_document_iface_init),
+ (impress_document_thumbnails_get_thumbnail):
+ * backend/djvu/djvu-document-private.h:
+ * backend/djvu/djvu-document.c: (djvu_document_render),
+ (djvu_document_finalize), (djvu_document_document_iface_init),
+ (djvu_document_thumbnails_get_thumbnail), (djvu_document_init):
+ * backend/tiff/tiff-document.c: (tiff_document_render),
+ (tiff_document_render_pixbuf),
+ (tiff_document_document_iface_init):
+ * backend/pdf/ev-poppler.cc: (pdf_document_render),
+ (pdf_document_render_pixbuf), (pdf_document_document_iface_init),
+ (pdf_selection_render_selection):
+ * backend/comics/comics-document.c:
+ (comics_document_render_pixbuf), (comics_document_render),
+ (comics_document_document_iface_init):
+ * backend/pixbuf/pixbuf-document.c: (pixbuf_document_render),
+ (pixbuf_document_document_iface_init):
+ * libdocument/ev-document-misc.[ch]:
+ (ev_document_misc_surface_from_pixbuf),
+ (ev_document_misc_surface_rotate_and_scale):
+ * libdocument/ev-document.[ch]: (ev_document_render):
+ * libdocument/ev-selection.[ch]: (ev_selection_render_selection):
+ * shell/ev-pixbuf-cache.[ch]: (dispose_cache_job_info),
+ (move_one_job), (copy_job_to_job_info), (add_job_if_needed),
+ (ev_pixbuf_cache_get_surface), (new_selection_surface_needed),
+ (clear_selection_if_needed), (ev_pixbuf_cache_style_changed),
+ (ev_pixbuf_cache_get_selection_surface), (clear_job_selection):
+ * shell/ev-jobs.[ch]: (ev_job_render_dispose),
+ (render_finished_cb), (ev_job_render_run):
+ * shell/ev-view.c: (draw_loading_text), (draw_one_page),
+ (merge_selection_region):
+
+ Use cairo image surfaces instead of GDK pixbufs for drawing pages
+ and selections.
+
2007-06-12 Carlos Garcia Campos <carlosgc@gnome.org>
* shell/ev-window-title.c: (ev_window_title_update):
}
static GdkPixbuf *
-comics_document_render_pixbuf (EvDocument *document,
+comics_document_render_pixbuf (EvDocument *document,
EvRenderContext *rc)
{
GdkPixbufLoader *loader;
360 - rc->rotation);
g_spawn_close_pid (child_pid);
g_object_unref (loader);
+
return rotated_pixbuf;
}
+static cairo_surface_t *
+comics_document_render (EvDocument *document,
+ EvRenderContext *rc)
+{
+ GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
+
+ pixbuf = comics_document_render_pixbuf (document, rc);
+ surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
+
+ return surface;
+}
+
static void
render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
gint width,
gpointer data)
{
double *scale = data;
- int w = width * (*scale);
- int h = height * (*scale);
+ int w = (width * (*scale) + 0.5);
+ int h = (height * (*scale) + 0.5);
gdk_pixbuf_loader_set_size (loader, w, h);
}
{
iface->load = comics_document_load;
iface->save = comics_document_save;
- iface->can_get_text = comics_document_can_get_text;
- iface->get_n_pages = comics_document_get_n_pages;
+ iface->can_get_text = comics_document_can_get_text;
+ iface->get_n_pages = comics_document_get_n_pages;
iface->get_page_size = comics_document_get_page_size;
- iface->render_pixbuf = comics_document_render_pixbuf;
- iface->get_info = comics_document_get_info;
+ iface->render = comics_document_render;
+ iface->get_info = comics_document_get_info;
}
static void
ddjvu_context_t *d_context;
ddjvu_document_t *d_document;
ddjvu_format_t *d_format;
+ ddjvu_format_t *thumbs_format;
gchar *uri;
while ((r = ddjvu_document_get_pageinfo(djvu_document->d_document, page, &info)) < DDJVU_JOB_OK)
djvu_handle_events(djvu_document, TRUE);
-
+
if (r >= DDJVU_JOB_FAILED)
djvu_handle_events(djvu_document, TRUE);
*height = info.height * SCALE_FACTOR;
}
-static GdkPixbuf *
-djvu_document_render_pixbuf (EvDocument *document,
- EvRenderContext *rc)
+static cairo_surface_t *
+djvu_document_render (EvDocument *document,
+ EvRenderContext *rc)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
- GdkPixbuf *pixbuf;
- GdkPixbuf *rotated_pixbuf;
-
+ cairo_surface_t *surface, *rotated_surface;
+ gchar *pixels;
+ gint rowstride;
ddjvu_rect_t rrect;
ddjvu_rect_t prect;
ddjvu_page_t *d_page;
-
double page_width, page_height;
+ static const cairo_user_data_key_t key;
d_page = ddjvu_page_create_by_pageno (djvu_document->d_document, rc->page);
while (!ddjvu_page_decoding_done (d_page))
djvu_handle_events(djvu_document, TRUE);
-
- page_width = ddjvu_page_get_width (d_page) * rc->scale * SCALE_FACTOR;
- page_height = ddjvu_page_get_height (d_page) * rc->scale * SCALE_FACTOR;
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, page_width, page_height);
-
- prect.x = 0; prect.y = 0;
- prect.w = page_width; prect.h = page_height;
+ page_width = ddjvu_page_get_width (d_page) * rc->scale * SCALE_FACTOR + 0.5;
+ page_height = ddjvu_page_get_height (d_page) * rc->scale * SCALE_FACTOR + 0.5;
+
+ rowstride = page_width * 4;
+ pixels = (gchar *) g_malloc (page_height * rowstride);
+ surface = cairo_image_surface_create_for_data (pixels,
+ CAIRO_FORMAT_ARGB32,
+ page_width,
+ page_height,
+ rowstride);
+ cairo_surface_set_user_data (surface, &key,
+ pixels, (cairo_destroy_func_t)g_free);
+ prect.x = 0;
+ prect.y = 0;
+ prect.w = page_width;
+ prect.h = page_height;
rrect = prect;
- ddjvu_page_render(d_page, DDJVU_RENDER_COLOR,
- &prect,
- &rrect,
- djvu_document->d_format,
- gdk_pixbuf_get_rowstride (pixbuf),
- (gchar *)gdk_pixbuf_get_pixels (pixbuf));
-
- rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rc->rotation);
- g_object_unref (pixbuf);
-
- return rotated_pixbuf;
+ ddjvu_page_render (d_page, DDJVU_RENDER_COLOR,
+ &prect,
+ &rrect,
+ djvu_document->d_format,
+ rowstride,
+ pixels);
+
+ rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
+ page_width,
+ page_height,
+ rc->rotation);
+ cairo_surface_destroy (surface);
+
+ return rotated_surface;
}
static void
ddjvu_context_release (djvu_document->d_context);
ddjvu_format_release (djvu_document->d_format);
+ ddjvu_format_release (djvu_document->thumbs_format);
g_free (djvu_document->uri);
G_OBJECT_CLASS (djvu_document_parent_class)->finalize (object);
iface->get_text = djvu_document_get_text;
iface->get_n_pages = djvu_document_get_n_pages;
iface->get_page_size = djvu_document_get_page_size;
- iface->render_pixbuf = djvu_document_render_pixbuf;
+ iface->render = djvu_document_render;
iface->get_info = djvu_document_get_info;
}
ddjvu_thumbnail_render (djvu_document->d_document, rc->page,
&thumb_width, &thumb_height,
- djvu_document->d_format,
+ djvu_document->thumbs_format,
gdk_pixbuf_get_rowstride (pixbuf),
(gchar *)pixels);
static void
djvu_document_file_exporter_begin (EvFileExporter *exporter,
- EvFileExporterFormat format,
- const char *filename, /* for storing the temp ps file */
- int first_page,
- int last_page,
- double width,
- double height,
- gboolean duplex)
+ EvFileExporterFormat format,
+ const char *filename, /* for storing the temp ps file */
+ int first_page,
+ int last_page,
+ double width,
+ double height,
+ gboolean duplex)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (exporter);
}
static void
-djvu_document_file_exporter_do_page (EvFileExporter *exporter, EvRenderContext *rc)
+djvu_document_file_exporter_do_page (EvFileExporter *exporter,
+ EvRenderContext *rc)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (exporter);
static void
djvu_document_init (DjvuDocument *djvu_document)
{
+ guint masks[4] = { 0xff0000, 0xff00, 0xff, 0xff000000 };
+
djvu_document->d_context = ddjvu_context_create ("Evince");
- djvu_document->d_format = ddjvu_format_create (DDJVU_FORMAT_RGB24, 0, 0);
- ddjvu_format_set_row_order (djvu_document->d_format,1);
+ djvu_document->d_format = ddjvu_format_create (DDJVU_FORMAT_RGBMASK32, 4, masks);
+ ddjvu_format_set_row_order (djvu_document->d_format, 1);
+
+ djvu_document->thumbs_format = ddjvu_format_create (DDJVU_FORMAT_RGB24, 0, 0);
+ ddjvu_format_set_row_order (djvu_document->thumbs_format, 1);
djvu_document->ps_filename = NULL;
djvu_document->opts = g_string_new ("");
return;
}
-static GdkPixbuf *
-dvi_document_render_pixbuf (EvDocument *document,
- EvRenderContext *rc)
+static cairo_surface_t *
+dvi_document_render (EvDocument *document,
+ EvRenderContext *rc)
{
GdkPixbuf *pixbuf;
- GdkPixbuf *rotated_pixbuf;
-
+ cairo_surface_t *surface;
+ cairo_surface_t *rotated_surface;
DviDocument *dvi_document = DVI_DOCUMENT(document);
-
gint required_width, required_height;
gint proposed_width, proposed_height;
gint xmargin = 0, ymargin = 0;
(int)((dvi_document->params->hshrink - 1) / rc->scale) + 1,
(int)((dvi_document->params->vshrink - 1) / rc->scale) + 1);
- required_width = dvi_document->base_width * rc->scale;
- required_height = dvi_document->base_height * rc->scale;
+ required_width = dvi_document->base_width * rc->scale + 0.5;
+ required_height = dvi_document->base_height * rc->scale + 0.5;
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;
g_mutex_unlock (dvi_context_mutex);
- rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rc->rotation);
+ /* FIXME: we should write a mdvi device based on cairo */
+ surface = ev_document_misc_surface_from_pixbuf (pixbuf);
g_object_unref (pixbuf);
- return rotated_pixbuf;
+ rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
+ required_width,
+ required_height,
+ rc->rotation);
+ cairo_surface_destroy (surface);
+
+ return rotated_surface;
}
static void
iface->can_get_text = dvi_document_can_get_text;
iface->get_n_pages = dvi_document_get_n_pages;
iface->get_page_size = dvi_document_get_page_size;
- iface->render_pixbuf = dvi_document_render_pixbuf;
+ iface->render = dvi_document_render;
iface->get_info = dvi_document_get_info;
}
g_return_val_if_fail (page != NULL, FALSE);
+ ev_document_doc_mutex_lock ();
imp_context_set_page (impress_document->ctx, page);
imp_render (impress_document->ctx, impress_document);
+ ev_document_doc_mutex_unlock ();
impress_document->pixbuf = gdk_pixbuf_get_from_drawable (NULL,
GDK_DRAWABLE (impress_document->pixmap),
}
static GdkPixbuf *
-impress_document_render_pixbuf (EvDocument *document,
+impress_document_render_pixbuf (EvDocument *document,
EvRenderContext *rc)
{
ImpressDocument *impress_document = IMPRESS_DOCUMENT (document);
- GdkPixbuf *scaled_pixbuf;
-
- g_return_val_if_fail (IMPRESS_IS_DOCUMENT (document), 0);
- g_return_val_if_fail (impress_document->imp != NULL, 0);
+ GdkPixbuf *pixbuf;
+ g_return_val_if_fail (IMPRESS_IS_DOCUMENT (document), NULL);
+ g_return_val_if_fail (impress_document->imp != NULL, NULL);
+
impress_document->pagenum = rc->page;
g_mutex_lock (impress_document->mutex);
impress_document->cond = g_cond_new ();
ev_document_fc_mutex_unlock ();
+ ev_document_doc_mutex_unlock ();
g_idle_add ((GSourceFunc) imp_render_get_from_drawable, impress_document);
g_cond_wait (impress_document->cond, impress_document->mutex);
g_cond_free (impress_document->cond);
+ ev_document_doc_mutex_lock ();
ev_document_fc_mutex_lock ();
-
+
g_mutex_unlock (impress_document->mutex);
- scaled_pixbuf = gdk_pixbuf_scale_simple (impress_document->pixbuf,
- PAGE_WIDTH * rc->scale,
- PAGE_HEIGHT * rc->scale,
- GDK_INTERP_BILINEAR);
- gdk_pixbuf_unref (impress_document->pixbuf);
+ pixbuf = impress_document->pixbuf;
impress_document->pixbuf = NULL;
- return scaled_pixbuf;
+ return pixbuf;
+}
+
+static cairo_surface_t *
+impress_document_render (EvDocument *document,
+ EvRenderContext *rc)
+{
+ GdkPixbuf *pixbuf;
+ cairo_surface_t *surface, *scaled_surface;
+
+ pixbuf = impress_document_render_pixbuf (document, rc);
+
+ /* FIXME: impress backend should be ported to cairo */
+ surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
+
+ scaled_surface = ev_document_misc_surface_rotate_and_scale (surface,
+ (PAGE_WIDTH * rc->scale) + 0.5,
+ (PAGE_HEIGHT * rc->scale) + 0.5,
+ rc->rotation);
+ cairo_surface_destroy (surface);
+
+ return scaled_surface;
}
static void
iface->can_get_text = impress_document_can_get_text;
iface->get_n_pages = impress_document_get_n_pages;
iface->get_page_size = impress_document_get_page_size;
- iface->render_pixbuf = impress_document_render_pixbuf;
+ iface->render = impress_document_render;
iface->get_info = impress_document_get_info;
}
EvRenderContext *rc,
gboolean border)
{
- GdkPixbuf *pixbuf = NULL;
+ GdkPixbuf *pixbuf;
+ GdkPixbuf *scaled_pixbuf;
gdouble w, h;
pixbuf = impress_document_render_pixbuf (EV_DOCUMENT (document), rc);
+ scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
+ (PAGE_WIDTH * rc->scale),
+ (PAGE_HEIGHT * rc->scale),
+ GDK_INTERP_BILINEAR);
+ g_object_unref (pixbuf);
if (border)
{
- GdkPixbuf *tmp_pixbuf = pixbuf;
+ GdkPixbuf *tmp_pixbuf = scaled_pixbuf;
- pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
+ scaled_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
g_object_unref (tmp_pixbuf);
}
- return pixbuf;
+ return scaled_pixbuf;
}
static void
return g_list_reverse (retval);
}
-static GdkPixbuf *
-pdf_document_render_pixbuf (EvDocument *document,
- EvRenderContext *rc)
+static cairo_surface_t *
+pdf_document_render (EvDocument *document,
+ EvRenderContext *rc)
{
PdfDocument *pdf_document;
- GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
double width_points, height_points;
gint width, height;
width = (int) ((width_points * rc->scale) + 0.5);
height = (int) ((height_points * rc->scale) + 0.5);
}
-
+
+#ifdef HAVE_POPPLER_PAGE_RENDER
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width, height);
+ memset (cairo_image_surface_get_data (surface), 0xff,
+ cairo_image_surface_get_height (surface) *
+ cairo_image_surface_get_stride (surface));
+
+ cr = cairo_create (surface);
+ switch (rc->rotation) {
+ case 90:
+ cairo_translate (cr, width, 0);
+ break;
+ case 180:
+ cairo_translate (cr, width, height);
+ break;
+ case 270:
+ cairo_translate (cr, 0, height);
+ break;
+ default:
+ cairo_translate (cr, 0, 0);
+ }
+ cairo_scale (cr, rc->scale, rc->scale);
+ cairo_rotate (cr, rc->rotation * G_PI / 180.0);
+ poppler_page_render (POPPLER_PAGE (rc->data), cr);
+ cairo_destroy (cr);
+#else /* HAVE_POPPLER_PAGE_RENDER */
+ GdkPixbuf *pixbuf;
+
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
FALSE, 8,
width, height);
rc->scale,
rc->rotation,
pixbuf);
-
-
- return pixbuf;
+ surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
+#endif /* HAVE_POPPLER_PAGE_RENDER */
+
+ return surface;
}
/* EvDocumentSecurity */
iface->get_page_label = pdf_document_get_page_label;
iface->has_attachments = pdf_document_has_attachments;
iface->get_attachments = pdf_document_get_attachments;
- iface->render_pixbuf = pdf_document_render_pixbuf;
+ iface->render = pdf_document_render;
iface->get_text = pdf_document_get_text;
iface->can_get_text = pdf_document_can_get_text;
iface->get_info = pdf_document_get_info;
static void
pdf_selection_render_selection (EvSelection *selection,
EvRenderContext *rc,
- GdkPixbuf **pixbuf,
+ cairo_surface_t **surface,
EvRectangle *points,
EvRectangle *old_points,
- GdkColor *text,
- GdkColor *base)
+ GdkColor *text,
+ GdkColor *base)
{
PdfDocument *pdf_document;
double width_points, height_points;
pdf_document = PDF_DOCUMENT (selection);
set_rc_data (pdf_document, rc);
- poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
+ poppler_page_get_size (POPPLER_PAGE (rc->data),
+ &width_points, &height_points);
width = (int) ((width_points * rc->scale) + 0.5);
height = (int) ((height_points * rc->scale) + 0.5);
- if (*pixbuf == NULL) {
- * pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- TRUE, 8,
- width, height);
+
+#ifdef HAVE_POPPLER_PAGE_RENDER
+ cairo_t *cr;
+
+ if (*surface == NULL) {
+ *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width, height);
+
}
+ cr = cairo_create (*surface);
+ cairo_scale (cr, rc->scale, rc->scale);
+ cairo_surface_set_device_offset (*surface, 0, 0);
+ memset (cairo_image_surface_get_data (*surface), 0x00,
+ cairo_image_surface_get_height (*surface) *
+ cairo_image_surface_get_stride (*surface));
+ poppler_page_render_selection (POPPLER_PAGE (rc->data),
+ cr,
+ (PopplerRectangle *)points,
+ (PopplerRectangle *)old_points,
+ POPPLER_SELECTION_NORMAL, /* SelectionStyle */
+ text,
+ base);
+ cairo_destroy (cr);
+#else /* HAVE_POPPLER_PAGE_RENDER */
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ TRUE, 8,
+ width, height);
+
poppler_page_render_selection_to_pixbuf (POPPLER_PAGE (rc->data),
- rc->scale, rc->rotation, *pixbuf,
+ rc->scale, rc->rotation, pixbuf,
(PopplerRectangle *)points,
(PopplerRectangle *)old_points,
POPPLER_SELECTION_NORMAL, /* SelectionStyle */
text,
base);
+ if (*surface)
+ cairo_surface_destroy (*surface);
+ *surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
+#endif /* HAVE_POPPLER_PAGE_RENDER */
}
set_rc_data (pdf_document, rc);
- retval = poppler_page_get_selection_region ((PopplerPage *)rc->data, rc->scale, (PopplerRectangle *) points);
-
+ retval = poppler_page_get_selection_region ((PopplerPage *)rc->data,
+ rc->scale,
+ (PopplerRectangle *) points);
return retval;
}
*height = gdk_pixbuf_get_height (pixbuf_document->pixbuf);
}
-static GdkPixbuf*
-pixbuf_document_render_pixbuf (EvDocument *document,
- EvRenderContext *rc)
+static cairo_surface_t *
+pixbuf_document_render (EvDocument *document,
+ EvRenderContext *rc)
{
PixbufDocument *pixbuf_document = PIXBUF_DOCUMENT (document);
GdkPixbuf *scaled_pixbuf, *rotated_pixbuf;
+ cairo_surface_t *surface;
- scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf_document->pixbuf,
- gdk_pixbuf_get_width (pixbuf_document->pixbuf) * rc->scale,
- gdk_pixbuf_get_height (pixbuf_document->pixbuf) * rc->scale,
- GDK_INTERP_BILINEAR);
-
+ scaled_pixbuf = gdk_pixbuf_scale_simple (
+ pixbuf_document->pixbuf,
+ (gdk_pixbuf_get_width (pixbuf_document->pixbuf) * rc->scale) + 0.5,
+ (gdk_pixbuf_get_height (pixbuf_document->pixbuf) * rc->scale) + 0.5,
+ GDK_INTERP_BILINEAR);
+
rotated_pixbuf = gdk_pixbuf_rotate_simple (scaled_pixbuf, 360 - rc->rotation);
g_object_unref (scaled_pixbuf);
- return rotated_pixbuf;
+ surface = ev_document_misc_surface_from_pixbuf (rotated_pixbuf);
+ g_object_unref (rotated_pixbuf);
+
+ return surface;
}
static void
iface->can_get_text = pixbuf_document_can_get_text;
iface->get_n_pages = pixbuf_document_get_n_pages;
iface->get_page_size = pixbuf_document_get_page_size;
- iface->render_pixbuf = pixbuf_document_render_pixbuf;
+ iface->render = pixbuf_document_render;
iface->get_info = pixbuf_document_get_info;
}
pop_handlers ();
}
-static GdkPixbuf *
-tiff_document_render_pixbuf (EvDocument *document,
- EvRenderContext *rc)
+static cairo_surface_t *
+tiff_document_render (EvDocument *document,
+ EvRenderContext *rc)
{
TiffDocument *tiff_document = TIFF_DOCUMENT (document);
int width, height;
GdkPixbuf *pixbuf;
GdkPixbuf *scaled_pixbuf;
GdkPixbuf *rotated_pixbuf;
+ cairo_surface_t *surface;
+ cairo_surface_t *rotated_surface;
+ static const cairo_user_data_key_t key;
g_return_val_if_fail (TIFF_IS_DOCUMENT (document), NULL);
g_return_val_if_fail (tiff_document->tiff != NULL, NULL);
pop_handlers ();
+ /* Sanity check the doc */
+ if (width <= 0 || height <= 0)
+ return NULL;
+
+ rowstride = width * 4;
+ if (rowstride / 4 != width)
+ /* overflow */
+ return NULL;
+
+ bytes = height * rowstride;
+ if (bytes / rowstride != height)
+ /* overflow */
+ return NULL;
+
+ pixels = g_try_malloc (bytes);
+ if (!pixels)
+ return NULL;
+
+ surface = cairo_image_surface_create_for_data (pixels,
+ CAIRO_FORMAT_ARGB32,
+ width, height,
+ rowstride);
+ cairo_surface_set_user_data (surface, &key,
+ pixels, (cairo_destroy_func_t)g_free);
+
+ TIFFReadRGBAImageOriented (tiff_document->tiff,
+ width, height,
+ (uint32 *)pixels,
+ ORIENTATION_TOPLEFT, 1);
+ pop_handlers ();
+
+ rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
+ (width * rc->scale) + 0.5,
+ (height * rc->scale * (x_res / y_res)) + 0.5,
+ rc->rotation);
+ cairo_surface_destroy (surface);
+
+ return rotated_surface;
+}
+
+static GdkPixbuf *
+tiff_document_render_pixbuf (EvDocument *document,
+ EvRenderContext *rc)
+{
+ TiffDocument *tiff_document = TIFF_DOCUMENT (document);
+ int width, height;
+ float x_res, y_res;
+ gint rowstride, bytes;
+ guchar *pixels = NULL;
+ GdkPixbuf *pixbuf;
+ GdkPixbuf *scaled_pixbuf;
+ GdkPixbuf *rotated_pixbuf;
+
+ push_handlers ();
+ if (TIFFSetDirectory (tiff_document->tiff, rc->page) != 1) {
+ pop_handlers ();
+ return NULL;
+ }
+
+ if (!TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &width)) {
+ pop_handlers ();
+ return NULL;
+ }
+
+ if (! TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &height)) {
+ pop_handlers ();
+ return NULL;
+ }
+
+ tiff_document_get_resolution (tiff_document, &x_res, &y_res);
+
+ pop_handlers ();
+
/* Sanity check the doc */
if (width <= 0 || height <= 0)
return NULL;
pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8,
width, height, rowstride,
(GdkPixbufDestroyNotify) g_free, NULL);
-
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
- TIFFReadRGBAImageOriented (tiff_document->tiff, width, height,
- (uint32 *)gdk_pixbuf_get_pixels (pixbuf),
+ TIFFReadRGBAImageOriented (tiff_document->tiff,
+ width, height,
+ (uint32 *)pixels,
ORIENTATION_TOPLEFT, 1);
pop_handlers ();
-
+
scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
width * rc->scale,
height * rc->scale * (x_res / y_res),
iface->can_get_text = tiff_document_can_get_text;
iface->get_n_pages = tiff_document_get_n_pages;
iface->get_page_size = tiff_document_get_page_size;
- iface->render_pixbuf = tiff_document_render_pixbuf;
+ iface->render = tiff_document_render;
iface->get_info = tiff_document_get_info;
}
+/*
+ * Copyright (c) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ * Copyright (C) 2000-2003 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
#include "ev-document-misc.h"
#include <string.h>
* NULL, then it will fill the return pixbuf with the contents of
* source_pixbuf.
*/
-
GdkPixbuf *
ev_document_misc_get_thumbnail_frame (int width,
int height,
border->right - border->left);
}
+
+cairo_surface_t *
+ev_document_misc_surface_from_pixbuf (GdkPixbuf *pixbuf)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+ cr = cairo_create (surface);
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ return surface;
+}
+
+cairo_surface_t *
+ev_document_misc_surface_rotate_and_scale (cairo_surface_t *surface,
+ gint dest_width,
+ gint dest_height,
+ gint dest_rotation)
+{
+ cairo_surface_t *new_surface;
+ cairo_t *cr;
+ gint width, height;
+ gint new_width = dest_width;
+ gint new_height = dest_height;
+
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_height (surface);
+
+ if (dest_width == width &&
+ dest_height == height &&
+ dest_rotation == 0) {
+ return cairo_surface_reference (surface);
+ }
+
+ if (dest_rotation == 90 || dest_rotation == 270) {
+ new_width = dest_height;
+ new_height = dest_width;
+ }
+
+ new_surface = cairo_surface_create_similar (surface,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ new_width, new_height);
+
+ cr = cairo_create (new_surface);
+ switch (dest_rotation) {
+ case 90:
+ cairo_translate (cr, new_width, 0);
+ break;
+ case 180:
+ cairo_translate (cr, new_width, new_height);
+ break;
+ case 270:
+ cairo_translate (cr, 0, new_height);
+ break;
+ default:
+ cairo_translate (cr, 0, 0);
+ }
+ cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_BILINEAR);
+ cairo_scale (cr,
+ (gdouble)dest_width / width,
+ (gdouble)dest_height / height);
+ cairo_rotate (cr, dest_rotation * G_PI / 180.0);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ return new_surface;
+}
+
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtkstyle.h>
+#include <cairo.h>
G_BEGIN_DECLS
GdkRectangle *area,
GtkBorder *border,
gboolean highlight);
+cairo_surface_t *ev_document_misc_surface_from_pixbuf (GdkPixbuf *pixbuf);
+cairo_surface_t *ev_document_misc_surface_rotate_and_scale (cairo_surface_t *surface,
+ gint dest_width,
+ gint dest_height,
+ gint dest_rotation);
G_END_DECLS
return retval;
}
-GdkPixbuf *
-ev_document_render_pixbuf (EvDocument *document,
- EvRenderContext *rc)
+cairo_surface_t *
+ev_document_render (EvDocument *document,
+ EvRenderContext *rc)
{
EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document);
- GdkPixbuf *retval;
+ cairo_surface_t *retval;
LOG ("ev_document_render_pixbuf");
- g_assert (iface->render_pixbuf);
+ g_assert (iface->render);
- retval = iface->render_pixbuf (document, rc);
+ retval = iface->render (document, rc);
return retval;
}
#include <glib-object.h>
#include <glib.h>
#include <gdk/gdk.h>
+#include <cairo.h>
#include "ev-link.h"
#include "ev-document-info.h"
G_BEGIN_DECLS
-#define EV_TYPE_DOCUMENT (ev_document_get_type ())
-#define EV_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT, EvDocument))
-#define EV_DOCUMENT_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT, EvDocumentIface))
-#define EV_IS_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EV_TYPE_DOCUMENT))
-#define EV_IS_DOCUMENT_IFACE(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_DOCUMENT))
+#define EV_TYPE_DOCUMENT (ev_document_get_type ())
+#define EV_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT, EvDocument))
+#define EV_DOCUMENT_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT, EvDocumentIface))
+#define EV_IS_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EV_TYPE_DOCUMENT))
+#define EV_IS_DOCUMENT_IFACE(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_DOCUMENT))
#define EV_DOCUMENT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), EV_TYPE_DOCUMENT, EvDocumentIface))
-typedef struct _EvDocument EvDocument;
+typedef struct _EvDocument EvDocument;
typedef struct _EvDocumentIface EvDocumentIface;
typedef struct _EvPageCache EvPageCache;
typedef struct _EvPageCacheClass EvPageCacheClass;
typedef enum
{
- EV_DOCUMENT_ERROR_INVALID,
- EV_DOCUMENT_ERROR_ENCRYPTED
+ EV_DOCUMENT_ERROR_INVALID,
+ EV_DOCUMENT_ERROR_ENCRYPTED
} EvDocumentError;
typedef struct {
- double x;
- double y;
+ double x;
+ double y;
} EvPoint;
typedef struct {
- double x1;
- double y1;
- double x2;
- double y2;
+ double x1;
+ double y1;
+ double x2;
+ double y2;
} EvRectangle;
struct _EvDocumentIface
{
- GTypeInterface base_iface;
-
- /* Methods */
- gboolean (* load) (EvDocument *document,
- const char *uri,
- GError **error);
- gboolean (* save) (EvDocument *document,
- const char *uri,
- GError **error);
- int (* get_n_pages) (EvDocument *document);
- void (* get_page_size) (EvDocument *document,
- int page,
- double *width,
- double *height);
- char * (* get_page_label) (EvDocument *document,
- int page);
- gboolean (* can_get_text) (EvDocument *document);
- char * (* get_text) (EvDocument *document,
- int page,
- EvRectangle *rect);
- gboolean (* has_attachments) (EvDocument *document);
- GList * (* get_attachments) (EvDocument *document);
- GdkPixbuf * (* render_pixbuf) (EvDocument *document,
- EvRenderContext *rc);
- EvDocumentInfo * (* get_info) (EvDocument *document);
+ GTypeInterface base_iface;
+
+ /* Methods */
+ gboolean (* load) (EvDocument *document,
+ const char *uri,
+ GError **error);
+ gboolean (* save) (EvDocument *document,
+ const char *uri,
+ GError **error);
+ int (* get_n_pages) (EvDocument *document);
+ void (* get_page_size) (EvDocument *document,
+ int page,
+ double *width,
+ double *height);
+ char * (* get_page_label) (EvDocument *document,
+ int page);
+ gboolean (* can_get_text) (EvDocument *document);
+ char * (* get_text) (EvDocument *document,
+ int page,
+ EvRectangle *rect);
+ gboolean (* has_attachments) (EvDocument *document);
+ GList * (* get_attachments) (EvDocument *document);
+ cairo_surface_t * (* render) (EvDocument *document,
+ EvRenderContext *rc);
+ EvDocumentInfo * (* get_info) (EvDocument *document);
};
-GType ev_document_get_type (void);
-GQuark ev_document_error_quark (void);
+GType ev_document_get_type (void) G_GNUC_CONST;
+GQuark ev_document_error_quark (void);
/* Document mutex */
-GMutex *ev_document_get_doc_mutex (void);
-void ev_document_doc_mutex_lock (void);
-void ev_document_doc_mutex_unlock (void);
+GMutex *ev_document_get_doc_mutex (void);
+void ev_document_doc_mutex_lock (void);
+void ev_document_doc_mutex_unlock (void);
/* FontConfig mutex */
-GMutex *ev_document_get_fc_mutex (void);
-void ev_document_fc_mutex_lock (void);
-void ev_document_fc_mutex_unlock (void);
-
-EvDocumentInfo *ev_document_get_info (EvDocument *document);
-gboolean ev_document_load (EvDocument *document,
- const char *uri,
- GError **error);
-gboolean ev_document_save (EvDocument *document,
- const char *uri,
- GError **error);
-int ev_document_get_n_pages (EvDocument *document);
-void ev_document_get_page_size (EvDocument *document,
- int page,
- double *width,
- double *height);
-char *ev_document_get_page_label (EvDocument *document,
- int page);
-gboolean ev_document_can_get_text (EvDocument *document);
-char *ev_document_get_text (EvDocument *document,
- int page,
- EvRectangle *rect);
-gboolean ev_document_has_attachments (EvDocument *document);
-GList *ev_document_get_attachments (EvDocument *document);
-GdkPixbuf *ev_document_render_pixbuf (EvDocument *document,
- EvRenderContext *rc);
-
-gint ev_rect_cmp (EvRectangle *a,
- EvRectangle *b);
+GMutex *ev_document_get_fc_mutex (void);
+void ev_document_fc_mutex_lock (void);
+void ev_document_fc_mutex_unlock (void);
+
+EvDocumentInfo *ev_document_get_info (EvDocument *document);
+gboolean ev_document_load (EvDocument *document,
+ const char *uri,
+ GError **error);
+gboolean ev_document_save (EvDocument *document,
+ const char *uri,
+ GError **error);
+int ev_document_get_n_pages (EvDocument *document);
+void ev_document_get_page_size (EvDocument *document,
+ int page,
+ double *width,
+ double *height);
+char *ev_document_get_page_label (EvDocument *document,
+ int page);
+gboolean ev_document_can_get_text (EvDocument *document);
+char *ev_document_get_text (EvDocument *document,
+ int page,
+ EvRectangle *rect);
+gboolean ev_document_has_attachments (EvDocument *document);
+GList *ev_document_get_attachments (EvDocument *document);
+cairo_surface_t *ev_document_render (EvDocument *document,
+ EvRenderContext *rc);
+
+gint ev_rect_cmp (EvRectangle *a,
+ EvRectangle *b);
G_END_DECLS
-#endif
+#endif /* EV_DOCUMENT_H */
void
ev_selection_render_selection (EvSelection *selection,
EvRenderContext *rc,
- GdkPixbuf **pixbuf,
+ cairo_surface_t **surface,
EvRectangle *points,
EvRectangle *old_points,
GdkColor *text,
EvSelectionIface *iface = EV_SELECTION_GET_IFACE (selection);
iface->render_selection (selection, rc,
- pixbuf,
+ surface,
points, old_points,
text, base);
}
void (* render_selection) (EvSelection *selection,
EvRenderContext *rc,
- GdkPixbuf **pixbuf,
+ cairo_surface_t **surface,
EvRectangle *points,
EvRectangle *old_points,
GdkColor *text,
GType ev_selection_get_type (void);
void ev_selection_render_selection (EvSelection *selection,
EvRenderContext *rc,
- GdkPixbuf **pixbuf,
+ cairo_surface_t **surface,
EvRectangle *points,
EvRectangle *old_points,
GdkColor *text,
#include "ev-document-links.h"
#include "ev-document-images.h"
#include "ev-document-factory.h"
+#include "ev-document-misc.h"
#include "ev-file-helpers.h"
#include "ev-document-fonts.h"
#include "ev-selection.h"
job = EV_JOB_RENDER (object);
- if (job->pixbuf) {
- g_object_unref (job->pixbuf);
- job->pixbuf = NULL;
+ if (job->surface) {
+ cairo_surface_destroy (job->surface);
+ job->surface = NULL;
}
if (job->rc) {
}
if (job->selection) {
- g_object_unref (job->selection);
+ cairo_surface_destroy (job->selection);
job->selection = NULL;
}
}
static void
-render_finished_cb (EvDocument *document, GdkPixbuf *pixbuf, EvJobRender *job)
+render_finished_cb (EvDocument *document,
+ GdkPixbuf *pixbuf,
+ EvJobRender *job)
{
g_signal_handlers_disconnect_by_func (EV_JOB (job)->document,
render_finished_cb, job);
+ /* FIXME: ps backend should be ported to cairo */
+ job->surface = ev_document_misc_surface_from_pixbuf (pixbuf);
EV_JOB (job)->finished = TRUE;
- job->pixbuf = g_object_ref (pixbuf);
ev_job_finished (EV_JOB (job));
}
} else {
ev_document_fc_mutex_lock ();
- job->pixbuf = ev_document_render_pixbuf (EV_JOB (job)->document, job->rc);
+ job->surface = ev_document_render (EV_JOB (job)->document, job->rc);
if (job->include_links && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document))
job->link_mapping =
ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document),
EvRenderContext *rc;
gint target_width;
gint target_height;
- GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
GList *link_mapping;
GdkRegion *text_mapping;
GList *image_mapping;
- GdkPixbuf *selection;
+ cairo_surface_t *selection;
GdkRegion *selection_region;
EvRectangle selection_points;
GdkColor base;
EvRenderContext *rc;
/* Data we get from rendering */
- GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
GList *link_mapping;
GList *image_mapping;
GdkRegion *text_mapping;
EvRectangle target_points;
gboolean points_set;
- GdkPixbuf *selection;
+ cairo_surface_t *selection;
GdkRegion *selection_region;
} CacheJobInfo;
static void copy_job_to_job_info (EvJobRender *job_render,
CacheJobInfo *job_info,
EvPixbufCache *pixbuf_cache);
-static gboolean new_selection_pixbuf_needed(EvPixbufCache *pixbuf_cache,
- CacheJobInfo *job_info,
- gint page,
- gfloat scale);
+static gboolean new_selection_surface_needed(EvPixbufCache *pixbuf_cache,
+ CacheJobInfo *job_info,
+ gint page,
+ gfloat scale);
/* These are used for iterating through the prev and next arrays */
g_object_unref (G_OBJECT (job_info->job));
job_info->job = NULL;
}
- if (job_info->pixbuf) {
- g_object_unref (G_OBJECT (job_info->pixbuf));
- job_info->pixbuf = NULL;
+ if (job_info->surface) {
+ cairo_surface_destroy (job_info->surface);
+ job_info->surface = NULL;
}
if (job_info->link_mapping) {
ev_link_mapping_free (job_info->link_mapping);
job_info->text_mapping = NULL;
}
if (job_info->selection) {
- g_object_unref (G_OBJECT (job_info->selection));
+ cairo_surface_destroy (job_info->selection);
job_info->selection = NULL;
}
if (job_info->selection_region) {
*target_page = *job_info;
job_info->job = NULL;
- job_info->pixbuf = NULL;
+ job_info->surface = NULL;
job_info->link_mapping = NULL;
job_info->image_mapping = NULL;
job_info->points_set = FALSE;
- if (job_info->pixbuf) {
- g_object_unref (G_OBJECT (job_info->pixbuf));
+ if (job_info->surface) {
+ cairo_surface_destroy (job_info->surface);
}
- job_info->pixbuf = g_object_ref (job_render->pixbuf);
+ job_info->surface = cairo_surface_reference (job_render->surface);
if (job_info->rc) {
g_object_unref (G_OBJECT (job_info->rc));
if (job_render->include_selection) {
if (job_info->selection) {
- g_object_unref (G_OBJECT (job_info->selection));
+ cairo_surface_destroy (job_info->selection);
job_info->selection = NULL;
}
if (job_info->selection_region) {
job_info->selection_points = job_render->selection_points;
job_info->selection_region = gdk_region_copy (job_render->selection_region);
- job_info->selection = g_object_ref (job_render->selection);
+ job_info->selection = cairo_surface_reference (job_render->selection);
g_assert (job_info->selection_points.x1 >= 0);
job_info->points_set = TRUE;
}
ev_page_cache_get_size (page_cache, page, rotation,
scale, &width, &height);
- if (job_info->pixbuf &&
- gdk_pixbuf_get_width (job_info->pixbuf) == width &&
- gdk_pixbuf_get_height (job_info->pixbuf) == height)
+ if (job_info->surface &&
+ cairo_image_surface_get_width (job_info->surface) == width &&
+ cairo_image_surface_get_height (job_info->surface) == height)
return;
/* make a new job now */
include_images = TRUE;
if (job_info->text_mapping == NULL)
include_text = TRUE;
- if (new_selection_pixbuf_needed (pixbuf_cache, job_info, page, scale)) {
+ if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
include_selection = TRUE;
}
ev_pixbuf_cache_add_jobs_if_needed (pixbuf_cache, rotation, scale);
}
-GdkPixbuf *
-ev_pixbuf_cache_get_pixbuf (EvPixbufCache *pixbuf_cache,
- gint page)
+cairo_surface_t *
+ev_pixbuf_cache_get_surface (EvPixbufCache *pixbuf_cache,
+ gint page)
{
CacheJobInfo *job_info;
copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache);
}
- return job_info->pixbuf;
+ return job_info->surface;
}
GList *
}
static gboolean
-new_selection_pixbuf_needed (EvPixbufCache *pixbuf_cache,
+new_selection_surface_needed (EvPixbufCache *pixbuf_cache,
CacheJobInfo *job_info,
gint page,
gfloat scale)
{
EvPageCache *page_cache;
- gint width, height;
if (job_info->selection) {
+ gint width, height;
+ gint selection_width, selection_height;
+
page_cache = ev_page_cache_get (pixbuf_cache->document);
- ev_page_cache_get_size (page_cache, page, job_info->rc->rotation,
+ ev_page_cache_get_size (page_cache, page,
+ job_info->rc->rotation,
scale, &width, &height);
+
+ selection_width = cairo_image_surface_get_width (job_info->selection);
+ selection_height = cairo_image_surface_get_height (job_info->selection);
- if (width != gdk_pixbuf_get_width (job_info->selection) ||
- height != gdk_pixbuf_get_height (job_info->selection))
+ if (width != selection_width || height != selection_height)
return TRUE;
} else {
if (job_info->points_set)
return TRUE;
}
+
return FALSE;
}
gint page,
gfloat scale)
{
- if (new_selection_pixbuf_needed (pixbuf_cache, job_info, page, scale)) {
+ if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
if (job_info->selection)
- g_object_unref (job_info->selection);
+ cairo_surface_destroy (job_info->selection);
job_info->selection = NULL;
job_info->selection_points.x1 = -1;
}
job_info = pixbuf_cache->prev_job + i;
if (job_info->selection) {
- g_object_unref (G_OBJECT (job_info->selection));
+ cairo_surface_destroy (job_info->selection);
job_info->selection = NULL;
}
job_info = pixbuf_cache->next_job + i;
if (job_info->selection) {
- g_object_unref (G_OBJECT (job_info->selection));
+ cairo_surface_destroy (job_info->selection);
job_info->selection = NULL;
}
}
job_info = pixbuf_cache->job_list + i;
if (job_info->selection) {
- g_object_unref (G_OBJECT (job_info->selection));
+ cairo_surface_destroy (job_info->selection);
job_info->selection = NULL;
}
}
}
-GdkPixbuf *
-ev_pixbuf_cache_get_selection_pixbuf (EvPixbufCache *pixbuf_cache,
- gint page,
- gfloat scale,
- GdkRegion **region)
+cairo_surface_t *
+ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
+ gint page,
+ gfloat scale,
+ GdkRegion **region)
{
CacheJobInfo *job_info;
job_info->selection_points.x1 = -1;
if (job_info->selection) {
- g_object_unref (job_info->selection);
+ cairo_surface_destroy (job_info->selection);
job_info->selection = NULL;
}
}
gint rotation,
gfloat scale,
GList *selection_list);
-GdkPixbuf *ev_pixbuf_cache_get_pixbuf (EvPixbufCache *pixbuf_cache,
+cairo_surface_t *ev_pixbuf_cache_get_surface (EvPixbufCache *pixbuf_cache,
gint page);
GList *ev_pixbuf_cache_get_link_mapping (EvPixbufCache *pixbuf_cache,
gint page);
void ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache);
/* Selection */
-GdkPixbuf *ev_pixbuf_cache_get_selection_pixbuf (EvPixbufCache *pixbuf_cache,
- gint page,
- gfloat scale,
- GdkRegion **region);
+cairo_surface_t *ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
+ gint page,
+ gfloat scale,
+ GdkRegion **region);
void ev_pixbuf_cache_set_selection_list (EvPixbufCache *pixbuf_cache,
GList *selection_list);
GList *ev_pixbuf_cache_get_selection_list (EvPixbufCache *pixbuf_cache);
view->selection_info.in_drag = TRUE;
} else {
clear_selection (view);
+
+ view->selection_info.start.x = event->x + view->scroll_x;
+ view->selection_info.start.y = event->y + view->scroll_y;
}
gtk_widget_queue_draw (widget);
view->image_dnd_info.start.x = event->x + view->scroll_x;
view->image_dnd_info.start.y = event->y + view->scroll_y;
+ } else {
+ view->selection_info.start.x = event->x + view->scroll_x;
+ view->selection_info.start.y = event->y + view->scroll_y;
}
-
- view->selection_info.start.x = event->x + view->scroll_x;
- view->selection_info.start.y = event->y + view->scroll_y;
}
return TRUE;
case 2:
EvDocumentFind *find;
int i, results = 0;
- g_return_if_fail (EV_IS_DOCUMENT_FIND (view->document));
-
find = EV_DOCUMENT_FIND (view->document);
results = ev_document_find_get_n_results (find, page);
{
cairo_t *cr;
gint width, height;
-
+
/* Don't annoy users with loading messages during presentations.
* FIXME: Temporary "workaround" for
* http://bugzilla.gnome.org/show_bug.cgi?id=320352 */
return;
if (!view->loading_text) {
- const gchar *loading_text;
+ const gchar *loading_text = _("Loading...");
PangoLayout *layout;
PangoFontDescription *font_desc;
PangoRectangle logical_rect;
- gdouble real_scale;
gint target_width;
-
- loading_text = _("Loading...");
+ gdouble real_scale;
ev_document_fc_mutex_lock ();
-
+
layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), loading_text);
font_desc = pango_font_description_new ();
pango_font_description_set_size (font_desc, 10 * PANGO_SCALE);
pango_layout_set_font_description (layout, font_desc);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-
- /* Make sure we fit the middle of the page */
+
target_width = MAX (page_area->width / 2, 1);
real_scale = ((double)target_width / (double) logical_rect.width) * (PANGO_SCALE * 10);
pango_font_description_set_size (font_desc, (int)real_scale);
height = (page_area->height - cairo_image_surface_get_height (view->loading_text)) / 2;
cr = gdk_cairo_create (GTK_WIDGET (view)->window);
- cairo_set_source_surface (cr, view->loading_text,
- page_area->x + width,
- page_area->y + height);
+ cairo_translate (cr,
+ page_area->x + width,
+ page_area->y + height);
+ cairo_set_source_surface (cr, view->loading_text, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
}
static void
-draw_one_page (EvView *view,
- gint page,
- GdkRectangle *page_area,
- GtkBorder *border,
- GdkRectangle *expose_area,
- gboolean *page_ready)
+draw_one_page (EvView *view,
+ gint page,
+ GdkRectangle *page_area,
+ GtkBorder *border,
+ GdkRectangle *expose_area,
+ gboolean *page_ready)
{
- gint width, height;
- GdkPixbuf *current_pixbuf;
GdkRectangle overlap;
GdkRectangle real_page_area;
- EvViewSelection *selection;
- gint current_page;
g_assert (view->document);
if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
return;
-
- current_page = ev_page_cache_get_current_page (view->page_cache);
- selection = find_selection_for_page (view, page);
- ev_page_cache_get_size (view->page_cache,
- page, view->rotation,
- view->scale,
- &width, &height);
+
/* Render the document itself */
real_page_area = *page_area;
*page_ready = TRUE;
if (!view->presentation) {
- ev_document_misc_paint_one_page (GTK_WIDGET(view)->window,
+ gint current_page;
+
+ current_page = ev_page_cache_get_current_page (view->page_cache);
+ ev_document_misc_paint_one_page (GTK_WIDGET (view)->window,
GTK_WIDGET (view),
page_area, border,
page == current_page);
}
if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) {
- GdkPixbuf *selection_pixbuf = NULL;
- GdkPixbuf *scaled_image;
- GdkPixbuf *scaled_selection;
+ gint width, height;
+ gint page_width, page_height;
+ cairo_surface_t *page_surface = NULL;
+ gint selection_width, selection_height;
+ cairo_surface_t *selection_surface = NULL;
+ cairo_t *cr = NULL;
- current_pixbuf = ev_pixbuf_cache_get_pixbuf (view->pixbuf_cache, page);
+ page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
- /* Get the selection pixbuf iff we have something to draw */
- if (current_pixbuf && view->selection_mode == EV_VIEW_SELECTION_TEXT && selection)
- selection_pixbuf = ev_pixbuf_cache_get_selection_pixbuf (view->pixbuf_cache,
- page,
- view->scale,
- NULL);
-
- if (current_pixbuf == NULL)
- scaled_image = NULL;
- else if (width == gdk_pixbuf_get_width (current_pixbuf) &&
- height == gdk_pixbuf_get_height (current_pixbuf))
- scaled_image = g_object_ref (current_pixbuf);
- else
- /* FIXME: We don't want to scale the whole area, just the right
- * area of it */
- scaled_image = gdk_pixbuf_scale_simple (current_pixbuf,
- width, height,
- GDK_INTERP_NEAREST);
-
- if (selection_pixbuf == NULL)
- scaled_selection = NULL;
- else if (width == gdk_pixbuf_get_width (selection_pixbuf) &&
- height == gdk_pixbuf_get_height (selection_pixbuf))
- scaled_selection = g_object_ref (selection_pixbuf);
- else
- /* FIXME: We don't want to scale the whole area, just the right
- * area of it */
- scaled_selection = gdk_pixbuf_scale_simple (selection_pixbuf,
- width, height,
- GDK_INTERP_NEAREST);
-
- if (scaled_image) {
- gdk_draw_pixbuf (GTK_WIDGET(view)->window,
- GTK_WIDGET (view)->style->fg_gc[GTK_STATE_NORMAL],
- scaled_image,
- overlap.x - real_page_area.x,
- overlap.y - real_page_area.y,
- overlap.x, overlap.y,
- overlap.width, overlap.height,
- GDK_RGB_DITHER_NORMAL,
- 0, 0);
- g_object_unref (scaled_image);
- } else {
+ if (!page_surface) {
draw_loading_text (view,
&real_page_area,
expose_area);
*page_ready = FALSE;
+
+ return;
+ }
+
+ ev_page_cache_get_size (view->page_cache,
+ page, view->rotation,
+ view->scale,
+ &width, &height);
+
+ cr = gdk_cairo_create (GTK_WIDGET (view)->window);
+
+ cairo_save (cr);
+
+ page_width = cairo_image_surface_get_width (page_surface);
+ page_height = cairo_image_surface_get_height (page_surface);
+
+ cairo_translate (cr, overlap.x, overlap.y);
+
+ if (width != page_width || height != page_height) {
+ cairo_pattern_set_filter (cairo_get_source (cr),
+ CAIRO_FILTER_FAST);
+ cairo_scale (cr,
+ (gdouble)width / page_width,
+ (gdouble)height / page_height);
}
- if (scaled_selection) {
- gdk_draw_pixbuf (GTK_WIDGET(view)->window,
- GTK_WIDGET (view)->style->fg_gc[GTK_STATE_NORMAL],
- scaled_selection,
- overlap.x - real_page_area.x,
- overlap.y - real_page_area.y,
- overlap.x, overlap.y,
- overlap.width, overlap.height,
- GDK_RGB_DITHER_NORMAL,
- 0, 0);
- g_object_unref (scaled_selection);
+ cairo_surface_set_device_offset (page_surface,
+ overlap.x - real_page_area.x,
+ overlap.y - real_page_area.y);
+
+ cairo_set_source_surface (cr, page_surface, 0, 0);
+ cairo_paint (cr);
+
+ cairo_restore (cr);
+
+ /* Get the selection pixbuf iff we have something to draw */
+ if (find_selection_for_page (view, page) &&
+ view->selection_mode == EV_VIEW_SELECTION_TEXT) {
+ selection_surface =
+ ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
+ page,
+ view->scale,
+ NULL);
+ }
+
+ if (!selection_surface) {
+ cairo_destroy (cr);
+ return;
}
+
+ selection_width = cairo_image_surface_get_width (selection_surface);
+ selection_height = cairo_image_surface_get_height (selection_surface);
+
+ cairo_translate (cr, overlap.x, overlap.y);
+
+ if (width != selection_width || height != selection_height) {
+ cairo_pattern_set_filter (cairo_get_source (cr),
+ CAIRO_FILTER_FAST);
+ cairo_scale (cr,
+ (gdouble)width / selection_width,
+ (gdouble)height / selection_height);
+ }
+
+ cairo_surface_set_device_offset (selection_surface,
+ overlap.x - real_page_area.x,
+ overlap.y - real_page_area.y);
+
+ cairo_set_source_surface (cr, selection_surface, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
}
}
cairo_surface_destroy (view->loading_text);
view->loading_text = NULL;
}
-
+
view->scale = scale;
view->pending_resize = TRUE;
}
-
-
/* Now create a list of EvViewSelection's for the affected
* pages. This could be an empty list, a list of just one
* page or a number of pages.*/
* region too. */
if (new_sel) {
GdkRegion *tmp_region = NULL;
- ev_pixbuf_cache_get_selection_pixbuf (view->pixbuf_cache,
- cur_page,
- view->scale,
- &tmp_region);
+
+ ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
+ cur_page,
+ view->scale,
+ &tmp_region);
+
if (tmp_region) {
new_sel->covered_region = gdk_region_copy (tmp_region);
}
/* Now we figure out what needs redrawing */
if (old_sel && new_sel) {
- if (old_sel->covered_region &&
- new_sel->covered_region) {
+ if (old_sel->covered_region && new_sel->covered_region) {
/* We only want to redraw the areas that have
* changed, so we xor the old and new regions
* and redraw if it's different */
GdkRectangle page_area;
GtkBorder border;
+ /* I don't know why but the region is smaller
+ * than expected. This hack fixes it, I guess
+ * 10 pixels more won't hurt
+ */
+ gdk_region_shrink (region, -5, -5);
+
get_page_extents (view, cur_page, &page_area, &border);
gdk_region_offset (region,
page_area.x + border.left - view->scroll_x,