Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tiff-document.c File Reference
#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-file-exporter.h"
#include "ev-file-helpers.h"
+ Include dependency graph for tiff-document.c:

Go to the source code of this file.

Data Structures

struct  _TiffDocumentClass
 
struct  _TiffDocument
 

Typedefs

typedef struct _TiffDocumentClass TiffDocumentClass
 

Functions

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 void push_handlers (void)
 
static void pop_handlers (void)
 
static gboolean tiff_document_load (EvDocument *document, const char *uri, GError **error)
 
static gboolean tiff_document_save (EvDocument *document, const char *uri, GError **error)
 
static int tiff_document_get_n_pages (EvDocument *document)
 
static void tiff_document_get_resolution (TiffDocument *tiff_document, gfloat *x_res, gfloat *y_res)
 
static void tiff_document_get_page_size (EvDocument *document, EvPage *page, double *width, double *height)
 
static cairo_surface_t * tiff_document_render (EvDocument *document, EvRenderContext *rc)
 
static GdkPixbuf * tiff_document_get_thumbnail (EvDocument *document, EvRenderContext *rc)
 
static gchar * tiff_document_get_page_label (EvDocument *document, EvPage *page)
 
static void tiff_document_finalize (GObject *object)
 
static void tiff_document_class_init (TiffDocumentClass *klass)
 
static void tiff_document_file_exporter_begin (EvFileExporter *exporter, EvFileExporterContext *fc)
 
static void tiff_document_file_exporter_do_page (EvFileExporter *exporter, EvRenderContext *rc)
 
static void tiff_document_file_exporter_end (EvFileExporter *exporter)
 
static EvFileExporterCapabilities tiff_document_file_exporter_get_capabilities (EvFileExporter *exporter)
 
static void tiff_document_init (TiffDocument *tiff_document)
 

Variables

static TIFFErrorHandler orig_error_handler = NULL
 
static TIFFErrorHandler orig_warning_handler = NULL
 

Typedef Documentation

Definition at line 53 of file tiff-document.c.

Function Documentation

static void pop_handlers ( void  )
static

Definition at line 74 of file tiff-document.c.

75 {
76  TIFFSetErrorHandler (orig_error_handler);
77  TIFFSetWarningHandler (orig_warning_handler);
78 }

+ Here is the caller graph for this function:

static void push_handlers ( void  )
static

Definition at line 67 of file tiff-document.c.

68 {
69  orig_error_handler = TIFFSetErrorHandler (NULL);
70  orig_warning_handler = TIFFSetWarningHandler (NULL);
71 }

+ Here is the caller graph for this function:

static void tiff_document_class_init ( TiffDocumentClass klass)
static

Definition at line 442 of file tiff-document.c.

443 {
444  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
445  EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
446 
447  gobject_class->finalize = tiff_document_finalize;
448 
449  ev_document_class->load = tiff_document_load;
450  ev_document_class->save = tiff_document_save;
451  ev_document_class->get_n_pages = tiff_document_get_n_pages;
452  ev_document_class->get_page_size = tiff_document_get_page_size;
453  ev_document_class->render = tiff_document_render;
454  ev_document_class->get_thumbnail = tiff_document_get_thumbnail;
455  ev_document_class->get_page_label = tiff_document_get_page_label;
456 }
static void tiff_document_document_file_exporter_iface_init ( EvFileExporterInterface iface)
static
static void tiff_document_file_exporter_begin ( EvFileExporter exporter,
EvFileExporterContext fc 
)
static

Definition at line 460 of file tiff-document.c.

462 {
463  TiffDocument *document = TIFF_DOCUMENT (exporter);
464 
465  document->ps_export_ctx = tiff2ps_context_new(fc->filename);
466 }

+ Here is the caller graph for this function:

static void tiff_document_file_exporter_do_page ( EvFileExporter exporter,
EvRenderContext rc 
)
static

Definition at line 469 of file tiff-document.c.

470 {
471  TiffDocument *document = TIFF_DOCUMENT (exporter);
472 
473  if (document->ps_export_ctx == NULL)
474  return;
475  if (TIFFSetDirectory (document->tiff, rc->page->index) != 1)
476  return;
477  tiff2ps_process_page (document->ps_export_ctx, document->tiff,
478  0, 0, 0, 0, 0);
479 }

