]> www.fi.muni.cz Git - evince.git/blobdiff - backend/tiff/tiff-document.c
tiff: Set stopOnError to zero on TIFFReadRGBAImageOriented() calls
[evince.git] / backend / tiff / tiff-document.c
index 24af05fbc887705fee05f28162bb30d5c42cf087..ca40397111d18c8b18a52e294b27a2ca8fb8e28c 100644 (file)
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 /* FIXME: Should probably buffer calls to libtiff with TIFFSetWarningHandler
  */
 
+#include "config.h"
+
+#include <config.h>
 #include <stdio.h>
 #include <glib.h>
+#include <glib/gi18n-lib.h>
 
 #include "tiffio.h"
 #include "tiff2ps.h"
 #include "tiff-document.h"
 #include "ev-document-misc.h"
-#include "ev-document-thumbnails.h"
 #include "ev-file-exporter.h"
+#include "ev-file-helpers.h"
 
 struct _TiffDocumentClass
 {
-  GObjectClass parent_class;
+  EvDocumentClass parent_class;
 };
 
 struct _TiffDocument
 {
-  GObject parent_instance;
+  EvDocument parent_instance;
 
   TIFF *tiff;
   gint n_pages;
@@ -48,17 +52,12 @@ struct _TiffDocument
 
 typedef struct _TiffDocumentClass TiffDocumentClass;
 
-static void tiff_document_document_iface_init (EvDocumentIface *iface);
-static void tiff_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
-static void tiff_document_document_file_exporter_iface_init (EvFileExporterIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (TiffDocument, tiff_document, G_TYPE_OBJECT,
-                         { G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
-                                                 tiff_document_document_iface_init);
-                          G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
-                                                 tiff_document_document_thumbnails_iface_init);
-                          G_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
-                                                 tiff_document_document_file_exporter_iface_init);
+static void tiff_document_document_file_exporter_iface_init (EvFileExporterInterface *iface);
+
+EV_BACKEND_REGISTER_WITH_CODE (TiffDocument, tiff_document,
+                        {
+                          EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
+                                                          tiff_document_document_file_exporter_iface_init);
                         });
 
 static TIFFErrorHandler orig_error_handler = NULL;
@@ -67,15 +66,15 @@ static TIFFErrorHandler orig_warning_handler = NULL;
 static void
 push_handlers (void)
 {
-  orig_error_handler = TIFFSetErrorHandler (NULL);
-  orig_warning_handler = TIFFSetWarningHandler (NULL);
+       orig_error_handler = TIFFSetErrorHandler (NULL);
+       orig_warning_handler = TIFFSetWarningHandler (NULL);
 }
 
 static void
 pop_handlers (void)
 {
-  TIFFSetErrorHandler (orig_error_handler);
-  TIFFSetWarningHandler (orig_warning_handler);
+       TIFFSetErrorHandler (orig_error_handler);
+       TIFFSetWarningHandler (orig_warning_handler);
 }
 
 static gboolean
