]> www.fi.muni.cz Git - evince.git/blob - dvi/dvi-document.c
Updated Czech translation.
[evince.git] / dvi / dvi-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 <config.h>
21
22 #include "dvi-document.h"
23 #include "ev-document-thumbnails.h"
24 #include "ev-document-misc.h"
25
26 #include "mdvi.h"
27 #include "fonts.h"
28 #include "pixbuf-device.h"
29
30 #include <gtk/gtk.h>
31 #include <glib/gi18n.h>
32 #include <libgnomevfs/gnome-vfs-uri.h>
33 #include <libgnomevfs/gnome-vfs-utils.h>
34 #include <libgnomevfs/gnome-vfs-ops.h>
35 #include <libgnomevfs/gnome-vfs-xfer.h>
36
37 GMutex *dvi_context_mutex = NULL;
38
39 enum {
40         PROP_0,
41         PROP_TITLE
42 };
43
44 struct _DviDocumentClass
45 {
46         GObjectClass parent_class;
47 };
48
49 struct _DviDocument
50 {
51         GObject parent_instance;
52
53         DviContext *context;
54         DviPageSpec *spec;
55         DviParams *params;
56         
57         /* To let document scale we should remember width and height */
58         
59         double base_width;
60         double base_height;
61         
62         gchar *uri;
63 };
64
65 typedef struct _DviDocumentClass DviDocumentClass;
66
67 static void dvi_document_document_iface_init (EvDocumentIface *iface);
68 static void dvi_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
69 static void dvi_document_get_page_size                  (EvDocument   *document,
70                                                          int       page,
71                                                          double    *width,
72                                                          double    *height);
73
74 G_DEFINE_TYPE_WITH_CODE 
75     (DviDocument, dvi_document, G_TYPE_OBJECT, 
76     {
77       G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT, dvi_document_document_iface_init);    
78       G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS, dvi_document_document_thumbnails_iface_init)
79      });
80
81 static gboolean
82 dvi_document_load (EvDocument  *document,
83                       const char  *uri,
84                       GError     **error)
85 {
86     gchar *filename;
87     DviDocument *dvi_document = DVI_DOCUMENT(document);
88     
89     filename = g_filename_from_uri (uri, NULL, error);
90     
91     if (!filename) {
92                 g_set_error (error,
93                              EV_DOCUMENT_ERROR,
94                              EV_DOCUMENT_ERROR_INVALID,
95                              _("File not available"));
96                 return FALSE;
97     }
98         
99     if (dvi_document->context)
100         mdvi_destroy_context (dvi_document->context);
101
102     dvi_document->context = mdvi_init_context(dvi_document->params, dvi_document->spec, filename);
103
104     if (!dvi_document->context) {
105                 g_set_error (error,
106                              EV_DOCUMENT_ERROR,
107                              EV_DOCUMENT_ERROR_INVALID,
108                              _("DVI document has incorrect format"));
109                 return FALSE;
110     }
111
112     mdvi_pixbuf_device_init (&dvi_document->context->device);
113
114     dvi_document->base_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv 
115                 + 2 * unit2pix(dvi_document->params->dpi, MDVI_HMARGIN) / dvi_document->params->hshrink;
116                 
117     dvi_document->base_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv 
118                 + 2 * unit2pix(dvi_document->params->vdpi, MDVI_VMARGIN) / dvi_document->params->vshrink;
119
120     dvi_context_mutex = g_mutex_new ();
121
122     g_free (dvi_document->uri);
123     dvi_document->uri = g_strdup (uri);
124
125     return TRUE;
126 }
127
128
129 static gboolean
130 dvi_document_save (EvDocument  *document,
131                       const char  *uri,
132                       GError     **error)
133 {
134         DviDocument *dvi_document = DVI_DOCUMENT (document);
135         GnomeVFSResult result;
136         GnomeVFSURI *source_uri;
137         GnomeVFSURI *target_uri;
138         
139         if (!dvi_document->uri)
140                 return FALSE;
141         
142         source_uri = gnome_vfs_uri_new (dvi_document->uri);
143         target_uri = gnome_vfs_uri_new (uri);
144
145         result = gnome_vfs_xfer_uri (source_uri, target_uri, 
146                                      GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
147                                      GNOME_VFS_XFER_ERROR_MODE_ABORT,
148                                      GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
149                                      NULL,
150                                      NULL);
151         gnome_vfs_uri_unref (target_uri);
152         gnome_vfs_uri_unref (source_uri);
153     
154         if (result != GNOME_VFS_OK)
155                 g_set_error (error,
156                              EV_DOCUMENT_ERROR,
157                              0,
158                              gnome_vfs_result_to_string (result));                      
159         return (result == GNOME_VFS_OK);
160         return TRUE;
161 }
162
163 static int
164 dvi_document_get_n_pages (EvDocument  *document)
165 {
166     DviDocument *dvi_document = DVI_DOCUMENT (document);
167     return dvi_document->context->npages;
168 }
169
170 static void
171 dvi_document_get_page_size (EvDocument   *document,
172                             int       page,
173                             double    *width,
174                             double    *height)
175 {
176         DviDocument * dvi_document = DVI_DOCUMENT (document);   
177
178         *width = dvi_document->base_width;
179         *height = dvi_document->base_height;;
180                                     
181         return;
182 }
183
184 static GdkPixbuf *
185 dvi_document_render_pixbuf (EvDocument  *document,
186                             EvRenderContext *rc)
187 {
188         GdkPixbuf *pixbuf;
189         GdkPixbuf *rotated_pixbuf;
190
191         DviDocument *dvi_document = DVI_DOCUMENT(document);
192
193         gint required_width, required_height;
194         gint proposed_width, proposed_height;
195         gint xmargin = 0, ymargin = 0;
196
197         /* We should protect our context since it's not 
198          * thread safe. The work to the future - 
199          * let context render page independently
200          */
201         g_mutex_lock (dvi_context_mutex);
202         
203         mdvi_setpage(dvi_document->context,  rc->page);
204         
205         mdvi_set_shrink (dvi_document->context, 
206                          (int)((dvi_document->params->hshrink - 1) / rc->scale) + 1,
207                          (int)((dvi_document->params->vshrink - 1) / rc->scale) + 1);
208
209         required_width = dvi_document->base_width * rc->scale;
210         required_height = dvi_document->base_height * rc->scale;
211         proposed_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv;
212         proposed_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv;
213         
214         if (required_width >= proposed_width)
215             xmargin = (required_width - proposed_width) / 2;
216         if (required_height >= proposed_height)
217             ymargin = (required_height - proposed_height) / 2;
218             
219         mdvi_pixbuf_device_set_margins (&dvi_document->context->device, xmargin, ymargin);
220
221         mdvi_pixbuf_device_render (dvi_document->context);
222         
223         pixbuf = mdvi_pixbuf_device_get_pixbuf (&dvi_document->context->device);
224
225         g_mutex_unlock (dvi_context_mutex);
226
227         rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rc->rotation);
228         g_object_unref (pixbuf);
229
230         return rotated_pixbuf;
231 }
232
233 static void
234 dvi_document_finalize (GObject *object)
235 {       
236         DviDocument *dvi_document = DVI_DOCUMENT(object);
237
238         if (dvi_document->context)
239             {
240                 mdvi_pixbuf_device_free (&dvi_document->context->device);
241                 mdvi_destroy_context (dvi_document->context);
242             }
243
244         if (dvi_document->params)
245                 g_free (dvi_document->params);
246
247         g_free (dvi_document->uri);
248                 
249         G_OBJECT_CLASS (dvi_document_parent_class)->finalize (object);
250 }
251
252
253 static void
254 dvi_document_class_init (DviDocumentClass *klass)
255 {
256         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
257
258         gobject_class->finalize = dvi_document_finalize;
259 }
260
261 static gboolean
262 dvi_document_can_get_text (EvDocument *document)
263 {
264         return FALSE;
265 }
266
267 static EvDocumentInfo *
268 dvi_document_get_info (EvDocument *document)
269 {
270         EvDocumentInfo *info;
271
272         info = g_new0 (EvDocumentInfo, 1);
273
274         return info;
275 }
276
277 static void
278 dvi_document_document_iface_init (EvDocumentIface *iface)
279 {
280         iface->load = dvi_document_load;
281         iface->save = dvi_document_save;
282         iface->can_get_text = dvi_document_can_get_text;
283         iface->get_n_pages = dvi_document_get_n_pages;
284         iface->get_page_size = dvi_document_get_page_size;
285         iface->render_pixbuf = dvi_document_render_pixbuf;
286         iface->get_info = dvi_document_get_info;
287 }
288
289 static void
290 dvi_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
291                                         gint                  page,
292                                         gint                  suggested_width,
293                                         gint                  *width,
294                                         gint                  *height)
295 {       
296         DviDocument *dvi_document = DVI_DOCUMENT (document); 
297         gdouble page_ratio;
298         
299         page_ratio = dvi_document->base_height / dvi_document->base_width;
300         *width = suggested_width;
301         *height = (gint) (suggested_width * page_ratio);
302
303         return;
304 }
305
306 static GdkPixbuf *
307 dvi_document_thumbnails_get_thumbnail (EvDocumentThumbnails   *document,
308                                        gint                      page,
309                                        gint                      rotation,
310                                        gint                      width,
311                                        gboolean                  border)
312 {
313         DviDocument *dvi_document = DVI_DOCUMENT (document);
314         GdkPixbuf *pixbuf;
315         GdkPixbuf *border_pixbuf;
316         GdkPixbuf *rotated_pixbuf;
317         gint thumb_width, thumb_height;
318         gint proposed_width, proposed_height;
319         
320         dvi_document_thumbnails_get_dimensions (document, page, width, &thumb_width, &thumb_height);
321
322         g_mutex_lock (dvi_context_mutex);
323
324         mdvi_setpage(dvi_document->context,  page);
325
326         mdvi_set_shrink (dvi_document->context, 
327                           (int)dvi_document->base_width * dvi_document->params->hshrink / thumb_width,
328                           (int)dvi_document->base_height * dvi_document->params->vshrink / thumb_height);
329
330         proposed_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv;
331         proposed_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv;
332                           
333         if (border) {
334                 mdvi_pixbuf_device_set_margins  (&dvi_document->context->device, 
335                                                  MAX (thumb_width - proposed_width, 0) / 2,
336                                                  MAX (thumb_height - proposed_height, 0) / 2);  
337         } else {
338                 mdvi_pixbuf_device_set_margins  (&dvi_document->context->device, 
339                                                  MAX (thumb_width - proposed_width - 2, 0) / 2,
340                                                  MAX (thumb_height - proposed_height - 2, 0) / 2);      
341         }
342         
343
344         mdvi_pixbuf_device_render (dvi_document->context);
345         pixbuf = mdvi_pixbuf_device_get_pixbuf (&dvi_document->context->device);
346
347         g_mutex_unlock (dvi_context_mutex);
348         
349         rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rotation);
350         g_object_unref (pixbuf);
351         
352         if (border) {
353               GdkPixbuf *tmp_pixbuf = rotated_pixbuf;
354               rotated_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, 0, tmp_pixbuf);
355               g_object_unref (tmp_pixbuf);
356         }
357
358         return rotated_pixbuf;
359 }
360
361 static void
362 dvi_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
363 {
364         iface->get_thumbnail = dvi_document_thumbnails_get_thumbnail;
365         iface->get_dimensions = dvi_document_thumbnails_get_dimensions;
366 }
367
368
369 static void
370 dvi_document_init_params (DviDocument *dvi_document)
371 {       
372         dvi_document->params = g_new0 (DviParams, 1);   
373
374         dvi_document->params->dpi      = MDVI_DPI;
375         dvi_document->params->vdpi     = MDVI_VDPI;
376         dvi_document->params->mag      = MDVI_MAGNIFICATION;
377         dvi_document->params->density  = MDVI_DEFAULT_DENSITY;
378         dvi_document->params->gamma    = MDVI_DEFAULT_GAMMA;
379         dvi_document->params->flags    = MDVI_PARAM_ANTIALIASED;
380         dvi_document->params->hdrift   = 0;
381         dvi_document->params->vdrift   = 0;
382         dvi_document->params->hshrink  =  MDVI_SHRINK_FROM_DPI(dvi_document->params->dpi);
383         dvi_document->params->vshrink  =  MDVI_SHRINK_FROM_DPI(dvi_document->params->vdpi);
384         dvi_document->params->orientation = MDVI_ORIENT_TBLR;
385
386         dvi_document->spec = NULL;
387         
388         dvi_document->params->bg = 0xffffffff;
389         dvi_document->params->fg = 0xff000000;
390
391         mdvi_init_kpathsea("evince", MDVI_MFMODE, MDVI_FALLBACK_FONT, MDVI_DPI);
392         
393         mdvi_register_fonts ();
394 }
395
396 static void
397 dvi_document_init (DviDocument *dvi_document)
398 {
399         dvi_document->context = NULL;
400         dvi_document_init_params (dvi_document);
401 }