+ Here is the caller graph for this function:

static void tiff_document_file_exporter_end ( EvFileExporter exporter)
static

Definition at line 482 of file tiff-document.c.

483 {
484  TiffDocument *document = TIFF_DOCUMENT (exporter);
485 
486  if (document->ps_export_ctx == NULL)
487  return;
489 }

+ Here is the caller graph for this function:

static EvFileExporterCapabilities tiff_document_file_exporter_get_capabilities ( EvFileExporter exporter)
static

Definition at line 492 of file tiff-document.c.

+ Here is the caller graph for this function:

static void tiff_document_finalize ( GObject *  object)
static

Definition at line 429 of file tiff-document.c.

430 {
431  TiffDocument *tiff_document = TIFF_DOCUMENT (object);
432 
433  if (tiff_document->tiff)
434  TIFFClose (tiff_document->tiff);
435  if (tiff_document->uri)
436  g_free (tiff_document->uri);
437 
438  G_OBJECT_CLASS (tiff_document_parent_class)->finalize (object);
439 }

+ Here is the caller graph for this function:

static int tiff_document_get_n_pages ( EvDocument document)
static

Definition at line 149 of file tiff-document.c.

150 {
151  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
152 
153  g_return_val_if_fail (TIFF_IS_DOCUMENT (document), 0);
154  g_return_val_if_fail (tiff_document->tiff != NULL, 0);
155 
156  if (tiff_document->n_pages == -1) {
157  push_handlers ();
158  tiff_document->n_pages = 0;
159 
160  do {
161  tiff_document->n_pages ++;
162  }
163  while (TIFFReadDirectory (tiff_document->tiff));
164  pop_handlers ();
165  }
166 
167  return tiff_document->n_pages;
168 }

+ Here is the caller graph for this function:

static gchar* tiff_document_get_page_label ( EvDocument document,
EvPage page 
)
static

Definition at line 414 of file tiff-document.c.

416 {
417  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
418  static gchar *label;
419 
420  if (TIFFGetField (tiff_document->tiff, TIFFTAG_PAGENAME, &label) &&
421  g_utf8_validate (label, -1, NULL)) {
422  return g_strdup (label);
423  }
424 
425  return NULL;
426 }

+ Here is the caller graph for this function:

static void tiff_document_get_page_size ( EvDocument document,
EvPage page,
double *  width,
double *  height 
)
static

Definition at line 195 of file tiff-document.c.

199 {
200  guint32 w, h;
201  gfloat x_res, y_res;
202  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
203 
204  g_return_if_fail (TIFF_IS_DOCUMENT (document));
205  g_return_if_fail (tiff_document->tiff != NULL);
206 
207  push_handlers ();
208  if (TIFFSetDirectory (tiff_document->tiff, page->index) != 1) {
209  pop_handlers ();
210  return;
211  }
212 
213  TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &w);
214  TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &h);
215  tiff_document_get_resolution (tiff_document, &x_res, &y_res);
216  h = h * (x_res / y_res);
217 
218  *width = w;
219  *height = h;
220 
221  pop_handlers ();
222 }

+ Here is the caller graph for this function:

static void tiff_document_get_resolution ( TiffDocument tiff_document,
gfloat *  x_res,
gfloat *  y_res 
)
static

Definition at line 171 of file tiff-document.c.

174 {
175  gfloat x = 0.0;
176  gfloat y = 0.0;
177  gushort unit;
178 
179  if (TIFFGetField (tiff_document->tiff, TIFFTAG_XRESOLUTION, &x) &&
180  TIFFGetField (tiff_document->tiff, TIFFTAG_YRESOLUTION, &y)) {
181  if (TIFFGetFieldDefaulted (tiff_document->tiff, TIFFTAG_RESOLUTIONUNIT, &unit)) {
182  if (unit == RESUNIT_CENTIMETER) {
183  x *= 2.54;
184  y *= 2.54;
185  }
186  }
187  }
188 
189  /* Handle 0 values: some software set TIFF resolution as `0 , 0` see bug #646414 */
190  *x_res = x > 0 ? x : 72.0;
191  *y_res = y > 0 ? y : 72.0;
192 }