@@ -83,44 +82,63 @@ tiff_document_load (EvDocument  *document,
                    const char  *uri,
                    GError     **error)
 {
-  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
-  gchar *filename;
-  TIFF *tiff;
+       TiffDocument *tiff_document = TIFF_DOCUMENT (document);
+       gchar *filename;
+       TIFF *tiff;
+       
+       filename = g_filename_from_uri (uri, NULL, error);
+       if (!filename)
+               return FALSE;
+       
+       push_handlers ();
+
+#ifdef G_OS_WIN32
+{
+       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, error);
+       if (wfilename == NULL) {
+               return FALSE;
+       }
 
-  push_handlers ();
-  filename = g_filename_from_uri (uri, NULL, error);
-  if (!filename)
-    {
-      pop_handlers ();
-      return FALSE;
-    }
-
-  tiff = TIFFOpen (filename, "r");
-  if (tiff)
-    {
-      guint32 w, h;
-      /* FIXME: unused data? why bother here */
-      TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
-      TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
-    }
-  if (!tiff)
-    {
-      pop_handlers ();
-      return FALSE;
-    }
-  tiff_document->tiff = tiff;
-  g_free (tiff_document->uri);
-  g_free (filename);
-  tiff_document->uri = g_strdup (uri);
-
-  pop_handlers ();
-  return TRUE;
+       tiff = TIFFOpenW (wfilename, "r");
+
+       g_free (wfilename);
+}
+#else
+       tiff = TIFFOpen (filename, "r");
+#endif
+       if (tiff) {
+               guint32 w, h;
+               
+               /* FIXME: unused data? why bother here */
+               TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
+               TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
+       }
+       
+       if (!tiff) {
+               pop_handlers ();
+
+               g_set_error_literal (error,
+                                    EV_DOCUMENT_ERROR,
+                                    EV_DOCUMENT_ERROR_INVALID,
+                                    _("Invalid document"));
+
+               g_free (filename);
+               return FALSE;
+       }
+       
+       tiff_document->tiff = tiff;
+       g_free (tiff_document->uri);
+       g_free (filename);
+       tiff_document->uri = g_strdup (uri);
+       
+       pop_handlers ();
+       return TRUE;
 }
 
 static gboolean
 tiff_document_save (EvDocument  *document,
-                     const char  *uri,
-                     GError     **error)
+                   const char  *uri,
+                   GError     **error)
 {              
        TiffDocument *tiff_document = TIFF_DOCUMENT (document);
 
@@ -130,143 +148,264 @@ tiff_document_save (EvDocument  *document,
 static int
 tiff_document_get_n_pages (EvDocument  *document)
 {
-  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
-
-  g_return_val_if_fail (TIFF_IS_DOCUMENT (document), 0);
-  g_return_val_if_fail (tiff_document->tiff != NULL, 0);
-
-  if (tiff_document->n_pages == -1)
-    {
-      push_handlers ();
-      tiff_document->n_pages = 0;
-      do
-       {
-         tiff_document->n_pages ++;
+       TiffDocument *tiff_document = TIFF_DOCUMENT (document);
+       
+       g_return_val_if_fail (TIFF_IS_DOCUMENT (document), 0);
+       g_return_val_if_fail (tiff_document->tiff != NULL, 0);
+       
+       if (tiff_document->n_pages == -1) {
+               push_handlers ();
+               tiff_document->n_pages = 0;
+               
+               do {
+                       tiff_document->n_pages ++;
+               }
+               while (TIFFReadDirectory (tiff_document->tiff));
+               pop_handlers ();
+       }
+
+       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;
+                       }
+               }
        }
-      while (TIFFReadDirectory (tiff_document->tiff));
-      pop_handlers ();
-    }
 
-  return tiff_document->n_pages;
+       *x_res = x;
+       *y_res = y;
 }
 
 static void
-tiff_document_get_page_size (EvDocument   *document,
-                            int           page,
-                            double       *width,
-                            double       *height)
+tiff_document_get_page_size (EvDocument *document,
+                            EvPage     *page,
+                            double     *width,
+                            double     *height)
 {
-  guint32 w, h;
-  gfloat x_res, y_res;
-  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
-
-  g_return_if_fail (TIFF_IS_DOCUMENT (document));
-  g_return_if_fail (tiff_document->tiff != NULL);
-
-  push_handlers ();
-  if (TIFFSetDirectory (tiff_document->tiff, page) != 1)
-    {
-      pop_handlers ();
-      return;
-    }
-
-  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);
-  h = h * (x_res / y_res);
-
-  *width = w;
-  *height = h;
-
-  pop_handlers ();
+       guint32 w, h;
+       gfloat x_res, y_res;
+       TiffDocument *tiff_document = TIFF_DOCUMENT (document);
+       
+       g_return_if_fail (TIFF_IS_DOCUMENT (document));
+       g_return_if_fail (tiff_document->tiff != NULL);
+       
+       push_handlers ();
+       if (TIFFSetDirectory (tiff_document->tiff, page->index) != 1) {
+               pop_handlers ();
+               return;
+       }
+       
+       TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &w);
+       TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &h);
+       tiff_document_get_resolution (tiff_document, &x_res, &y_res);
+       h = h * (x_res / y_res);
+       
+       *width = w;
+       *height = h;
+       
+       pop_handlers ();
+}
+
+static cairo_surface_t *
+tiff_document_render (EvDocument      *document,
+                     EvRenderContext *rc)
+{
+       TiffDocument *tiff_document = TIFF_DOCUMENT (document);
+       int width, height;
+       float x_res, y_res;
+       gint rowstride, bytes;
+       guchar *pixels = NULL;
+       guchar *p;
+       int orientation;
+       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);
+  
+       push_handlers ();
+       if (TIFFSetDirectory (tiff_document->tiff, rc->page->index) != 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;
+       }
+
+       if (! TIFFGetField (tiff_document->tiff, TIFFTAG_ORIENTATION, &orientation)) {
+               orientation = ORIENTATION_TOPLEFT;
+       }
+
+       tiff_document_get_resolution (tiff_document, &x_res, &y_res);
+       
+       pop_handlers ();
+  
+       /* Sanity check the doc */
+       if (width <= 0 || height <= 0)
+               return NULL;                
+
+#ifdef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH
+       rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, width);
+#else
+       rowstride = width * 4;
+#endif
+       if (rowstride / 4 != width)
+               /* overflow, or cairo was changed in an unsupported way */
+               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_RGB24,
+                                                      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, 0);
+       pop_handlers ();
+
+       /* Convert the format returned by libtiff to
+       * what cairo expects
+       */
+       p = pixels;
+       while (p < pixels + bytes) {
+               guint32 *pixel = (guint32*)p;
+               guint8 r = TIFFGetR(*pixel);
+               guint8 g = TIFFGetG(*pixel);
+               guint8 b = TIFFGetB(*pixel);
+               guint8 a = TIFFGetA(*pixel);
+
+               *pixel = (a << 24) | (r << 16) | (g << 8) | b;
+
+               p += 4;
+       }
+
+       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,
+tiff_document_get_thumbnail (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;
-
-  g_return_val_if_fail (TIFF_IS_DOCUMENT (document), 0);
-  g_return_val_if_fail (tiff_document->tiff != NULL, 0);
-
-  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;
-    }
-
-  if (!TIFFGetField (tiff_document->tiff, TIFFTAG_XRESOLUTION, &x_res))
-    {
-      pop_handlers ();
-      return NULL;
-    }
-
-  if (! TIFFGetField (tiff_document->tiff, TIFFTAG_YRESOLUTION, &y_res))
-    {
-      pop_handlers ();
-      return 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;                
+       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->index) != 1) {
+               pop_handlers ();
+               return NULL;
+       }
 
