]> www.fi.muni.cz Git - evince.git/blobdiff - backend/tiff/tiff-document.c
2007-07-03 Jovan Naumovski <jovanna@svn.gnome.org> *mk.po: Updated Macedonian transla...
[evince.git] / backend / tiff / tiff-document.c
index 9348ed4efb68e893fe6cb03b707970ca1269da8d..8247c2a269b9751bc222f07c7447f4d7ab4d05e8 100644 (file)
@@ -149,6 +149,28 @@ tiff_document_get_n_pages (EvDocument  *document)
        return tiff_document->n_pages;
 }
 
+static void
+tiff_document_get_resolution (TiffDocument *tiff_document,
+                             gfloat       *x_res,
+                             gfloat       *y_res)
+{
+       gfloat x = 72.0, y = 72.0;
+       gushort unit;
+       
+       if (TIFFGetField (tiff_document->tiff, TIFFTAG_XRESOLUTION, &x) &&
+           TIFFGetField (tiff_document->tiff, TIFFTAG_YRESOLUTION, &y)) {
+               if (TIFFGetFieldDefaulted (tiff_document->tiff, TIFFTAG_RESOLUTIONUNIT, &unit)) {
+                       if (unit == RESUNIT_CENTIMETER) {
+                               x *= 2.54;
+                               y *= 2.54;
+                       }
+               }
+       }
+
+       *x_res = x;
+       *y_res = y;
+}
+
 static void
 tiff_document_get_page_size (EvDocument   *document,
                             int           page,
@@ -170,8 +192,7 @@ tiff_document_get_page_size (EvDocument   *document,
        
        TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &w);
        TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &h);
-       TIFFGetField (tiff_document->tiff, TIFFTAG_XRESOLUTION, &x_res);
-       TIFFGetField (tiff_document->tiff, TIFFTAG_YRESOLUTION, &y_res);
+       tiff_document_get_resolution (tiff_document, &x_res, &y_res);
        h = h * (x_res / y_res);
        
        *width = w;
@@ -180,9 +201,9 @@ tiff_document_get_page_size (EvDocument   *document,
        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;
@@ -192,6 +213,9 @@ tiff_document_render_pixbuf (EvDocument      *document,
        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);
@@ -212,22 +236,87 @@ tiff_document_render_pixbuf (EvDocument      *document,
                return NULL;
        }
 
-       if (!TIFFGetField (tiff_document->tiff, TIFFTAG_XRESOLUTION, &x_res)) {
+       tiff_document_get_resolution (tiff_document, &x_res, &y_res);
+       
+       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_YRESOLUTION, &y_res)) {
+       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;                
-        
+
        rowstride = width * 4;
        if (rowstride / 4 != width)
                /* overflow */
@@ -245,14 +334,15 @@ tiff_document_render_pixbuf (EvDocument      *document,
        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), ORIENTATION_TOPLEFT, 1);
+       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),
+                                                height * rc->scale * (x_res / y_res),
                                                 GDK_INTERP_BILINEAR);
        g_object_unref (pixbuf);
        
@@ -308,7 +398,7 @@ tiff_document_document_iface_init (EvDocumentIface *iface)
        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;
 }