1 /* this file is part of evince, a gnome document viewer
3 * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
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.
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.
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.
23 #include <glib/gi18n-lib.h>
25 #include <libspectre/spectre.h>
27 #include "ev-spectre.h"
29 #include "ev-file-exporter.h"
30 #include "ev-document-thumbnails.h"
31 #include "ev-document-misc.h"
37 SpectreExporter *exporter;
40 struct _PSDocumentClass {
41 EvDocumentClass parent_class;
44 static void ps_document_file_exporter_iface_init (EvFileExporterInterface *iface);
45 static void ps_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface);
47 EV_BACKEND_REGISTER_WITH_CODE (PSDocument, ps_document,
49 EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
50 ps_document_document_thumbnails_iface_init);
51 EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
52 ps_document_file_exporter_iface_init);
57 ps_document_init (PSDocument *ps_document)
62 ps_document_dispose (GObject *object)
64 PSDocument *ps = PS_DOCUMENT (object);
67 spectre_document_free (ps->doc);
72 spectre_exporter_free (ps->exporter);
76 G_OBJECT_CLASS (ps_document_parent_class)->dispose (object);
81 ps_document_load (EvDocument *document,
85 PSDocument *ps = PS_DOCUMENT (document);
88 filename = g_filename_from_uri (uri, NULL, error);
92 ps->doc = spectre_document_new ();
94 spectre_document_load (ps->doc, filename);
95 if (spectre_document_status (ps->doc)) {
98 filename_dsp = g_filename_display_name (filename);
102 _("Failed to load document ā%sā"),
104 g_free (filename_dsp);
116 ps_document_save (EvDocument *document,
120 PSDocument *ps = PS_DOCUMENT (document);
123 filename = g_filename_from_uri (uri, NULL, error);
127 spectre_document_save (ps->doc, filename);
128 if (spectre_document_status (ps->doc)) {
131 filename_dsp = g_filename_display_name (filename);
135 _("Failed to save document ā%sā"),
137 g_free (filename_dsp);
149 ps_document_get_n_pages (EvDocument *document)
151 PSDocument *ps = PS_DOCUMENT (document);
153 return spectre_document_get_n_pages (ps->doc);
157 ps_document_get_page (EvDocument *document,
160 PSDocument *ps = PS_DOCUMENT (document);
161 SpectrePage *ps_page;
164 ps_page = spectre_document_get_page (ps->doc, index);
165 page = ev_page_new (index);
166 page->backend_page = (EvBackendPage)ps_page;
167 page->backend_destroy_func = (EvBackendPageDestroyFunc)spectre_page_free;
173 get_page_rotation (SpectrePage *page)
175 switch (spectre_page_get_orientation (page)) {
177 case SPECTRE_ORIENTATION_PORTRAIT:
179 case SPECTRE_ORIENTATION_LANDSCAPE:
181 case SPECTRE_ORIENTATION_REVERSE_PORTRAIT:
183 case SPECTRE_ORIENTATION_REVERSE_LANDSCAPE:
191 ps_document_get_page_size (EvDocument *document,
196 SpectrePage *ps_page;
197 gdouble page_width, page_height;
198 gint pwidth, pheight;
201 ps_page = (SpectrePage *)page->backend_page;
203 spectre_page_get_size (ps_page, &pwidth, &pheight);
205 rotate = get_page_rotation (ps_page);
206 if (rotate == 90 || rotate == 270) {
207 page_height = pwidth;
208 page_width = pheight;
211 page_height = pheight;
219 *height = page_height;
224 ps_document_get_page_label (EvDocument *document,
227 return g_strdup (spectre_page_get_label ((SpectrePage *)page->backend_page));
230 static EvDocumentInfo *
231 ps_document_get_info (EvDocument *document)
233 PSDocument *ps = PS_DOCUMENT (document);
234 EvDocumentInfo *info;
235 const gchar *creator;
236 SpectrePage *ps_page;
239 info = g_new0 (EvDocumentInfo, 1);
240 info->fields_mask = EV_DOCUMENT_INFO_TITLE |
241 EV_DOCUMENT_INFO_FORMAT |
242 EV_DOCUMENT_INFO_CREATOR |
243 EV_DOCUMENT_INFO_N_PAGES |
244 EV_DOCUMENT_INFO_PAPER_SIZE;
246 creator = spectre_document_get_creator (ps->doc);
248 ps_page = spectre_document_get_page (ps->doc, 0);
249 spectre_page_get_size (ps_page, &width, &height);
250 spectre_page_free (ps_page);
252 info->title = g_strdup (spectre_document_get_title (ps->doc));
253 info->format = g_strdup (spectre_document_get_format (ps->doc));
254 info->creator = g_strdup (creator ? creator : spectre_document_get_for (ps->doc));
255 info->n_pages = spectre_document_get_n_pages (ps->doc);
256 info->paper_width = width / 72.0f * 25.4f;
257 info->paper_height = height / 72.0f * 25.4f;
263 ps_document_get_backend_info (EvDocument *document,
264 EvDocumentBackendInfo *info)
266 info->name = "libspectre";
267 info->version = SPECTRE_VERSION_STRING;
272 static cairo_surface_t *
273 ps_document_render (EvDocument *document,
276 SpectrePage *ps_page;
277 SpectreRenderContext *src;
281 gint swidth, sheight;
285 cairo_surface_t *surface;
286 static const cairo_user_data_key_t key;
288 ps_page = (SpectrePage *)rc->page->backend_page;
290 spectre_page_get_size (ps_page, &width_points, &height_points);
292 width = (gint) ((width_points * rc->scale) + 0.5);
293 height = (gint) ((height_points * rc->scale) + 0.5);
294 rotation = (rc->rotation + get_page_rotation (ps_page)) % 360;
296 src = spectre_render_context_new ();
297 spectre_render_context_set_scale (src,
298 (gdouble)width / width_points,
299 (gdouble)height / height_points);
300 spectre_render_context_set_rotation (src, rotation);
301 spectre_page_render (ps_page, src, &data, &stride);
302 spectre_render_context_free (src);
308 if (spectre_page_status (ps_page)) {
309 g_warning ("%s", spectre_status_to_string (spectre_page_status (ps_page)));
315 if (rotation == 90 || rotation == 270) {
323 surface = cairo_image_surface_create_for_data (data,
327 cairo_surface_set_user_data (surface, &key,
328 data, (cairo_destroy_func_t)g_free);
333 ps_document_class_init (PSDocumentClass *klass)
335 GObjectClass *object_class = G_OBJECT_CLASS (klass);
336 EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
338 object_class->dispose = ps_document_dispose;
340 ev_document_class->load = ps_document_load;
341 ev_document_class->save = ps_document_save;
342 ev_document_class->get_n_pages = ps_document_get_n_pages;
343 ev_document_class->get_page = ps_document_get_page;
344 ev_document_class->get_page_size = ps_document_get_page_size;
345 ev_document_class->get_page_label = ps_document_get_page_label;
346 ev_document_class->get_info = ps_document_get_info;
347 ev_document_class->get_backend_info = ps_document_get_backend_info;
348 ev_document_class->render = ps_document_render;
351 /* EvDocumentThumbnailsIface */
353 ps_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
357 PSDocument *ps = PS_DOCUMENT (document_thumbnails);
358 cairo_surface_t *surface;
359 GdkPixbuf *pixbuf = NULL;
361 surface = ps_document_render (EV_DOCUMENT (ps), rc);
363 g_warning ("Error rendering thumbnail");
367 pixbuf = ev_document_misc_pixbuf_from_surface (surface);
368 cairo_surface_destroy (surface);
371 GdkPixbuf *border_pixbuf;
373 border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
374 g_object_unref (pixbuf);
375 pixbuf = border_pixbuf;
382 ps_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
387 PSDocument *ps = PS_DOCUMENT (document_thumbnails);
388 gdouble page_width, page_height;
390 ps_document_get_page_size (EV_DOCUMENT (ps),
392 &page_width, &page_height);
394 if (rc->rotation == 90 || rc->rotation == 270) {
395 *width = (gint) (page_height * rc->scale);
396 *height = (gint) (page_width * rc->scale);
398 *width = (gint) (page_width * rc->scale);
399 *height = (gint) (page_height * rc->scale);
404 ps_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface)
406 iface->get_thumbnail = ps_document_thumbnails_get_thumbnail;
407 iface->get_dimensions = ps_document_thumbnails_get_dimensions;
410 /* EvFileExporterIface */
412 ps_document_file_exporter_begin (EvFileExporter *exporter,
413 EvFileExporterContext *fc)
415 PSDocument *ps = PS_DOCUMENT (exporter);
418 spectre_exporter_free (ps->exporter);
420 switch (fc->format) {
421 case EV_FILE_FORMAT_PS:
423 spectre_exporter_new (ps->doc,
424 SPECTRE_EXPORTER_FORMAT_PS);
426 case EV_FILE_FORMAT_PDF:
428 spectre_exporter_new (ps->doc,
429 SPECTRE_EXPORTER_FORMAT_PDF);
432 g_assert_not_reached ();
435 spectre_exporter_begin (ps->exporter, fc->filename);
439 ps_document_file_exporter_do_page (EvFileExporter *exporter,
442 PSDocument *ps = PS_DOCUMENT (exporter);
444 spectre_exporter_do_page (ps->exporter, rc->page->index);
448 ps_document_file_exporter_end (EvFileExporter *exporter)
450 PSDocument *ps = PS_DOCUMENT (exporter);
452 spectre_exporter_end (ps->exporter);
455 static EvFileExporterCapabilities
456 ps_document_file_exporter_get_capabilities (EvFileExporter *exporter)
458 return EV_FILE_EXPORTER_CAN_PAGE_SET |
459 EV_FILE_EXPORTER_CAN_COPIES |
460 EV_FILE_EXPORTER_CAN_COLLATE |
461 EV_FILE_EXPORTER_CAN_REVERSE |
462 EV_FILE_EXPORTER_CAN_GENERATE_PS |
463 EV_FILE_EXPORTER_CAN_GENERATE_PDF;
467 ps_document_file_exporter_iface_init (EvFileExporterInterface *iface)
469 iface->begin = ps_document_file_exporter_begin;
470 iface->do_page = ps_document_file_exporter_do_page;
471 iface->end = ps_document_file_exporter_end;
472 iface->get_capabilities = ps_document_file_exporter_get_capabilities;