]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/bonobo-image-x-pdf.cc
embryonic PDF viewer as a Bonobo container...
[evince.git] / pdf / xpdf / bonobo-image-x-pdf.cc
1 /*
2  * image/x-pdf BonoboObject.
3  *
4  * Author:
5  *   Michael Meeks <michael@imaginator.com>
6  *
7  */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stddef.h>
11 #include <string.h>
12 #include <config.h>
13 extern "C" {
14 #define GString G_String
15 #include <gnome.h>
16 #include <libgnorba/gnorba.h>
17 #include <bonobo/gnome-bonobo.h>
18 #undef  GString 
19 }
20 #include "gtypes.h"
21 #include "GString.h"
22 #include "parseargs.h"
23 #include "gfile.h"
24 #include "gmem.h"
25 #include "Object.h"
26 #include "Stream.h"
27 #include "Array.h"
28 #include "Dict.h"
29 #include "XRef.h"
30 #include "Catalog.h"
31 #include "Page.h"
32 #include "Link.h"
33 #include "PDFDoc.h"
34 #include "GOutputDev.h"
35 #include "PSOutputDev.h"
36 #include "TextOutputDev.h"
37 #include "Params.h"
38 #include "Error.h"
39 #include "config.h"
40
41 GBool printCommands = gFalse;
42
43 CORBA_Environment ev;
44 CORBA_ORB orb;
45
46 /*
47  * BonoboObject data
48  */
49 typedef struct {
50   GnomeEmbeddable *bonobo_object;
51
52   PDFDoc       *pdf;
53   GNOME_Stream  stream; /* To free it later */
54
55   GList *views;
56 } bonobo_object_data_t;
57
58 /*
59  * View data
60  */
61 typedef struct {
62   double                scale;
63   bonobo_object_data_t *bonobo_object_data;
64   GtkWidget            *drawing_area;
65   GdkPixmap            *pixmap;
66   GOutputDev           *out;
67   GdkColor              paper;
68   gint                  w, h;
69   gdouble               zoom;
70   gint                  page;
71 } view_data_t;
72
73 static void
74 redraw_view (view_data_t *view_data, GdkRectangle *rect)
75 {
76   gint width, height;
77   bonobo_object_data_t *bonobo_object_data = view_data->bonobo_object_data;
78
79   g_return_if_fail (view_data->pixmap != NULL);
80
81   /*
82    * Do not draw outside the region that we know how to display
83    */
84   if (rect->x > view_data->w)
85     return;
86   
87   if (rect->y > view_data->h)
88     return;
89
90   /*
91    * Clip the draw region
92    */
93   if (rect->x + rect->width > view_data->w)
94     rect->width = view_data->w - rect->x;
95   
96   if (rect->y + rect->height > view_data->h)
97     rect->height = view_data->h - rect->y;
98   
99   /*
100    * Draw the exposed region.
101    */
102   gdk_draw_pixmap (view_data->drawing_area->window,
103                    view_data->drawing_area->style->white_gc,
104                    view_data->pixmap,
105                    rect->x, rect->y,
106                    rect->x, rect->y,
107                    rect->width,
108                    rect->height);
109 }
110
111 static void
112 configure_size (view_data_t *view_data, GdkRectangle *rect)
113 {
114 /*      ArtPixBuf *pixbuf;
115         
116         if (view_data->scaled)
117                 pixbuf = view_data->scaled;
118         else
119                 pixbuf = view_data->bonobo_object_data->image;
120 */
121   gtk_widget_set_usize (
122     view_data->drawing_area,
123     view_data->w,
124     view_data->h);
125   
126   rect->x = 0;
127   rect->y = 0;
128   rect->width = view_data->w;
129   rect->height = view_data->h;
130 }
131
132 static void
133 redraw_all (bonobo_object_data_t *bonobo_object_data)
134 {
135         GList *l;
136         
137         for (l = bonobo_object_data->views; l; l = l->next){
138                 GdkRectangle rect;
139                 view_data_t *view_data = (view_data_t *)l->data;
140
141                 configure_size (view_data, &rect);
142                 
143                 redraw_view (view_data, &rect);
144         }
145 }
146
147 static int
148 save_image (GnomePersistStream *ps, GNOME_Stream stream, void *data)
149 {
150   g_warning ("Unimplemented");
151   return -1;
152 }
153
154 static void
155 setup_size (bonobo_object_data_t *doc, view_data_t *view)
156 {
157   if (!doc || !view || !doc->pdf) {
158     view->w = 320;
159     view->h = 200;
160     return;
161   }
162   view->w = (int)((doc->pdf->getPageWidth  (view->page) * view->zoom) / 72.0);
163   view->h = (int)((doc->pdf->getPageHeight (view->page) * view->zoom) / 72.0);
164 }
165
166 /*
167  * Loads a PDF from a GNOME_Stream
168  */
169 static int
170 load_image_from_stream (GnomePersistStream *ps, GNOME_Stream stream, void *data)
171 {
172         bonobo_object_data_t *bonobo_object_data = (bonobo_object_data_t *)data;
173         CORBA_long length;
174         GNOME_Stream_iobuf *buffer;
175         guint lp;
176         #define CHUNK 512
177         FILE *hack;
178         char *name;
179
180         if (bonobo_object_data->pdf ||
181             bonobo_object_data->stream) {
182           g_warning ("Won't overwrite pre-existing stream: you wierdo");
183           return 0;
184         }
185
186         /* We need this for later */
187         CORBA_Object_duplicate (stream, &ev);
188         g_return_val_if_fail (ev._major == CORBA_NO_EXCEPTION, 0);
189
190 /*      buffer = GNOME_Stream_iobuf__alloc ();
191         length = GNOME_Stream_length (stream, &ev);
192
193         name = tempnam (NULL, "xpdf-hack");
194         if (!name)
195           return -1;
196         hack = fopen (name, "wb+");
197         if (!hack)
198           return -1;
199
200         while (length > 0) {
201           guint getlen;
202           if (length > 128)
203             getlen = 128;
204           else
205             getlen = length;
206           GNOME_Stream_read (stream, getlen, &buffer, &ev);
207           fwrite (buffer->_buffer, 1, buffer->_length, hack);
208           length -= buffer->_length;
209         }
210
211         fclose (hack);
212
213         CORBA_free (buffer);*/
214
215         printf ("Loading PDF from persiststream\n");
216         bonobo_object_data->stream = stream;
217         bonobo_object_data->pdf = new PDFDoc (stream, new GString ("Bonobo.pdf"));
218         printf ("Done load\n");
219         if (!(bonobo_object_data->pdf->isOk())) {
220           g_warning ("Duff pdf data\n");
221           delete bonobo_object_data->pdf;
222           bonobo_object_data->pdf = NULL;
223         }
224         if (!bonobo_object_data->pdf->getCatalog()) {
225           g_warning ("Duff pdf catalog\n");
226           delete bonobo_object_data->pdf;
227           bonobo_object_data->pdf = NULL;
228         }
229
230         redraw_all (bonobo_object_data);
231         return 0;
232 }
233
234 extern "C" {
235   static void
236   destroy_view (GnomeView *view, view_data_t *view_data)
237   {
238     view_data->bonobo_object_data->views = g_list_remove (view_data->bonobo_object_data->views, view_data);
239     gtk_object_unref (GTK_OBJECT (view_data->drawing_area));
240     
241     g_free (view_data);
242   }
243 }
244
245 static GdkPixmap *
246 setup_pixmap (bonobo_object_data_t *doc, view_data_t *view, GdkWindow *window)
247 {
248     GdkGCValues  gcValues;
249     GdkGC       *strokeGC;
250     PDFDoc      *pdf;
251     int          w, h;
252     GdkPixmap   *pixmap = NULL;
253     
254     g_return_val_if_fail (doc != NULL, NULL);
255     g_return_val_if_fail (view != NULL, NULL);
256     g_return_val_if_fail (doc->pdf != NULL, NULL);
257     
258     pdf = doc->pdf;
259
260     setup_size (doc, view);
261
262     w = view->w;
263     h = view->h;
264    
265     pixmap = gdk_pixmap_new (window, w, h, -1);
266     
267     gdk_color_white (gtk_widget_get_default_colormap(), &view->paper);
268     view->out    = new GOutputDev (pixmap, view->paper, window);
269     
270     gdk_color_white (gtk_widget_get_default_colormap (), &gcValues.foreground);
271     gdk_color_black (gtk_widget_get_default_colormap (), &gcValues.background);
272     gcValues.line_width = 1;
273     gcValues.line_style = GDK_LINE_SOLID;
274     strokeGC = gdk_gc_new_with_values (
275       pixmap, &gcValues, 
276       (enum GdkGCValuesMask)(GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_LINE_WIDTH | GDK_GC_LINE_STYLE));
277     
278     gdk_draw_rectangle (pixmap, strokeGC,
279                         TRUE, 0, 0,
280                         w, h);
281     
282     return pixmap;
283 }
284
285 extern "C" {
286   static int
287   drawing_area_exposed (GtkWidget *widget, GdkEventExpose *event, view_data_t *view_data)
288   {
289     if (!view_data ||
290         !view_data->bonobo_object_data->pdf)
291       return TRUE;
292     
293 /* Hoisted from view_factory: ugly */
294     if (!view_data->pixmap) {
295       GdkWindow *win = gtk_widget_get_parent_window (widget);
296       GdkRectangle tmp;
297       
298       g_return_val_if_fail (win, TRUE);
299       
300       view_data->pixmap = setup_pixmap (view_data->bonobo_object_data, view_data, win);
301       view_data->bonobo_object_data->pdf->displayPage(view_data->out, view_data->page, view_data->zoom, 0, gTrue);
302
303       configure_size (view_data, &tmp);
304     }
305     
306     redraw_view (view_data, &event->area);
307     
308     return TRUE;
309   }
310 }
311
312 static GnomeView *
313 view_factory (GnomeEmbeddable *bonobo_object,
314               const GNOME_ViewFrame view_frame,
315               void *data)
316 {
317         GnomeView *view;
318         bonobo_object_data_t *bonobo_object_data = (bonobo_object_data_t *)data;
319         view_data_t *view_data = g_new (view_data_t, 1);
320
321         printf ("Created new bonobo object view %p\n", view_data);
322         
323         view_data->scale  = 1.0;
324         view_data->bonobo_object_data = bonobo_object_data;
325         view_data->drawing_area = gtk_drawing_area_new ();
326         view_data->pixmap = NULL;
327         view_data->out    = NULL;
328         view_data->w      = 320;
329         view_data->h      = 320;
330         view_data->zoom   = 24.0; /* 86.0; Must be small for demos :-) */
331         view_data->page   = 1;
332
333         gtk_signal_connect (
334                 GTK_OBJECT (view_data->drawing_area),
335                 "expose_event",
336                 GTK_SIGNAL_FUNC (drawing_area_exposed), view_data);
337
338         gtk_widget_show (view_data->drawing_area);
339
340         setup_size (bonobo_object_data, view_data);
341
342         view = gnome_view_new (view_data->drawing_area);
343
344         gtk_signal_connect (
345                 GTK_OBJECT (view), "destroy",
346                 GTK_SIGNAL_FUNC (destroy_view), view_data);
347
348         bonobo_object_data->views = g_list_prepend (bonobo_object_data->views,
349                                                 view_data);
350
351         return view;
352 }
353
354 static GnomeObject *
355 bonobo_object_factory (GnomeEmbeddableFactory *This, void *data)
356 {
357         GnomeEmbeddable *bonobo_object;
358         GnomePersistStream *stream;
359         bonobo_object_data_t *bonobo_object_data = (bonobo_object_data_t *)data;
360
361         bonobo_object_data = g_new0 (bonobo_object_data_t, 1);
362         if (!bonobo_object_data)
363                 return NULL;
364
365         printf ("Created new bonobo object %p\n", bonobo_object_data);
366         /*
367          * Creates the BonoboObject server
368          */
369         bonobo_object = gnome_embeddable_new (view_factory, bonobo_object_data);
370         if (bonobo_object == NULL){
371                 g_free (bonobo_object_data);
372                 return NULL;
373         }
374
375         bonobo_object_data->pdf = NULL;
376
377         /*
378          * Interface GNOME::PersistStream 
379          */
380         stream = gnome_persist_stream_new ("bonobo-object:image-x-pdf",
381                                            load_image_from_stream,
382                                            save_image,
383                                            bonobo_object_data);
384         if (stream == NULL){
385                 gtk_object_unref (GTK_OBJECT (bonobo_object));
386                 g_free (bonobo_object_data);
387                 return NULL;
388         }
389
390         bonobo_object_data->bonobo_object = bonobo_object;
391
392         /*
393          * Bind the interfaces
394          */
395         gnome_object_add_interface (GNOME_OBJECT (bonobo_object),
396                                     GNOME_OBJECT (stream));
397         return (GnomeObject *) bonobo_object;
398 }
399
400 static void
401 init_bonobo_image_x_png_factory (void)
402 {
403         GnomeEmbeddableFactory *factory;
404         
405         factory = gnome_embeddable_factory_new (
406                 "bonobo-object-factory:image-x-pdf",
407                 bonobo_object_factory, NULL);
408 }
409
410 static void
411 init_server_factory (int argc, char **argv)
412 {
413         gnome_CORBA_init_with_popt_table (
414                 "bonobo-image-x-pdf", "1.0",
415                 &argc, argv, NULL, 0, NULL, GNORBA_INIT_SERVER_FUNC, &ev);
416
417         if (bonobo_init (CORBA_OBJECT_NIL, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL) == FALSE)
418                 g_error (_("I could not initialize Bonobo"));
419 }
420
421 int
422 main (int argc, char *argv [])
423 {
424         CORBA_exception_init (&ev);
425
426         init_server_factory (argc, argv);
427         init_bonobo_image_x_png_factory ();
428
429         errorInit();
430
431         initParams (xpdfConfigFile); /* Init font path */
432
433         gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
434         gtk_widget_set_default_visual (gdk_rgb_get_visual ());
435         gtk_main ();
436         
437         CORBA_exception_free (&ev);
438
439         return 0;
440 }
441