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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20 #include <glib/gi18n.h>
22 #include <libspectre/spectre.h>
24 #include "ev-spectre.h"
26 #include "ev-file-exporter.h"
27 #include "ev-document-thumbnails.h"
28 #include "ev-document-misc.h"
34 SpectreExporter *exporter;
37 struct _PSDocumentClass {
38 GObjectClass parent_class;
41 static void ps_document_document_iface_init (EvDocumentIface *iface);
42 static void ps_document_file_exporter_iface_init (EvFileExporterIface *iface);
43 static void ps_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
45 G_DEFINE_TYPE_WITH_CODE (PSDocument, ps_document, G_TYPE_OBJECT,
47 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
48 ps_document_document_iface_init);
49 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
50 ps_document_document_thumbnails_iface_init);
51 G_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);
80 ps_document_class_init (PSDocumentClass *klass)
82 GObjectClass *object_class;
84 object_class = G_OBJECT_CLASS (klass);
86 object_class->dispose = ps_document_dispose;
91 ps_document_load (EvDocument *document,
95 PSDocument *ps = PS_DOCUMENT (document);
98 filename = g_filename_from_uri (uri, NULL, error);
102 ps->doc = spectre_document_new ();
104 spectre_document_load (ps->doc, filename);
105 if (spectre_document_status (ps->doc)) {
108 filename_dsp = g_filename_display_name (filename);
112 _("Failed to load document ā%sā"),
114 g_free (filename_dsp);
126 ps_document_save (EvDocument *document,
130 PSDocument *ps = PS_DOCUMENT (document);
133 filename = g_filename_from_uri (uri, NULL, error);
137 spectre_document_save (ps->doc, filename);
138 if (spectre_document_status (ps->doc)) {
141 filename_dsp = g_filename_display_name (filename);
145 _("Failed to save document ā%sā"),
147 g_free (filename_dsp);
159 ps_document_get_n_pages (EvDocument *document)
161 PSDocument *ps = PS_DOCUMENT (document);
163 return spectre_document_get_n_pages (ps->doc);
167 get_page_rotation (SpectrePage *page)
169 switch (spectre_page_get_orientation (page)) {
171 case SPECTRE_ORIENTATION_PORTRAIT:
173 case SPECTRE_ORIENTATION_LANDSCAPE:
175 case SPECTRE_ORIENTATION_REVERSE_PORTRAIT:
177 case SPECTRE_ORIENTATION_REVERSE_LANDSCAPE:
185 ps_document_get_page_size (EvDocument *document,
190 PSDocument *ps = PS_DOCUMENT (document);
191 SpectrePage *ps_page;
192 gdouble page_width, page_height;
193 gint pwidth, pheight;
196 ps_page = spectre_document_get_page (ps->doc, page);
197 spectre_page_get_size (ps_page, &pwidth, &pheight);
199 rotate = get_page_rotation (ps_page);
200 if (rotate == 90 || rotate == 270) {
201 page_height = pwidth;
202 page_width = pheight;
205 page_height = pheight;
208 spectre_page_free (ps_page);
215 *height = page_height;
220 ps_document_get_page_label (EvDocument *document,
223 PSDocument *ps = PS_DOCUMENT (document);
224 SpectrePage *ps_page;
227 ps_page = spectre_document_get_page (ps->doc, page);
228 label = g_strdup (spectre_page_get_label (ps_page));
229 spectre_page_free (ps_page);
234 static EvDocumentInfo *
235 ps_document_get_info (EvDocument *document)
237 PSDocument *ps = PS_DOCUMENT (document);
238 EvDocumentInfo *info;
239 const gchar *creator;
240 SpectrePage *ps_page;
243 info = g_new0 (EvDocumentInfo, 1);
244 info->fields_mask = EV_DOCUMENT_INFO_TITLE |
245 EV_DOCUMENT_INFO_FORMAT |
246 EV_DOCUMENT_INFO_CREATOR |
247 EV_DOCUMENT_INFO_N_PAGES |
248 EV_DOCUMENT_INFO_PAPER_SIZE;
250 creator = spectre_document_get_creator (ps->doc);
252 ps_page = spectre_document_get_page (ps->doc, 0);
253 spectre_page_get_size (ps_page, &width, &height);
254 spectre_page_free (ps_page);
256 info->title = g_strdup (spectre_document_get_title (ps->doc));
257 info->format = g_strdup (spectre_document_get_format (ps->doc));
258 info->creator = g_strdup (creator ? creator : spectre_document_get_for (ps->doc));
259 info->n_pages = spectre_document_get_n_pages (ps->doc);
260 info->paper_width = width / 72.0f * 25.4f;
261 info->paper_height = height / 72.0f * 25.4f;
266 static cairo_surface_t *
267 ps_document_render (EvDocument *document,
270 PSDocument *ps = PS_DOCUMENT (document);
271 SpectrePage *ps_page;
272 SpectreRenderContext *src;
276 gint swidth, sheight;
280 cairo_surface_t *surface;
281 static const cairo_user_data_key_t key;
283 ps_page = spectre_document_get_page (ps->doc, rc->page);
284 spectre_page_get_size (ps_page, &width_points, &height_points);
286 width = (gint) ((width_points * rc->scale) + 0.5);
287 height = (gint) ((height_points * rc->scale) + 0.5);
288 rotation = (rc->rotation + get_page_rotation (ps_page)) % 360;
290 src = spectre_render_context_new ();
291 spectre_render_context_set_page_size (src, width, height);
292 spectre_render_context_set_rotation (src, rotation);
293 spectre_page_render (ps_page, src, &data, &stride);
294 spectre_render_context_free (src);
297 spectre_page_free (ps_page);
301 if (spectre_page_status (ps_page)) {
302 g_warning (spectre_status_to_string (spectre_page_status (ps_page)));
304 spectre_page_free (ps_page);
309 spectre_page_free (ps_page);
311 if (rotation == 90 || rotation == 270) {
319 surface = cairo_image_surface_create_for_data (data,
323 cairo_surface_set_user_data (surface, &key,
324 data, (cairo_destroy_func_t)g_free);
329 ps_document_document_iface_init (EvDocumentIface *iface)
331 iface->load = ps_document_load;
332 iface->save = ps_document_save;
333 iface->get_n_pages = ps_document_get_n_pages;
334 iface->get_page_size = ps_document_get_page_size;
335 iface->get_page_label = ps_document_get_page_label;
336 iface->get_info = ps_document_get_info;
337 iface->render = ps_document_render;
340 /* EvDocumentThumbnailsIface */
342 ps_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
346 PSDocument *ps = PS_DOCUMENT (document_thumbnails);
347 cairo_surface_t *surface;
348 GdkPixbuf *pixbuf = NULL;
350 surface = ps_document_render (EV_DOCUMENT (ps), rc);
351 pixbuf = ev_document_misc_pixbuf_from_surface (surface);
352 cairo_surface_destroy (surface);
355 GdkPixbuf *border_pixbuf;
357 border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
358 g_object_unref (pixbuf);
359 pixbuf = border_pixbuf;
366 ps_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
371 PSDocument *ps = PS_DOCUMENT (document_thumbnails);
372 gdouble page_width, page_height;
374 ps_document_get_page_size (EV_DOCUMENT (ps),
376 &page_width, &page_height);
378 if (rc->rotation == 90 || rc->rotation == 270) {
379 *width = (gint) (page_height * rc->scale);
380 *height = (gint) (page_width * rc->scale);
382 *width = (gint) (page_width * rc->scale);
383 *height = (gint) (page_height * rc->scale);
388 ps_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
390 iface->get_thumbnail = ps_document_thumbnails_get_thumbnail;
391 iface->get_dimensions = ps_document_thumbnails_get_dimensions;
394 /* EvFileExporterIface */
396 ps_document_file_exporter_begin (EvFileExporter *exporter,
397 EvFileExporterContext *fc)
399 PSDocument *ps = PS_DOCUMENT (exporter);
402 spectre_exporter_free (ps->exporter);
404 switch (fc->format) {
405 case EV_FILE_FORMAT_PS:
407 spectre_exporter_new (ps->doc,
408 SPECTRE_EXPORTER_FORMAT_PS);
410 case EV_FILE_FORMAT_PDF:
412 spectre_exporter_new (ps->doc,
413 SPECTRE_EXPORTER_FORMAT_PDF);
416 g_assert_not_reached ();
419 spectre_exporter_begin (ps->exporter, fc->filename);
423 ps_document_file_exporter_do_page (EvFileExporter *exporter,
426 PSDocument *ps = PS_DOCUMENT (exporter);
428 spectre_exporter_do_page (ps->exporter, rc->page);
432 ps_document_file_exporter_end (EvFileExporter *exporter)
434 PSDocument *ps = PS_DOCUMENT (exporter);
436 spectre_exporter_end (ps->exporter);
439 static EvFileExporterCapabilities
440 ps_document_file_exporter_get_capabilities (EvFileExporter *exporter)
442 return EV_FILE_EXPORTER_CAN_PAGE_SET |
443 EV_FILE_EXPORTER_CAN_COPIES |
444 EV_FILE_EXPORTER_CAN_COLLATE |
445 EV_FILE_EXPORTER_CAN_REVERSE |
446 EV_FILE_EXPORTER_CAN_GENERATE_PS |
447 EV_FILE_EXPORTER_CAN_GENERATE_PDF;
451 ps_document_file_exporter_iface_init (EvFileExporterIface *iface)
453 iface->begin = ps_document_file_exporter_begin;
454 iface->do_page = ps_document_file_exporter_do_page;
455 iface->end = ps_document_file_exporter_end;
456 iface->get_capabilities = ps_document_file_exporter_get_capabilities;