]> www.fi.muni.cz Git - evince.git/blob - djvu/djvu-document.c
Translation updated.
[evince.git] / djvu / djvu-document.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /*
3  * Copyright (C) 2005, Nickolay V. Shmyrev <nshmyrev@yandex.ru>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include "djvu-document.h"
21 #include "djvu-text.h"
22 #include "djvu-document-private.h"
23 #include "ev-document-thumbnails.h"
24 #include "ev-document-misc.h"
25 #include "ev-document-find.h"
26
27 #include <libdjvu/ddjvuapi.h>
28 #include <gtk/gtk.h>
29 #include <gdk-pixbuf/gdk-pixbuf-core.h>
30 #include <glib/gunicode.h>
31 #include <string.h>
32
33 #define SCALE_FACTOR 0.2
34
35 enum {
36         PROP_0,
37         PROP_TITLE
38 };
39
40 struct _DjvuDocumentClass
41 {
42         GObjectClass parent_class;
43 };
44
45 typedef struct _DjvuDocumentClass DjvuDocumentClass;
46
47 static void djvu_document_document_iface_init (EvDocumentIface *iface);
48 static void djvu_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
49 static void djvu_document_find_iface_init (EvDocumentFindIface *iface);
50
51 G_DEFINE_TYPE_WITH_CODE 
52     (DjvuDocument, djvu_document, G_TYPE_OBJECT, 
53     {
54       G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT, djvu_document_document_iface_init);    
55       G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS, djvu_document_document_thumbnails_iface_init)
56       G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND, djvu_document_find_iface_init);
57      });
58
59
60 void 
61 djvu_handle_events (DjvuDocument *djvu_document, int wait)
62 {
63         ddjvu_context_t *ctx = djvu_document->d_context;
64         const ddjvu_message_t *msg;
65         if (!ctx)
66                 return;
67         if (wait)
68                 msg = ddjvu_message_wait (ctx);
69         while ((msg = ddjvu_message_peek (ctx))) {
70                 switch (msg->m_any.tag) {
71                         case DDJVU_ERROR:
72                                 g_warning ("DjvuLibre error: %s", 
73                                            msg->m_error.message);
74                                 if (msg->m_error.filename)
75                                         g_warning ("DjvuLibre error: %s:%d", 
76                                                    msg->m_error.filename,
77                                                    msg->m_error.lineno);
78                         default:
79                                 break;
80                 }
81                 ddjvu_message_pop (ctx);
82         }
83 }
84
85 static gboolean
86 djvu_document_load (EvDocument  *document,
87                     const char  *uri,
88                     GError     **error)
89 {
90         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
91         ddjvu_document_t *doc;
92         gchar *filename;
93
94         /* FIXME: We could actually load uris  */
95         filename = g_filename_from_uri (uri, NULL, error);
96         if (!filename)
97                 return FALSE;
98         
99         doc = ddjvu_document_create_by_filename (djvu_document->d_context, filename, TRUE);
100
101         if (!doc) return FALSE;
102
103         if (djvu_document->d_document)
104             ddjvu_document_release (djvu_document->d_document);
105
106         djvu_document->d_document = doc;
107
108         while (!ddjvu_document_decoding_done (djvu_document->d_document)) 
109                 djvu_handle_events(djvu_document, TRUE);
110         g_free (djvu_document->uri);
111         djvu_document->uri = g_strdup (uri);
112
113         return TRUE;
114 }
115
116
117 static gboolean
118 djvu_document_save (EvDocument  *document,
119                     const char  *uri,
120                     GError     **error)
121 {
122         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
123
124         return ev_xfer_uri_simple (djvu_document->uri, uri, error);
125 }
126
127 int
128 djvu_document_get_n_pages (EvDocument  *document)
129 {
130         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
131         
132         g_return_val_if_fail (djvu_document->d_document, 0);
133         
134         return ddjvu_document_get_pagenum (djvu_document->d_document);
135 }
136
137 static void
138 djvu_document_get_page_size (EvDocument   *document,
139                              int           page,
140                              double       *width,
141                              double       *height)
142 {
143         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
144         ddjvu_pageinfo_t info;
145         
146         g_return_if_fail (djvu_document->d_document);
147         
148         while (ddjvu_document_get_pageinfo(djvu_document->d_document, page, &info) < DDJVU_JOB_OK)
149                 djvu_handle_events(djvu_document, TRUE);
150
151         *width = info.width * SCALE_FACTOR; 
152         *height = info.height * SCALE_FACTOR;
153 }
154
155 static GdkPixbuf *
156 djvu_document_render_pixbuf (EvDocument  *document, 
157                              EvRenderContext *rc)
158 {
159         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
160         GdkPixbuf *pixbuf;
161         GdkPixbuf *rotated_pixbuf;
162         
163         ddjvu_rect_t rrect;
164         ddjvu_rect_t prect;
165         ddjvu_page_t *d_page;
166         
167         double page_width, page_height;
168
169         d_page = ddjvu_page_create_by_pageno (djvu_document->d_document, rc->page);
170         
171         while (!ddjvu_page_decoding_done (d_page))
172                 djvu_handle_events(djvu_document, TRUE);
173         
174         page_width = ddjvu_page_get_width (d_page) * rc->scale * SCALE_FACTOR;
175         page_height = ddjvu_page_get_height (d_page) * rc->scale * SCALE_FACTOR;
176
177         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, page_width, page_height);
178
179         prect.x = 0; prect.y = 0;
180         prect.w = page_width; prect.h = page_height;
181         rrect = prect;
182
183         ddjvu_page_render(d_page, DDJVU_RENDER_COLOR,
184                           &prect,
185                           &rrect,
186                           djvu_document->d_format,
187                           gdk_pixbuf_get_rowstride (pixbuf),
188                           (gchar *)gdk_pixbuf_get_pixels (pixbuf));
189         
190         rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rc->rotation);
191         g_object_unref (pixbuf);
192         
193         return rotated_pixbuf;
194 }
195
196 static void
197 djvu_document_finalize (GObject *object)
198 {
199         DjvuDocument *djvu_document = DJVU_DOCUMENT (object);
200
201         if (djvu_document->d_document)
202             ddjvu_document_release (djvu_document->d_document);
203
204         ddjvu_context_release (djvu_document->d_context);
205         ddjvu_format_release (djvu_document->d_format);
206         g_free (djvu_document->uri);
207         
208         G_OBJECT_CLASS (djvu_document_parent_class)->finalize (object);
209 }
210
211 static void
212 djvu_document_class_init (DjvuDocumentClass *klass)
213 {
214         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
215
216         gobject_class->finalize = djvu_document_finalize;
217 }
218
219 static gboolean
220 djvu_document_can_get_text (EvDocument *document)
221 {
222         return TRUE;
223 }
224
225
226 static char *
227 djvu_document_get_text (EvDocument *document, int page, EvRectangle *rect)
228 {
229         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
230         double width, height;
231         EvRectangle rectangle;
232         char* text;
233              
234         djvu_document_get_page_size (document, page, &width, &height);          
235         rectangle.x1 = rect->x1 / SCALE_FACTOR;
236         rectangle.y1 = (height - rect->y2) / SCALE_FACTOR;
237         rectangle.x2 = rect->x2 / SCALE_FACTOR;
238         rectangle.y2 = (height - rect->y1) / SCALE_FACTOR;
239                 
240         text = djvu_text_copy (djvu_document, page, &rectangle);
241       
242         if (text == NULL)
243                 text = g_strdup ("");
244                 
245         return text;
246 }
247
248 static EvDocumentInfo *
249 djvu_document_get_info (EvDocument *document)
250 {
251         EvDocumentInfo *info;
252
253         info = g_new0 (EvDocumentInfo, 1);
254
255         return info;
256 }
257
258 static void
259 djvu_document_document_iface_init (EvDocumentIface *iface)
260 {
261         iface->load = djvu_document_load;
262         iface->save = djvu_document_save;
263         iface->can_get_text = djvu_document_can_get_text;
264         iface->get_text = djvu_document_get_text;
265         iface->get_n_pages = djvu_document_get_n_pages;
266         iface->get_page_size = djvu_document_get_page_size;
267         iface->render_pixbuf = djvu_document_render_pixbuf;
268         iface->get_info = djvu_document_get_info;
269 }
270
271 static void
272 djvu_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
273                                            gint                  page,
274                                            gint                  suggested_width,
275                                            gint                  *width,
276                                            gint                  *height)
277 {
278         DjvuDocument *djvu_document = DJVU_DOCUMENT (document); 
279         gdouble p_width, p_height;
280         gdouble page_ratio;
281         
282         djvu_document_get_page_size (EV_DOCUMENT(djvu_document), page, &p_width, &p_height);
283
284         page_ratio = p_height / p_width;
285         *width = suggested_width;
286         *height = (gint) (suggested_width * page_ratio);
287         
288         return;
289 }
290
291 static GdkPixbuf *
292 djvu_document_thumbnails_get_thumbnail (EvDocumentThumbnails   *document,
293                                           gint                   page,
294                                           gint                   rotation,
295                                           gint                   width,
296                                           gboolean               border)
297 {
298         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
299         GdkPixbuf *pixbuf, *rotated_pixbuf;
300         gint thumb_width, thumb_height;
301
302         guchar *pixels;
303         
304         g_return_val_if_fail (djvu_document->d_document, NULL);
305         
306         djvu_document_thumbnails_get_dimensions (document, page, width, &thumb_width, &thumb_height);
307         
308         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
309                                  thumb_width, thumb_height);
310         gdk_pixbuf_fill (pixbuf, 0xffffffff);
311         pixels = gdk_pixbuf_get_pixels (pixbuf);
312         
313         while (ddjvu_thumbnail_status (djvu_document->d_document, page, 1) < DDJVU_JOB_OK)
314                 djvu_handle_events(djvu_document, TRUE);
315                     
316         ddjvu_thumbnail_render (djvu_document->d_document, page, 
317                                 &thumb_width, &thumb_height,
318                                 djvu_document->d_format,
319                                 gdk_pixbuf_get_rowstride (pixbuf), 
320                                 (gchar *)pixels);
321
322         rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rotation);
323         g_object_unref (pixbuf);
324
325         if (border) {
326               GdkPixbuf *tmp_pixbuf = rotated_pixbuf;
327               rotated_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, 0, tmp_pixbuf);
328               g_object_unref (tmp_pixbuf);
329         }
330         
331         return rotated_pixbuf;
332 }
333
334 static void
335 djvu_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
336 {
337         iface->get_thumbnail = djvu_document_thumbnails_get_thumbnail;
338         iface->get_dimensions = djvu_document_thumbnails_get_dimensions;
339 }
340
341 static void
342 djvu_document_init (DjvuDocument *djvu_document)
343 {
344         djvu_document->d_context = ddjvu_context_create ("Evince");
345         djvu_document->d_format = ddjvu_format_create (DDJVU_FORMAT_RGB24, 0, 0);
346         ddjvu_format_set_row_order (djvu_document->d_format,1);
347         
348         djvu_document->d_document = NULL;
349 }
350
351 static void
352 djvu_document_find_begin (EvDocumentFind   *document,
353                           int               page,
354                           const char       *search_string,
355                           gboolean          case_sensitive)
356 {
357         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
358
359         if (djvu_document->search && 
360             strcmp (search_string, djvu_text_get_text (djvu_document->search)) == 0)
361                 return;
362
363         if (djvu_document->search)
364                 djvu_text_free (djvu_document->search);
365
366         djvu_document->search = djvu_text_new (djvu_document,
367                                                           page,
368                                                           case_sensitive,
369                                                           search_string);
370 }
371
372 static int
373 djvu_document_find_get_n_results (EvDocumentFind *document_find, int page)
374 {
375         DjvuText *search = DJVU_DOCUMENT (document_find)->search;
376
377         if (search) {
378                 return djvu_text_n_results (search, page);
379         } else {
380                 return 0;
381         }
382 }
383
384 static gboolean
385 djvu_document_find_get_result (EvDocumentFind *document_find,
386                                int             page,
387                                int             n_result,
388                                EvRectangle    *rectangle)
389 {
390         DjvuDocument *djvu_document = DJVU_DOCUMENT (document_find);
391         DjvuText *search = djvu_document->search;
392         EvRectangle *r;
393         double width, height;
394
395         if (search == NULL)
396                 return FALSE;
397
398         r = djvu_text_get_result (search, page, n_result);
399         if (r == NULL)
400                 return FALSE;
401
402         djvu_document_get_page_size (EV_DOCUMENT (djvu_document), 
403                 page, &width, &height);
404         rectangle->x1 = r->x1 * SCALE_FACTOR;
405         rectangle->y1 = height - r->y2 * SCALE_FACTOR;
406         rectangle->x2 = r->x2 * SCALE_FACTOR;
407         rectangle->y2 = height - r->y1 * SCALE_FACTOR;
408                 
409         return TRUE;
410 }
411
412 static int
413 djvu_document_find_page_has_results (EvDocumentFind *document_find,
414                                     int             page)
415 {
416         DjvuText *search = DJVU_DOCUMENT (document_find)->search;
417
418         return search && djvu_text_has_results (search, page);
419 }
420
421 static double
422 djvu_document_find_get_progress (EvDocumentFind *document_find)
423 {
424         DjvuText *search = DJVU_DOCUMENT (document_find)->search;
425         
426         if (search == NULL) {
427                 return 0;
428         }
429
430         return djvu_text_get_progress (search);
431 }
432
433 static void
434 djvu_document_find_cancel (EvDocumentFind *document)
435 {
436         DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
437
438         if (djvu_document->search) {
439                 djvu_text_free (djvu_document->search);
440                 djvu_document->search = NULL;
441         }
442 }
443
444 static void
445 djvu_document_find_iface_init (EvDocumentFindIface *iface)
446 {
447         iface->begin = djvu_document_find_begin;
448         iface->get_n_results = djvu_document_find_get_n_results;
449         iface->get_result = djvu_document_find_get_result;
450         iface->page_has_results = djvu_document_find_page_has_results;
451         iface->get_progress = djvu_document_find_get_progress;
452         iface->cancel = djvu_document_find_cancel;
453 }