X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=libdocument%2Fev-document-misc.c;h=889e4a88d0a08e51e1d3c2b92530ea1469bbb3df;hb=accc8f4a998adead7dbb923d7e453bdbd22c0e00;hp=fd6f4493904059138f8fa14e28f86b7f8ab1adbf;hpb=13a06349251874bd35d2f03c3fc93217cee749a2;p=evince.git diff --git a/libdocument/ev-document-misc.c b/libdocument/ev-document-misc.c index fd6f4493..889e4a88 100644 --- a/libdocument/ev-document-misc.c +++ b/libdocument/ev-document-misc.c @@ -1,18 +1,38 @@ +/* + * Copyright (c) 2007 Carlos Garcia Campos + * 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 -#include "ev-document-misc.h" #include + #include +#include "ev-document-misc.h" + /* Returns a new GdkPixbuf that is suitable for placing in the thumbnail view. * It is four pixels wider and taller than the source. If source_pixbuf is not * 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, - int rotation, GdkPixbuf *source_pixbuf) { GdkPixbuf *retval; @@ -21,9 +41,6 @@ ev_document_misc_get_thumbnail_frame (int width, int i; int width_r, height_r; - rotation = rotation % 360; - - if (source_pixbuf) g_return_val_if_fail (GDK_IS_PIXBUF (source_pixbuf), NULL); @@ -31,15 +48,8 @@ ev_document_misc_get_thumbnail_frame (int width, width_r = gdk_pixbuf_get_width (source_pixbuf); height_r = gdk_pixbuf_get_height (source_pixbuf); } else { - if (rotation == 0 || rotation == 180) { - width_r = width; - height_r = height; - } else if (rotation == 90 || rotation == 270) { - width_r = height; - height_r = width; - } else { - g_assert_not_reached (); - } + width_r = width; + height_r = height; } /* make sure no one is passing us garbage */ @@ -139,3 +149,149 @@ ev_document_misc_paint_one_page (GdkDrawable *drawable, 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 (gdk_pixbuf_get_has_alpha (pixbuf) ? + CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, + 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; +} + +GdkPixbuf * +ev_document_misc_pixbuf_from_surface (cairo_surface_t *surface) +{ + GdkPixbuf *pixbuf; + cairo_surface_t *image; + cairo_t *cr; + gboolean has_alpha; + gint width, height; + cairo_format_t surface_format; + gint pixbuf_n_channels; + gint pixbuf_rowstride; + guchar *pixbuf_pixels; + gint x, y; + + width = cairo_image_surface_get_width (surface); + height = cairo_image_surface_get_height (surface); + + surface_format = cairo_image_surface_get_format (surface); + has_alpha = (surface_format == CAIRO_FORMAT_ARGB32); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, 8, + width, height); + pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf); + pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf); + + image = cairo_image_surface_create_for_data (pixbuf_pixels, + surface_format, + width, height, + pixbuf_rowstride); + cr = cairo_create (image); + cairo_set_source_surface (cr, surface, 0, 0); + + if (has_alpha) + cairo_mask_surface (cr, surface, 0, 0); + else + cairo_paint (cr); + + cairo_destroy (cr); + cairo_surface_destroy (image); + + for (y = 0; y < height; y++) { + guchar *p = pixbuf_pixels + y * pixbuf_rowstride; + + for (x = 0; x < width; x++) { + guchar tmp; + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + tmp = p[0]; + p[0] = p[2]; + p[2] = tmp; + p[3] = (has_alpha) ? p[3] : 0xff; +#else + tmp = p[0]; + p[0] = p[1]; + p[1] = p[2]; + p[2] = p[3]; + p[3] = (has_alpha) ? tmp : 0xff; +#endif + p += pixbuf_n_channels; + } + } + + return pixbuf; +} + +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_surface_get_content (surface), + 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); + } + + if (dest_width != width || dest_height != height) { + 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; +} +