-  pixels = g_try_malloc (bytes);
-  if (!pixels)
-    return NULL;
+       if (!TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &width)) {
+               pop_handlers ();
+               return NULL;
+       }
 
-  pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, 
-                                    width, height, rowstride,
-                                    (GdkPixbufDestroyNotify) g_free, NULL);
+       if (! TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &height)) {
+               pop_handlers ();
+               return 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);
-  pop_handlers ();
+       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;
+       
+       pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, 
+                                          width, height, rowstride,
+                                          (GdkPixbufDestroyNotify) g_free, NULL);
+       TIFFReadRGBAImageOriented (tiff_document->tiff,
+                                  width, height,
+                                  (uint32 *)pixels,
+                                  ORIENTATION_TOPLEFT, 0);
+       pop_handlers ();
+
+       scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
+                                                width * rc->scale,
+                                                height * rc->scale * (x_res / y_res),
+                                                GDK_INTERP_BILINEAR);
+       g_object_unref (pixbuf);
+       
+       rotated_pixbuf = gdk_pixbuf_rotate_simple (scaled_pixbuf, 360 - rc->rotation);
+       g_object_unref (scaled_pixbuf);
+       
+       return rotated_pixbuf;
+}
 
-  scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
-                                          width * rc->scale,
-                                          height * rc->scale * (x_res/y_res),
-                                          GDK_INTERP_BILINEAR);
-  g_object_unref (pixbuf);
+static gchar *
+tiff_document_get_page_label (EvDocument *document,
+                             EvPage     *page)
+{
+       TiffDocument *tiff_document = TIFF_DOCUMENT (document);
+       static gchar *label;
 
-  rotated_pixbuf = gdk_pixbuf_rotate_simple (scaled_pixbuf, 360 - rc->rotation);
-  g_object_unref (scaled_pixbuf);
+       if (TIFFGetField (tiff_document->tiff, TIFFTAG_PAGENAME, &label) &&
+           g_utf8_validate (label, -1, NULL)) {
+               return g_strdup (label);
+       }
 
-  return rotated_pixbuf;
+       return NULL;
 }
 
 static void
@@ -285,117 +424,28 @@ tiff_document_finalize (GObject *object)
 static void
 tiff_document_class_init (TiffDocumentClass *klass)
 {
-       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+       GObjectClass    *gobject_class = G_OBJECT_CLASS (klass);
+       EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
 
        gobject_class->finalize = tiff_document_finalize;
-}
-
-static gboolean
-tiff_document_can_get_text (EvDocument *document)
-{
-       return FALSE;
-}
-
-static EvDocumentInfo *
-tiff_document_get_info (EvDocument *document)
-{
-       EvDocumentInfo *info;
-
-       info = g_new0 (EvDocumentInfo, 1);
-       info->fields_mask = 0;
-
-       return info;
-}
-
-static void
-tiff_document_document_iface_init (EvDocumentIface *iface)
-{
-       iface->load = tiff_document_load;
-       iface->save = tiff_document_save;
-       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->get_info = tiff_document_get_info;
-}
 
