]> www.fi.muni.cz Git - evince.git/blob - tiff/tiff-document.c
modify the expose handling to get the shadows.
[evince.git] / tiff / tiff-document.c
1
2 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
3 /*
4  * Copyright (C) 2005, Jonathan Blandford <jrb@gnome.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 /* FIXME: Shoudl probably buffer calls to libtiff with TIFFSetWarningHandler
22  */
23 #include "tiffio.h"
24 #include "tiff-document.h"
25 #include "ev-document-thumbnails.h"
26 #include "ev-document-misc.h"
27
28 struct _TiffDocumentClass
29 {
30   GObjectClass parent_class;
31 };
32
33 struct _TiffDocument
34 {
35   GObject parent_instance;
36
37   TIFF *tiff;
38   gint n_pages;
39 };
40
41 typedef struct _TiffDocumentClass TiffDocumentClass;
42
43 static void tiff_document_document_iface_init (EvDocumentIface *iface);
44 static void tiff_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
45
46 G_DEFINE_TYPE_WITH_CODE (TiffDocument, tiff_document, G_TYPE_OBJECT,
47                          { G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
48                                                   tiff_document_document_iface_init);
49                            G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
50                                                   tiff_document_document_thumbnails_iface_init);
51                          });
52
53 static TIFFErrorHandler orig_error_handler = NULL;
54 static TIFFErrorHandler orig_warning_handler = NULL;
55
56 static void
57 push_handlers (void)
58 {
59   orig_error_handler = TIFFSetErrorHandler (NULL);
60   orig_warning_handler = TIFFSetWarningHandler (NULL);
61 }
62
63 static void
64 pop_handlers (void)
65 {
66   TIFFSetErrorHandler (orig_error_handler);
67   TIFFSetWarningHandler (orig_warning_handler);
68 }
69
70 static gboolean
71 tiff_document_load (EvDocument  *document,
72                     const char  *uri,
73                     GError     **error)
74 {
75   TiffDocument *tiff_document = TIFF_DOCUMENT (document);
76   gchar *filename;
77   TIFF *tiff;
78
79   push_handlers ();
80   /* FIXME: We could actually load uris  */
81   filename = g_filename_from_uri (uri, NULL, error);
82   if (!filename)
83     {
84       pop_handlers ();
85       return FALSE;
86     }
87
88   tiff = TIFFOpen (filename, "r");
89   if (tiff)
90     {
91       guint32 w, h;
92       
93       TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
94       TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
95     }
96   if (!tiff)
97     {
98       pop_handlers ();
99       return FALSE;
100     }
101   tiff_document->tiff = tiff;
102
103   pop_handlers ();
104   return TRUE;
105 }
106
107 static gboolean
108 tiff_document_save (EvDocument  *document,
109                       const char  *uri,
110                       GError     **error)
111 {
112         return FALSE;
113 }
114
115 static int
116 tiff_document_get_n_pages (EvDocument  *document)
117 {
118   TiffDocument *tiff_document = TIFF_DOCUMENT (document);
119
120   g_return_val_if_fail (TIFF_IS_DOCUMENT (document), 0);
121   g_return_val_if_fail (tiff_document->tiff != NULL, 0);
122
123   if (tiff_document->n_pages == -1)
124     {
125       push_handlers ();
126       tiff_document->n_pages = 0;
127       do
128         {
129           tiff_document->n_pages ++;
130         }
131       while (TIFFReadDirectory (tiff_document->tiff));
132       pop_handlers ();
133     }
134
135   return tiff_document->n_pages;
136 }
137
138 static void
139 tiff_document_get_page_size (EvDocument   *document,
140                              int           page,
141                              double       *width,
142                              double       *height)
143 {
144   guint32 w, h;
145   TiffDocument *tiff_document = TIFF_DOCUMENT (document);
146
147   g_return_if_fail (TIFF_IS_DOCUMENT (document));
148   g_return_if_fail (tiff_document->tiff != NULL);
149
150   push_handlers ();
151   if (TIFFSetDirectory (tiff_document->tiff, page) != 1)
152     {
153       pop_handlers ();
154       return;
155     }
156
157   TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &w);
158   TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &h);
159
160   *width = w;
161   *height = h;
162   pop_handlers ();
163 }
164
165 static GdkPixbuf *
166 tiff_document_render_pixbuf (EvDocument  *document, int page, double scale)
167 {
168   TiffDocument *tiff_document = TIFF_DOCUMENT (document);
169   int width, height;
170   gint rowstride, bytes;
171   guchar *pixels = NULL;
172   GdkPixbuf *pixbuf;
173   GdkPixbuf *scaled_pixbuf;
174
175   g_return_val_if_fail (TIFF_IS_DOCUMENT (document), 0);
176   g_return_val_if_fail (tiff_document->tiff != NULL, 0);
177
178   push_handlers ();
179   if (TIFFSetDirectory (tiff_document->tiff, page) != 1)
180     {
181       pop_handlers ();
182       return NULL;
183     }
184
185   if (!TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &width))
186     {
187       pop_handlers ();
188       return NULL;
189     }
190
191   if (! TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &height))
192     {
193       pop_handlers ();
194       return NULL;
195     }
196
197   pop_handlers ();
198
199   /* Sanity check the doc */
200   if (width <= 0 || height <= 0)
201     return NULL;                
202         
203   rowstride = width * 4;
204   if (rowstride / 4 != width)
205     /* overflow */
206     return NULL;                
207         
208   bytes = height * rowstride;
209   if (bytes / rowstride != height)
210     /* overflow */
211     return NULL;                
212
213   pixels = g_try_malloc (bytes);
214   if (!pixels)
215     return NULL;
216
217   pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, 
218                                      width, height, rowstride,
219                                      (GdkPixbufDestroyNotify) g_free, NULL);
220
221   pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
222   TIFFReadRGBAImageOriented (tiff_document->tiff, width, height, (uint32 *)gdk_pixbuf_get_pixels (pixbuf), ORIENTATION_TOPLEFT, 1);
223   pop_handlers ();
224
225   scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
226                                            width * scale,
227                                            height * scale,
228                                            GDK_INTERP_BILINEAR);
229   g_object_unref (pixbuf);
230
231   return scaled_pixbuf;
232 }
233
234 static void
235 tiff_document_finalize (GObject *object)
236 {
237         TiffDocument *tiff_document = TIFF_DOCUMENT (object);
238
239         TIFFClose (tiff_document->tiff);
240
241         G_OBJECT_CLASS (tiff_document_parent_class)->finalize (object);
242 }
243
244 static void
245 tiff_document_class_init (TiffDocumentClass *klass)
246 {
247         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
248
249         gobject_class->finalize = tiff_document_finalize;
250 }
251
252 static gboolean
253 tiff_document_can_get_text (EvDocument *document)
254 {
255         return FALSE;
256 }
257
258 static EvDocumentInfo *
259 tiff_document_get_info (EvDocument *document)
260 {
261         EvDocumentInfo *info;
262
263         info = g_new0 (EvDocumentInfo, 1);
264         info->fields_mask = 0;
265
266         return info;
267 }
268
269 static void
270 tiff_document_document_iface_init (EvDocumentIface *iface)
271 {
272         iface->load = tiff_document_load;
273         iface->save = tiff_document_save;
274         iface->can_get_text = tiff_document_can_get_text;
275         iface->get_n_pages = tiff_document_get_n_pages;
276         iface->get_page_size = tiff_document_get_page_size;
277         iface->render_pixbuf = tiff_document_render_pixbuf;
278         iface->get_info = tiff_document_get_info;
279 }
280
281 static GdkPixbuf *
282 tiff_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
283                                         gint                  page,
284                                         gint                  size,
285                                         gboolean              border)
286 {
287   GdkPixbuf *pixbuf;
288   gdouble w, h;
289
290   tiff_document_get_page_size (EV_DOCUMENT (document),
291                                page,
292                                &w, &h);
293
294   pixbuf = tiff_document_render_pixbuf (EV_DOCUMENT (document),
295                                         page,
296                                         size/w);
297
298   if (border)
299     {
300       GdkPixbuf *tmp_pixbuf = pixbuf;
301       pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
302       g_object_unref (tmp_pixbuf);
303     }
304
305   return pixbuf;
306 }
307
308 static void
309 tiff_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
310                                          gint                  page,
311                                          gint                  suggested_width,
312                                          gint                 *width,
313                                          gint                 *height)
314 {
315   gdouble page_ratio;
316   gdouble w, h;
317
318   tiff_document_get_page_size (EV_DOCUMENT (document),
319                                page,
320                                &w, &h);
321   g_return_if_fail (w > 0);
322   page_ratio = h/w;
323   *width = suggested_width;
324   *height = (gint) (suggested_width * page_ratio);
325 }
326
327 static void
328 tiff_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
329 {
330   iface->get_thumbnail = tiff_document_thumbnails_get_thumbnail;
331   iface->get_dimensions = tiff_document_thumbnails_get_dimensions;
332 }
333
334
335 static void
336 tiff_document_init (TiffDocument *tiff_document)
337 {
338   tiff_document->n_pages = -1;
339 }