]> www.fi.muni.cz Git - evince.git/blob - backend/ps/ev-spectre.c
Remove EvDocumentThumbnails interface
[evince.git] / backend / ps / ev-spectre.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <config.h>
21
22 #include <config.h>
23 #include <glib/gi18n-lib.h>
24 #include <stdlib.h>
25 #include <libspectre/spectre.h>
26
27 #include "ev-spectre.h"
28
29 #include "ev-file-exporter.h"
30 #include "ev-document-misc.h"
31
32 struct _PSDocument {
33         EvDocument object;
34
35         SpectreDocument *doc;
36         SpectreExporter *exporter;
37 };
38
39 struct _PSDocumentClass {
40         EvDocumentClass parent_class;
41 };
42
43 static void ps_document_file_exporter_iface_init       (EvFileExporterInterface       *iface);
44
45 EV_BACKEND_REGISTER_WITH_CODE (PSDocument, ps_document,
46                          {
47                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
48                                                                  ps_document_file_exporter_iface_init);
49                          });
50
51 /* PSDocument */
52 static void
53 ps_document_init (PSDocument *ps_document)
54 {
55 }
56
57 static void
58 ps_document_dispose (GObject *object)
59 {
60         PSDocument *ps = PS_DOCUMENT (object);
61
62         if (ps->doc) {
63                 spectre_document_free (ps->doc);
64                 ps->doc = NULL;
65         }
66
67         if (ps->exporter) {
68                 spectre_exporter_free (ps->exporter);
69                 ps->exporter = NULL;
70         }
71
72         G_OBJECT_CLASS (ps_document_parent_class)->dispose (object);
73 }
74
75 /* EvDocumentIface */
76 static gboolean
77 ps_document_load (EvDocument *document,
78                   const char *uri,
79                   GError    **error)
80 {
81         PSDocument *ps = PS_DOCUMENT (document);
82         gchar      *filename;
83
84         filename = g_filename_from_uri (uri, NULL, error);
85         if (!filename)
86                 return FALSE;
87         
88         ps->doc = spectre_document_new ();
89
90         spectre_document_load (ps->doc, filename);
91         if (spectre_document_status (ps->doc)) {
92                 gchar *filename_dsp;
93                 
94                 filename_dsp = g_filename_display_name (filename);
95                 g_set_error (error,
96                              G_FILE_ERROR,
97                              G_FILE_ERROR_FAILED,
98                              _("Failed to load document ā€œ%sā€"),
99                              filename_dsp);
100                 g_free (filename_dsp);
101                 g_free (filename);
102
103                 return FALSE;
104         }
105
106         g_free (filename);
107
108         return TRUE;
109 }
110
111 static gboolean
112 ps_document_save (EvDocument *document,
113                   const char *uri,
114                   GError    **error)
115 {
116         PSDocument *ps = PS_DOCUMENT (document);
117         gchar      *filename;
118
119         filename = g_filename_from_uri (uri, NULL, error);
120         if (!filename)
121                 return FALSE;
122
123         spectre_document_save (ps->doc, filename);
124         if (spectre_document_status (ps->doc)) {
125                 gchar *filename_dsp;
126
127                 filename_dsp = g_filename_display_name (filename);
128                 g_set_error (error,
129                              G_FILE_ERROR,
130                              G_FILE_ERROR_FAILED,
131                              _("Failed to save document ā€œ%sā€"),
132                              filename_dsp);
133                 g_free (filename_dsp);
134                 g_free (filename);
135
136                 return FALSE;
137         }
138
139         g_free (filename);
140
141         return TRUE;
142 }
143
144 static int
145 ps_document_get_n_pages (EvDocument *document)
146 {
147         PSDocument *ps = PS_DOCUMENT (document);
148
149         return spectre_document_get_n_pages (ps->doc);
150 }
151
152 static EvPage *
153 ps_document_get_page (EvDocument *document,
154                       gint        index)
155 {
156         PSDocument  *ps = PS_DOCUMENT (document);
157         SpectrePage *ps_page;
158         EvPage      *page;
159
160         ps_page = spectre_document_get_page (ps->doc, index);
161         page = ev_page_new (index);
162         page->backend_page = (EvBackendPage)ps_page;
163         page->backend_destroy_func = (EvBackendPageDestroyFunc)spectre_page_free;
164
165         return page;
166 }
167
168 static gint
169 get_page_rotation (SpectrePage *page)
170 {
171         switch (spectre_page_get_orientation (page)) {
172                 default:
173                 case SPECTRE_ORIENTATION_PORTRAIT:
174                         return 0;
175                 case SPECTRE_ORIENTATION_LANDSCAPE:
176                         return 90;
177                 case SPECTRE_ORIENTATION_REVERSE_PORTRAIT:
178                         return 180;
179                 case SPECTRE_ORIENTATION_REVERSE_LANDSCAPE:
180                         return 270;
181         }
182
183         return 0;
184 }
185
186 static void
187 ps_document_get_page_size (EvDocument *document,
188                            EvPage     *page,
189                            double     *width,
190                            double     *height)
191 {
192         SpectrePage *ps_page;
193         gdouble      page_width, page_height;
194         gint         pwidth, pheight;
195         gint         rotate;
196
197         ps_page = (SpectrePage *)page->backend_page;
198
199         spectre_page_get_size (ps_page, &pwidth, &pheight);
200
201         rotate = get_page_rotation (ps_page);
202         if (rotate == 90 || rotate == 270) {
203                 page_height = pwidth;
204                 page_width = pheight;
205         } else {
206                 page_width = pwidth;
207                 page_height = pheight;
208         }
209
210         if (width) {
211                 *width = page_width;
212         }
213
214         if (height) {
215                 *height = page_height;
216         }
217 }
218
219 static char *
220 ps_document_get_page_label (EvDocument *document,
221                             EvPage     *page)
222 {
223         return g_strdup (spectre_page_get_label ((SpectrePage *)page->backend_page));
224 }
225
226 static EvDocumentInfo *
227 ps_document_get_info (EvDocument *document)
228 {
229         PSDocument     *ps = PS_DOCUMENT (document);
230         EvDocumentInfo *info;
231         const gchar    *creator;
232         SpectrePage    *ps_page;
233         gint            width, height;
234
235         info = g_new0 (EvDocumentInfo, 1);
236         info->fields_mask = EV_DOCUMENT_INFO_TITLE |
237                             EV_DOCUMENT_INFO_FORMAT |
238                             EV_DOCUMENT_INFO_CREATOR |
239                             EV_DOCUMENT_INFO_N_PAGES |
240                             EV_DOCUMENT_INFO_PAPER_SIZE;
241
242         creator = spectre_document_get_creator (ps->doc);
243
244         ps_page = spectre_document_get_page (ps->doc, 0);
245         spectre_page_get_size (ps_page, &width, &height);
246         spectre_page_free (ps_page);
247         
248         info->title = g_strdup (spectre_document_get_title (ps->doc));
249         info->format = g_strdup (spectre_document_get_format (ps->doc));
250         info->creator = g_strdup (creator ? creator : spectre_document_get_for (ps->doc));
251         info->n_pages = spectre_document_get_n_pages (ps->doc);
252         info->paper_width  = width / 72.0f * 25.4f;
253         info->paper_height = height / 72.0f * 25.4f;
254
255         return info;
256 }
257
258 static gboolean
259 ps_document_get_backend_info (EvDocument            *document,
260                               EvDocumentBackendInfo *info)
261 {
262         info->name = "libspectre";
263         info->version = SPECTRE_VERSION_STRING;
264
265         return TRUE;
266 }
267
268 static cairo_surface_t *
269 ps_document_render (EvDocument      *document,
270                     EvRenderContext *rc)
271 {
272         SpectrePage          *ps_page;
273         SpectreRenderContext *src;
274         gint                  width_points;
275         gint                  height_points;
276         gint                  width, height;
277         gint                  swidth, sheight;
278         guchar               *data = NULL;
279         gint                  stride;
280         gint                  rotation;
281         cairo_surface_t      *surface;
282         static const cairo_user_data_key_t key;
283
284         ps_page = (SpectrePage *)rc->page->backend_page;
285         
286         spectre_page_get_size (ps_page, &width_points, &height_points);
287
288         width = (gint) ((width_points * rc->scale) + 0.5);
289         height = (gint) ((height_points * rc->scale) + 0.5);
290         rotation = (rc->rotation + get_page_rotation (ps_page)) % 360;
291
292         src = spectre_render_context_new ();
293         spectre_render_context_set_scale (src,
294                                           (gdouble)width / width_points,
295                                           (gdouble)height / height_points);
296         spectre_render_context_set_rotation (src, rotation);
297         spectre_page_render (ps_page, src, &data, &stride);
298         spectre_render_context_free (src);
299
300         if (!data) {
301                 return NULL;
302         }
303
304         if (spectre_page_status (ps_page)) {
305                 g_warning ("%s", spectre_status_to_string (spectre_page_status (ps_page)));
306                 g_free (data);
307                 
308                 return NULL;
309         }
310
311         if (rotation == 90 || rotation == 270) {
312                 swidth = height;
313                 sheight = width;
314         } else {
315                 swidth = width;
316                 sheight = height;
317         }
318         
319         surface = cairo_image_surface_create_for_data (data,
320                                                        CAIRO_FORMAT_RGB24,
321                                                        swidth, sheight,
322                                                        stride);
323         cairo_surface_set_user_data (surface, &key,
324                                      data, (cairo_destroy_func_t)g_free);
325         return surface;
326 }
327
328 static void
329 ps_document_class_init (PSDocumentClass *klass)
330 {
331         GObjectClass    *object_class = G_OBJECT_CLASS (klass);
332         EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
333
334         object_class->dispose = ps_document_dispose;
335
336         ev_document_class->load = ps_document_load;
337         ev_document_class->save = ps_document_save;
338         ev_document_class->get_n_pages = ps_document_get_n_pages;
339         ev_document_class->get_page = ps_document_get_page;
340         ev_document_class->get_page_size = ps_document_get_page_size;
341         ev_document_class->get_page_label = ps_document_get_page_label;
342         ev_document_class->get_info = ps_document_get_info;
343         ev_document_class->get_backend_info = ps_document_get_backend_info;
344         ev_document_class->render = ps_document_render;
345 }
346
347 /* EvFileExporterIface */
348 static void
349 ps_document_file_exporter_begin (EvFileExporter        *exporter,
350                                  EvFileExporterContext *fc)
351 {
352         PSDocument *ps = PS_DOCUMENT (exporter);
353
354         if (ps->exporter)
355                 spectre_exporter_free (ps->exporter);
356
357         switch (fc->format) {
358                 case EV_FILE_FORMAT_PS:
359                         ps->exporter =
360                                 spectre_exporter_new (ps->doc,
361                                                       SPECTRE_EXPORTER_FORMAT_PS);
362                         break;
363                 case EV_FILE_FORMAT_PDF:
364                         ps->exporter =
365                                 spectre_exporter_new (ps->doc,
366                                                       SPECTRE_EXPORTER_FORMAT_PDF);
367                         break;
368                 default:
369                         g_assert_not_reached ();
370         }
371
372         spectre_exporter_begin (ps->exporter, fc->filename);
373 }
374
375 static void
376 ps_document_file_exporter_do_page (EvFileExporter  *exporter,
377                                    EvRenderContext *rc)
378 {
379         PSDocument *ps = PS_DOCUMENT (exporter);
380
381         spectre_exporter_do_page (ps->exporter, rc->page->index);
382 }
383
384 static void
385 ps_document_file_exporter_end (EvFileExporter *exporter)
386 {
387         PSDocument *ps = PS_DOCUMENT (exporter);
388
389         spectre_exporter_end (ps->exporter);
390 }
391
392 static EvFileExporterCapabilities
393 ps_document_file_exporter_get_capabilities (EvFileExporter *exporter)
394 {
395         return  EV_FILE_EXPORTER_CAN_PAGE_SET |
396                 EV_FILE_EXPORTER_CAN_COPIES |
397                 EV_FILE_EXPORTER_CAN_COLLATE |
398                 EV_FILE_EXPORTER_CAN_REVERSE |
399                 EV_FILE_EXPORTER_CAN_GENERATE_PS |
400                 EV_FILE_EXPORTER_CAN_GENERATE_PDF;
401 }
402
403 static void
404 ps_document_file_exporter_iface_init (EvFileExporterInterface *iface)
405 {
406         iface->begin = ps_document_file_exporter_begin;
407         iface->do_page = ps_document_file_exporter_do_page;
408         iface->end = ps_document_file_exporter_end;
409         iface->get_capabilities = ps_document_file_exporter_get_capabilities;
410 }