-static GdkPixbuf *
-tiff_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
-                                       gint                  page,
-                                       gint                  rotation,
-                                       gint                  size,
-                                       gboolean              border)
-{
-  EvRenderContext *rc;
-  GdkPixbuf *pixbuf;
-  gdouble w, h;
-
-  tiff_document_get_page_size (EV_DOCUMENT (document),
-                              page,
-                              &w, &h);
-
-  rc = ev_render_context_new (rotation, page, size/w);
-  pixbuf = tiff_document_render_pixbuf (EV_DOCUMENT (document), rc);
-  g_object_unref (G_OBJECT (rc));
-
-  if (border)
-    {
-      GdkPixbuf *tmp_pixbuf = pixbuf;
-      pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, 0, tmp_pixbuf);
-      g_object_unref (tmp_pixbuf);
-    }
-
-  return pixbuf;
-}
-
-static void
-tiff_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
-                                        gint                  page,
-                                        gint                  suggested_width,
-                                        gint                 *width,
-                                        gint                 *height)
-{
-  gdouble page_ratio;
-  gdouble w, h;
-
-  tiff_document_get_page_size (EV_DOCUMENT (document),
-                              page,
-                              &w, &h);
-  g_return_if_fail (w > 0);
-  page_ratio = h/w;
-  *width = suggested_width;
-  *height = (gint) (suggested_width * page_ratio);
-}
-
-static void
-tiff_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
-{
-  iface->get_thumbnail = tiff_document_thumbnails_get_thumbnail;
-  iface->get_dimensions = tiff_document_thumbnails_get_dimensions;
+       ev_document_class->load = tiff_document_load;
+       ev_document_class->save = tiff_document_save;
+       ev_document_class->get_n_pages = tiff_document_get_n_pages;
+       ev_document_class->get_page_size = tiff_document_get_page_size;
+       ev_document_class->render = tiff_document_render;
+       ev_document_class->get_thumbnail = tiff_document_get_thumbnail;
+       ev_document_class->get_page_label = tiff_document_get_page_label;
 }
 
 /* postscript exporter implementation */
-
-static gboolean
-tiff_document_file_exporter_format_supported (EvFileExporter      *exporter,
-                                             EvFileExporterFormat format)
-{
-       return (format == EV_FILE_FORMAT_PS);
-}
-
 static void
-tiff_document_file_exporter_begin (EvFileExporter      *exporter,
-                                  EvFileExporterFormat format,
-                                  const char          *filename,
-                                  int                  first_page,
-                                  int                  last_page,
-                                  double               width,
-                                  double               height,
-                                  gboolean             duplex)
+tiff_document_file_exporter_begin (EvFileExporter        *exporter,
+                                  EvFileExporterContext *fc)
 {
        TiffDocument *document = TIFF_DOCUMENT (exporter);
 
-       document->ps_export_ctx = tiff2ps_context_new(filename);
+       document->ps_export_ctx = tiff2ps_context_new(fc->filename);
 }
 
 static void
@@ -405,7 +455,7 @@ tiff_document_file_exporter_do_page (EvFileExporter *exporter, EvRenderContext *
 
        if (document->ps_export_ctx == NULL)
                return;
-       if (TIFFSetDirectory (document->tiff, rc->page) != 1)
+       if (TIFFSetDirectory (document->tiff, rc->page->index) != 1)
                return;
        tiff2ps_process_page (document->ps_export_ctx, document->tiff,
                              0, 0, 0, 0, 0);
@@ -421,17 +471,27 @@ tiff_document_file_exporter_end (EvFileExporter *exporter)
        tiff2ps_context_finalize(document->ps_export_ctx);
 }
 
+static EvFileExporterCapabilities
+tiff_document_file_exporter_get_capabilities (EvFileExporter *exporter)
+{
+       return  EV_FILE_EXPORTER_CAN_PAGE_SET |
+               EV_FILE_EXPORTER_CAN_COPIES |
+               EV_FILE_EXPORTER_CAN_COLLATE |
+               EV_FILE_EXPORTER_CAN_REVERSE |
+               EV_FILE_EXPORTER_CAN_GENERATE_PS;
+}
+
 static void
-tiff_document_document_file_exporter_iface_init (EvFileExporterIface *iface)
+tiff_document_document_file_exporter_iface_init (EvFileExporterInterface *iface)
 {
-       iface->format_supported = tiff_document_file_exporter_format_supported;
        iface->begin = tiff_document_file_exporter_begin;
        iface->do_page = tiff_document_file_exporter_do_page;
        iface->end = tiff_document_file_exporter_end;
+       iface->get_capabilities = tiff_document_file_exporter_get_capabilities;
 }
 
 static void
 tiff_document_init (TiffDocument *tiff_document)
 {
-  tiff_document->n_pages = -1;
+       tiff_document->n_pages = -1;
 }