]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/pdf-document.cc
a25f663030b57926fa6dc02978b9b8c52100d1d1
[evince.git] / pdf / xpdf / pdf-document.cc
1 /* pdfdocument.h: Implementation of EvDocument for PDF
2  * Copyright (C) 2004, Red Hat, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18
19 #include "gpdf-g-switch.h"
20 #include "pdf-document.h"
21 #include "gpdf-g-switch.h"
22
23 #include "GlobalParams.h"
24 #include "GDKSplashOutputDev.h"
25 #include "PDFDoc.h"
26
27 typedef struct _PdfDocumentClass PdfDocumentClass;
28
29 #define PDF_DOCUMENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), PDF_TYPE_DOCUMENT, PdfDocumentClass))
30 #define PDF_IS_DOCUMENT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), PDF_TYPE_DOCUMENT))
31 #define PDF_DOCUMENT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), PDF_TYPE_DOCUMENT, PdfDocumentClass))
32
33 struct _PdfDocumentClass
34 {
35         GObjectClass parent_class;
36 };
37
38 struct _PdfDocument
39 {
40         GObject parent_instance;
41
42         int page;
43         int page_x_offset;
44         int page_y_offset;
45         double scale;
46         GdkDrawable *target;
47
48         GDKSplashOutputDev *out;
49         PDFDoc *doc;
50
51         gboolean page_valid;
52 };
53
54 static void pdf_document_document_iface_init (EvDocumentIface *iface);
55
56 G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
57                          { G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
58                                                   pdf_document_document_iface_init) });
59
60 static gboolean
61 document_validate_page (PdfDocument *pdf_document)
62 {
63         if (!pdf_document->page_valid) {
64                 pdf_document->doc->displayPage (pdf_document->out, pdf_document->page,
65                                                 72 * pdf_document->scale,
66                                                 72 * pdf_document->scale,
67                                                 0, gTrue, gTrue);
68                 
69                 pdf_document->page_valid = TRUE;
70         }
71 }
72
73 static gboolean
74 pdf_document_load (EvDocument  *document,
75                    const char  *uri,
76                    GError     **error)
77 {
78         PdfDocument *pdf_document = PDF_DOCUMENT (document);
79         PDFDoc *newDoc;
80         int err;
81         char *filename;
82         GString *filename_g;
83         
84         if (!globalParams) {
85                 globalParams = new GlobalParams("/etc/xpdfrc");
86                 globalParams->setupBaseFonts(NULL);
87         }
88
89         filename = g_filename_from_uri (uri, NULL, error);
90         if (!filename)
91                 return FALSE;
92
93         filename_g = new GString (filename);
94         g_free (filename);
95
96         // open the PDF file, assumes ownership of filename_g
97         newDoc = new PDFDoc(filename_g, 0, 0);
98
99         if (!newDoc->isOk()) {
100                 err = newDoc->getErrorCode();
101                 delete newDoc;
102
103                 /* FIXME: Add a real error enum to EvDocument */
104                 g_set_error (error, G_FILE_ERROR,
105                              G_FILE_ERROR_FAILED,
106                              "Failed to load document (error %d) '%s'\n",
107                              err,
108                              uri);
109                 
110                 return FALSE;
111         }
112
113         if (pdf_document->doc)
114                 delete pdf_document->doc;
115         pdf_document->doc = newDoc;
116
117         pdf_document->page = 1;
118
119         if (pdf_document->out)
120                 pdf_document->out->startDoc(pdf_document->doc->getXRef());
121
122         pdf_document->page_valid = FALSE;
123         
124         return TRUE;
125 }
126
127 static int
128 pdf_document_get_n_pages (EvDocument  *document)
129 {
130         PdfDocument *pdf_document = PDF_DOCUMENT (document);
131
132         if (pdf_document->doc)
133                 return pdf_document->doc->getNumPages();
134         else
135                 return 1;
136 }
137
138 static void
139 pdf_document_set_page (EvDocument  *document,
140                        int          page)
141 {
142         PdfDocument *pdf_document = PDF_DOCUMENT (document);
143
144         page = CLAMP (page, 1, ev_document_get_n_pages (document));
145
146         if (page != pdf_document->page) {
147                 pdf_document->page = page;
148                 pdf_document->page_valid = FALSE;
149         }
150
151 }
152
153 static int
154 pdf_document_get_page (EvDocument  *document)
155 {
156         PdfDocument *pdf_document = PDF_DOCUMENT (document);
157
158         return pdf_document->page;
159 }
160
161 static void
162 redraw_callback (void *data)
163 {
164         /* Need to hook up through a EvDocument callback? */
165 }
166
167 static void
168 pdf_document_set_target (EvDocument  *document,
169                          GdkDrawable *target)
170 {
171         PdfDocument *pdf_document = PDF_DOCUMENT (document);
172         
173         if (pdf_document->target != target) {
174                 if (pdf_document->target)
175                         g_object_unref (pdf_document->target);
176                 
177                 pdf_document->target = target;
178
179                 if (pdf_document->target)
180                         g_object_ref (pdf_document->target);
181
182                 if (pdf_document->out) {
183                         delete pdf_document->out;
184                         pdf_document->out = NULL;
185                 }
186
187                 if (pdf_document->target) {
188                         pdf_document->out = new GDKSplashOutputDev (gdk_drawable_get_screen (pdf_document->target),
189                                                          redraw_callback, (void*) document);
190
191                         if (pdf_document->doc)
192                                 pdf_document->out->startDoc(pdf_document->doc->getXRef());
193
194                 }
195
196                 pdf_document->page_valid = FALSE;
197         }
198 }
199
200 static void
201 pdf_document_set_scale (EvDocument  *document,
202                         double       scale)
203 {
204         PdfDocument *pdf_document = PDF_DOCUMENT (document);
205         
206         if (pdf_document->scale != scale) {
207                 pdf_document->scale = scale;
208                 pdf_document->page_valid = FALSE;
209         }
210 }
211
212 static void
213 pdf_document_set_page_offset (EvDocument  *document,
214                               int          x,
215                               int          y)
216 {
217         PdfDocument *pdf_document = PDF_DOCUMENT (document);
218         
219         pdf_document->page_x_offset = x;
220         pdf_document->page_y_offset = y;
221 }
222
223 static void
224 pdf_document_get_page_size (EvDocument   *document,
225                             int          *width,
226                             int          *height)
227 {
228         PdfDocument *pdf_document = PDF_DOCUMENT (document);
229
230         if (document_validate_page (pdf_document)) {
231                 if (width)
232                         *width = pdf_document->out->getBitmapWidth();
233                 if (height)
234                         *height = pdf_document->out->getBitmapHeight();
235         } else {
236                 if (width)
237                         *width = 1;
238                 if (height)
239                         *height = 1;
240         }
241 }
242
243 static void
244 pdf_document_render (EvDocument  *document,
245                      int          clip_x,
246                      int          clip_y,
247                      int          clip_width,
248                      int          clip_height)
249 {
250         PdfDocument *pdf_document = PDF_DOCUMENT (document);
251         GdkRectangle page;
252         GdkRectangle draw;
253
254         if (!document_validate_page (pdf_document) || !pdf_document->target)
255                 return;
256         
257         page.x = pdf_document->page_x_offset;
258         page.y = pdf_document->page_y_offset;
259         page.width = pdf_document->out->getBitmapWidth();
260         page.height = pdf_document->out->getBitmapHeight();
261
262         draw.x = clip_x;
263         draw.y = clip_y;
264         draw.width = clip_width;
265         draw.height = clip_height;
266         
267         if (gdk_rectangle_intersect (&page, &draw, &draw))
268                 pdf_document->out->redraw (draw.x - page.x, draw.y - page.y,
269                                            pdf_document->target,
270                                            draw.x, draw.y,
271                                            draw.width, draw.height);
272 }
273
274 static void
275 pdf_document_finalize (GObject *object)
276 {
277         PdfDocument *pdf_document = PDF_DOCUMENT (object);
278
279         if (pdf_document->target)
280                 g_object_unref (pdf_document->target);
281
282         if (pdf_document->out)
283                 delete pdf_document->out;
284         if (pdf_document->doc)
285                 delete pdf_document->doc;
286
287 }
288
289 static void
290 pdf_document_class_init (PdfDocumentClass *klass)
291 {
292         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
293   
294         gobject_class->finalize = pdf_document_finalize;
295 }
296
297 static void
298 pdf_document_document_iface_init (EvDocumentIface *iface)
299 {
300         iface->load = pdf_document_load;
301         iface->get_n_pages = pdf_document_get_n_pages;
302         iface->set_page = pdf_document_set_page;
303         iface->get_page = pdf_document_get_page;
304         iface->set_scale = pdf_document_set_scale;
305         iface->set_target = pdf_document_set_target;
306         iface->set_page_offset = pdf_document_set_page_offset;
307         iface->get_page_size = pdf_document_get_page_size;
308         iface->render = pdf_document_render;
309 }
310
311 static void
312 pdf_document_init (PdfDocument *pdf_document)
313 {
314         pdf_document->page = 1;
315         pdf_document->page_x_offset = 0;
316         pdf_document->page_y_offset = 0;
317         pdf_document->scale = 1.;
318         
319         pdf_document->page_valid = FALSE;
320 }
321