+ Here is the caller graph for this function:

static GdkPixbuf* tiff_document_get_thumbnail ( EvDocument document,
EvRenderContext rc 
)
static

Definition at line 340 of file tiff-document.c.

342 {
343  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
344  int width, height;
345  int scaled_width, scaled_height;
346  float x_res, y_res;
347  gint rowstride, bytes;
348  guchar *pixels = NULL;
349  GdkPixbuf *pixbuf;
350  GdkPixbuf *scaled_pixbuf;
351  GdkPixbuf *rotated_pixbuf;
352 
353  push_handlers ();
354  if (TIFFSetDirectory (tiff_document->tiff, rc->page->index) != 1) {
355  pop_handlers ();
356  return NULL;
357  }
358 
359  if (!TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &width)) {
360  pop_handlers ();
361  return NULL;
362  }
363 
364  if (! TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &height)) {
365  pop_handlers ();
366  return NULL;
367  }
368 
369  tiff_document_get_resolution (tiff_document, &x_res, &y_res);
370 
371  pop_handlers ();
372 
373  /* Sanity check the doc */
374  if (width <= 0 || height <= 0)
375  return NULL;
376 
377  rowstride = width * 4;
378  if (rowstride / 4 != width)
379  /* overflow */
380  return NULL;
381 
382  bytes = height * rowstride;
383  if (bytes / rowstride != height)
384  /* overflow */
385  return NULL;
386 
387  pixels = g_try_malloc (bytes);
388  if (!pixels)
389  return NULL;
390 
391  pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8,
392  width, height, rowstride,
393  (GdkPixbufDestroyNotify) g_free, NULL);
394  TIFFReadRGBAImageOriented (tiff_document->tiff,
395  width, height,
396  (uint32 *)pixels,
397  ORIENTATION_TOPLEFT, 0);
398  pop_handlers ();
399 
400  ev_render_context_compute_scaled_size (rc, width, height * (x_res / y_res),
401  &scaled_width, &scaled_height);
402  scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
403  scaled_width, scaled_height,
404  GDK_INTERP_BILINEAR);
405  g_object_unref (pixbuf);
406 
407  rotated_pixbuf = gdk_pixbuf_rotate_simple (scaled_pixbuf, 360 - rc->rotation);
408  g_object_unref (scaled_pixbuf);
409 
410  return rotated_pixbuf;
411 }

+ Here is the caller graph for this function:

static void tiff_document_init ( TiffDocument tiff_document)
static

Definition at line 511 of file tiff-document.c.

512 {
513  tiff_document->n_pages = -1;
514 }
static gboolean tiff_document_load ( EvDocument document,
const char *  uri,
GError **  error 
)
static

Definition at line 81 of file tiff-document.c.

84 {
85  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
86  gchar *filename;
87  TIFF *tiff;
88 
89  filename = g_filename_from_uri (uri, NULL, error);
90  if (!filename)
91  return FALSE;
92 
93  push_handlers ();
94 
95 #ifdef G_OS_WIN32
96 {
97  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, error);
98  if (wfilename == NULL) {
99  return FALSE;
100  }
101 
102  tiff = TIFFOpenW (wfilename, "r");
103 
104  g_free (wfilename);
105 }
106 #else
107  tiff = TIFFOpen (filename, "r");
108 #endif
109  if (tiff) {
110  guint32 w, h;
111 
112  /* FIXME: unused data? why bother here */
113  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
114  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
115  }
116 
117  if (!tiff) {
118  pop_handlers ();
119 
120  g_set_error_literal (error,
123  _("Invalid document"));
124 
125  g_free (filename);
126  return FALSE;
127  }
128 
129  tiff_document->tiff = tiff;
130  g_free (tiff_document->uri);
131  g_free (filename);
132  tiff_document->uri = g_strdup (uri);
133 
134  pop_handlers ();
135  return TRUE;
136 }

+ Here is the caller graph for this function:

static cairo_surface_t* tiff_document_render ( EvDocument document,
EvRenderContext rc 
)
static

Definition at line 225 of file tiff-document.c.

