~ubuntu-branches/ubuntu/oneiric/evince/oneiric-updates

« back to all changes in this revision

Viewing changes to backend/dvi/dvi-document.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-01-10 19:35:11 UTC
  • mto: (1.3.1 experimental) (52.1.1 hardy-proposed)
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: james.westby@ubuntu.com-20070110193511-yjrnndv8e8wv03yy
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

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