227 {
228  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
229  int width, height;
230  int scaled_width, scaled_height;
231  float x_res, y_res;
232  gint rowstride, bytes;
233  guchar *pixels = NULL;
234  guchar *p;
235  int orientation;
236  cairo_surface_t *surface;
237  cairo_surface_t *rotated_surface;
238  static const cairo_user_data_key_t key;
239 
240  g_return_val_if_fail (TIFF_IS_DOCUMENT (document), NULL);
241  g_return_val_if_fail (tiff_document->tiff != NULL, NULL);
242 
243  push_handlers ();
244  if (TIFFSetDirectory (tiff_document->tiff, rc->page->index) != 1) {
245  pop_handlers ();
246  g_warning("Failed to select page %d", rc->page->index);
247  return NULL;
248  }
249 
250  if (!TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &width)) {
251  pop_handlers ();
252  g_warning("Failed to read image width");
253  return NULL;
254  }
255 
256  if (! TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &height)) {
257  pop_handlers ();
258  g_warning("Failed to read image height");
259  return NULL;
260  }
261 
262  if (! TIFFGetField (tiff_document->tiff, TIFFTAG_ORIENTATION, &orientation)) {
263  orientation = ORIENTATION_TOPLEFT;
264  }
265 
266  tiff_document_get_resolution (tiff_document, &x_res, &y_res);
267 
268  pop_handlers ();
269 
270  /* Sanity check the doc */
271  if (width <= 0 || height <= 0) {
272  g_warning("Invalid width or height.");
273  return NULL;
274  }
275 
276 #ifdef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH
277  rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, width);
278 #else
279  rowstride = width * 4;
280 #endif
281  if (rowstride / 4 != width) {
282  g_warning("Overflow while rendering document.");
283  /* overflow, or cairo was changed in an unsupported way */
284  return NULL;
285  }
286 
287  bytes = height * rowstride;
288  if (bytes / rowstride != height) {
289  g_warning("Overflow while rendering document.");
290  /* overflow */
291  return NULL;
292  }
293 
294  pixels = g_try_malloc (bytes);
295  if (!pixels) {
296  g_warning("Failed to allocate memory for rendering.");
297  return NULL;
298  }
299 
300  surface = cairo_image_surface_create_for_data (pixels,
301  CAIRO_FORMAT_RGB24,
302  width, height,
303  rowstride);
304  cairo_surface_set_user_data (surface, &key,
305  pixels, (cairo_destroy_func_t)g_free);
306 
307  TIFFReadRGBAImageOriented (tiff_document->tiff,
308  width, height,
309  (uint32 *)pixels,
310  orientation, 0);
311  pop_handlers ();
312 
313  /* Convert the format returned by libtiff to
314  * what cairo expects
315  */
316  p = pixels;
317  while (p < pixels + bytes) {
318  guint32 *pixel = (guint32*)p;
319  guint8 r = TIFFGetR(*pixel);
320  guint8 g = TIFFGetG(*pixel);
321  guint8 b = TIFFGetB(*pixel);
322  guint8 a = TIFFGetA(*pixel);
323 
324  *pixel = (a << 24) | (r << 16) | (g << 8) | b;
325 
326  p += 4;
327  }
328 
329  ev_render_context_compute_scaled_size (rc, width, height * (x_res / y_res),
330  &scaled_width, &scaled_height);
331  rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
332  scaled_width, scaled_height,
333  rc->rotation);
334  cairo_surface_destroy (surface);
335 
336  return rotated_surface;
337 }

+ Here is the caller graph for this function:

static gboolean tiff_document_save ( EvDocument document,
const char *  uri,
GError **  error 
)
static

Definition at line 139 of file tiff-document.c.

142 {
143  TiffDocument *tiff_document = TIFF_DOCUMENT (document);
144 
145  return ev_xfer_uri_simple (tiff_document->uri, uri, error);
146 }

+ Here is the caller graph for this function:

Variable Documentation

TIFFErrorHandler orig_error_handler = NULL
static

Definition at line 63 of file tiff-document.c.

TIFFErrorHandler orig_warning_handler = NULL
static

Definition at line 64 of file tiff-document.c.