2 * image/x-pdf BonoboObject.
5 * Michael Meeks <michael@imaginator.com>
14 #define GString G_String
16 #include <libgnorba/gnorba.h>
17 #include <bonobo/gnome-bonobo.h>
22 #include "parseargs.h"
34 #include "GOutputDev.h"
35 #include "PSOutputDev.h"
36 #include "TextOutputDev.h"
40 #include "BonoboStream.h"
44 GBool printCommands = gFalse;
50 * Number of servers running on the system
51 * when the count reaches zero, we unregister from the
52 * Name Server and we shut down.
54 static int embeddable_servers = 0;
57 * Our embeddable factory
59 static GnomeEmbeddableFactory *factory;
66 GnomeEmbeddable *embeddable;
69 XRef *xref; /* Ugly global XRef hack fix */
70 BonoboStream *pdf_stream;
71 GNOME_Stream bonobo_stream;
84 GtkWidget *drawing_area;
95 static void realize_drawing_areas (bed_t *bed);
96 static void setup_pixmap (bed_t *doc, view_data_t *view, GdkWindow *window);
100 redraw_view (view_data_t *view_data, GdkRectangle *rect)
103 bed_t *bed = view_data->bed;
105 g_return_if_fail (view_data->pixmap != NULL);
108 * Do not draw outside the region that we know how to display
110 if (rect->x > view_data->w)
113 if (rect->y > view_data->h)
117 * Clip the draw region
119 if (rect->x + rect->width > view_data->w)
120 rect->width = view_data->w - rect->x;
122 if (rect->y + rect->height > view_data->h)
123 rect->height = view_data->h - rect->y;
126 * Draw the exposed region.
128 gdk_draw_pixmap (view_data->drawing_area->window,
129 view_data->drawing_area->style->white_gc,
138 configure_size (view_data_t *view_data)
140 gtk_widget_set_usize (
141 view_data->drawing_area,
147 render_page (view_data_t *view_data)
149 setup_pixmap (view_data->bed, view_data,
151 xref = view_data->bed->xref; /* Ugly global XRef hack fix */
152 view_data->out->startDoc();
153 view_data->bed->pdf->displayPage(view_data->out,
154 view_data->page, view_data->zoom,
156 view_data->bed->xref = xref;
161 redraw_view_all (view_data_t *view_data)
164 g_return_if_fail (view_data != NULL);
167 printf ("Redraw view of page %d\n", view_data->page);
169 render_page (view_data);
172 rect.width = view_data->w;
173 rect.height = view_data->h;
174 redraw_view (view_data, &rect);
175 gtk_widget_queue_draw (GTK_WIDGET (view_data->drawing_area));
179 redraw_all (bed_t *bed)
183 for (l = bed->views; l; l = l->next) {
185 view_data_t *view_data = (view_data_t *)l->data;
186 redraw_view_all (view_data);
191 save_image (GnomePersistStream *ps, GNOME_Stream stream, void *data)
193 g_warning ("Unimplemented");
201 setup_size (bed_t *doc, view_data_t *view)
206 if (!doc || !view || !doc->pdf) {
211 w = (int)((doc->pdf->getPageWidth (view->page) * view->zoom) / 72.0);
212 h = (int)((doc->pdf->getPageHeight (view->page) * view->zoom) / 72.0);
213 if (view->w == w && view->h == h)
224 bed_free_data (bed_t *bed)
226 g_return_if_fail (bed != NULL);
232 delete (bed->pdf_stream);
233 bed->pdf_stream = NULL;
235 if (bed->bonobo_stream) {
236 CORBA_exception_init (&ev);
237 CORBA_Object_release (bed->bonobo_stream, &ev);
238 bed->bonobo_stream = NULL;
239 CORBA_exception_free (&ev);
244 * Loads a PDF from a GNOME_Stream
247 load_image_from_stream (GnomePersistStream *ps, GNOME_Stream stream, void *data)
249 bed_t *bed = (bed_t *)data;
251 GNOME_Stream_iobuf *buffer;
258 if (bed->pdf || bed->pdf_stream ||
259 bed->bonobo_stream) {
260 g_warning ("Won't overwrite pre-existing stream: you wierdo");
264 /* We need this for later */
265 CORBA_Object_duplicate (stream, &ev);
266 bed->bonobo_stream = stream;
267 g_return_val_if_fail (ev._major == CORBA_NO_EXCEPTION, 0);
270 printf ("Loading PDF from persiststream\n");
273 bed->pdf_stream = new BonoboStream (stream, 0, -1, &obj);
274 bed->pdf = new PDFDoc (bed->pdf_stream);
275 bed->xref = xref; /* Ugly global XRef hack fix */
279 printf ("Done load\n");
281 if (!(bed->pdf->isOk())) {
282 g_warning ("Duff pdf data\n");
285 if (!bed->pdf->getCatalog()) {
286 g_warning ("Duff pdf catalog\n");
290 realize_drawing_areas (bed);
298 destroy_view (GnomeView *view, view_data_t *view_data)
300 view_data->bed->views = g_list_remove (view_data->bed->views, view_data);
301 gtk_object_unref (GTK_OBJECT (view_data->drawing_area));
307 destroy_embed (GnomeView *view, bed_t *bed)
309 CORBA_Environment ev;
311 printf ("Destroying embedded component\n");
314 destroy_view (NULL, (view_data_t *)bed->views->data);
319 embeddable_servers--;
321 if (embeddable_servers == 0){
322 gnome_object_unref (GNOME_OBJECT (factory));
328 setup_pixmap (bed_t *doc, view_data_t *view_data, GdkWindow *window)
330 GdkGCValues gcValues;
334 GdkPixmap *pixmap = NULL;
336 g_return_if_fail (doc != NULL);
337 g_return_if_fail (doc->pdf != NULL);
338 g_return_if_fail (view_data != NULL);
342 if (setup_size (doc, view_data) &&
345 printf ("No need to re-init output device\n");
353 pixmap = gdk_pixmap_new (window, w, h, -1);
355 gdk_color_white (gtk_widget_get_default_colormap(), &view_data->paper);
356 view_data->out = new GOutputDev (pixmap, view_data->paper, window);
358 gdk_color_white (gtk_widget_get_default_colormap (), &gcValues.foreground);
359 gdk_color_black (gtk_widget_get_default_colormap (), &gcValues.background);
360 gcValues.line_width = 1;
361 gcValues.line_style = GDK_LINE_SOLID;
362 strokeGC = gdk_gc_new_with_values (
364 (enum GdkGCValuesMask)(GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_LINE_WIDTH | GDK_GC_LINE_STYLE));
366 gdk_draw_rectangle (pixmap, strokeGC,
370 view_data->pixmap = pixmap;
371 configure_size (view_data);
375 view_is_good (view_data_t *view_data)
379 !view_data->bed->pdf)
386 first_page (view_data_t *view_data)
388 g_return_val_if_fail (view_is_good (view_data), FALSE);
389 if (view_data->page != 1) {
397 last_page (view_data_t *view_data)
399 g_return_val_if_fail (view_is_good (view_data), FALSE);
400 if (view_data->page < view_data->bed->pdf->getNumPages()) {
401 view_data->page = view_data->bed->pdf->getNumPages();
408 next_page (view_data_t *view_data)
410 g_return_val_if_fail (view_is_good (view_data), FALSE);
411 if (view_data->page < view_data->bed->pdf->getNumPages()) {
419 prev_page (view_data_t *view_data)
421 g_return_val_if_fail (view_is_good (view_data), FALSE);
422 if (view_data->page > 1) {
430 page_first_cb (GnomeUIHandler *uih, void *data, char *path)
432 first_page ((view_data_t *)data);
433 redraw_view_all ((view_data_t *)data);
437 page_next_cb (GnomeUIHandler *uih, void *data, char *path)
439 next_page ((view_data_t *)data);
440 redraw_view_all ((view_data_t *)data);
444 page_prev_cb (GnomeUIHandler *uih, void *data, char *path)
446 prev_page ((view_data_t *)data);
447 redraw_view_all ((view_data_t *)data);
451 page_last_cb (GnomeUIHandler *uih, void *data, char *path)
453 last_page ((view_data_t *)data);
454 redraw_view_all ((view_data_t *)data);
459 view_create_menus (view_data_t *view_data)
461 GNOME_UIHandler remote_uih;
462 GnomeView *view = view_data->view;
465 uih = gnome_view_get_ui_handler (view);
466 remote_uih = gnome_view_get_remote_ui_handler (view);
468 if (remote_uih == CORBA_OBJECT_NIL) {
469 g_warning ("server has no UI hander");
473 gnome_ui_handler_set_container (uih, remote_uih);
475 gnome_ui_handler_menu_new_subtree (uih, "/Page",
477 N_("Set the currently displayed page"),
479 GNOME_UI_HANDLER_PIXMAP_NONE, NULL,
480 0, (GdkModifierType)0);
482 gnome_ui_handler_menu_new_item (uih, "/Page/First",
483 N_("First"), N_("View the first page"), -1,
484 GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0,
485 (GdkModifierType)0, page_first_cb, (gpointer)view_data);
487 gnome_ui_handler_menu_new_item (uih, "/Page/Prev",
488 N_("Previous"), N_("View the previous page"), -1,
489 GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0,
490 (GdkModifierType)0, page_prev_cb, (gpointer)view_data);
492 gnome_ui_handler_menu_new_item (uih, "/Page/Next",
493 N_("Next"), N_("View the next page"), -1,
494 GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0,
495 (GdkModifierType)0, page_next_cb, (gpointer)view_data);
497 gnome_ui_handler_menu_new_item (uih, "/Page/Last",
498 N_("Last"), N_("View the last page"), -1,
499 GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0,
500 (GdkModifierType)0, page_last_cb, (gpointer)view_data);
502 gnome_ui_handler_toolbar_new_item (uih, "/First",
503 N_("First"), N_("View the first page"), -1,
504 GNOME_UI_HANDLER_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_FIRST,
505 0, (GdkModifierType)0, page_first_cb, (gpointer)view_data);
506 gnome_ui_handler_toolbar_new_item (uih, "/Prev",
507 N_("Previous"), N_("View the previous page"), -1,
508 GNOME_UI_HANDLER_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_BACK,
509 0, (GdkModifierType)0, page_prev_cb, (gpointer)view_data);
510 gnome_ui_handler_toolbar_new_item (uih, "/Next",
511 N_("Next"), N_("View the next page"), -1,
512 GNOME_UI_HANDLER_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_FORWARD,
513 0, (GdkModifierType)0, page_next_cb, (gpointer)view_data);
514 gnome_ui_handler_toolbar_new_item (uih, "/Last",
515 N_("Last"), N_("View the last page"), -1,
516 GNOME_UI_HANDLER_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_LAST,
517 0, (GdkModifierType)0, page_last_cb, (gpointer)view_data);
521 * When this view is deactivated, we must remove our menu items.
524 view_remove_menus (view_data_t *view_data)
526 GnomeView *view = view_data->view;
529 uih = gnome_view_get_ui_handler (view);
531 gnome_ui_handler_unset_container (uih);
537 drawing_area_realize (GtkWidget *drawing_area, view_data_t *view_data)
539 g_return_if_fail (view_data != NULL);
540 g_return_if_fail (drawing_area != NULL);
542 view_data->win = gtk_widget_get_parent_window (drawing_area);
546 drawing_area_exposed (GtkWidget *widget, GdkEventExpose *event, view_data_t *view_data)
549 !view_data->bed->pdf)
552 redraw_view (view_data, &event->area);
558 view_activate (GnomeView *view, gboolean activate, gpointer data)
560 view_data_t *view_data = (view_data_t *) data;
561 g_return_if_fail (view != NULL);
562 g_return_if_fail (view_data != NULL);
564 gnome_view_activate_notify (view, activate);
567 printf ("View change activation to %d\n", activate);
570 * If we were just activated, we merge in our menu entries.
571 * If we were just deactivated, we remove them.
574 view_create_menus (view_data);
576 view_remove_menus (view_data);
580 view_size_query (GnomeView *view, int *desired_width, int *desired_height,
583 view_data_t *view_data = (view_data_t *) data;
585 g_return_if_fail (view_data != NULL);
587 *desired_width = view_data->w;
588 *desired_height = view_data->h;
592 view_zoom_query (GnomeView *view, gdouble new_zoom, gpointer data)
594 view_data_t *view_data = (view_data_t *) data;
596 g_return_if_fail (view_data != NULL);
598 /* The rational behind this is that the _entire_ page is allocated
599 regardless of viewport size, so you _really_ don't want it too big ! */
600 g_return_if_fail (new_zoom > 10.0);
601 g_return_if_fail (new_zoom < 180.0);
603 view_data->zoom = new_zoom;
604 redraw_view_all (view_data);
608 realize_drawing_areas (bed_t *bed)
612 for (l = bed->views; l; l = l->next) {
613 view_data_t *view_data = (view_data_t *)l->data;
614 g_return_if_fail (view_data->win);
615 render_page (view_data);
616 configure_size (view_data);
621 view_switch_page (GnomeView *view, const char *verb_name, void *user_data)
623 view_data_t *view_data = (view_data_t *) user_data;
625 gboolean changed = FALSE;
627 if (!g_strcasecmp (verb_name, "firstpage")) {
628 changed = first_page (view_data);
629 } else if (!g_strcasecmp (verb_name, "prevpage")) {
630 changed = prev_page (view_data);
631 } else if (!g_strcasecmp (verb_name, "nextpage")) {
632 changed = next_page (view_data);
633 } else if (!g_strcasecmp (verb_name, "lastpage")) {
634 changed = last_page (view_data);
636 g_warning ("Unknown verb");
639 render_page (view_data);
640 redraw_view (view_data, &rect);
641 gtk_widget_queue_draw (GTK_WIDGET (view_data->drawing_area));
647 view_factory (GnomeEmbeddable *embeddable,
648 const GNOME_ViewFrame view_frame,
653 bed_t *bed = (bed_t *)data;
654 view_data_t *view_data = g_new (view_data_t, 1);
657 printf ("Created new bonobo object view %p\n", view_data);
660 view_data->scale = 1.0;
661 view_data->bed = bed;
662 view_data->drawing_area = gtk_drawing_area_new ();
663 view_data->pixmap = NULL;
664 view_data->win = NULL;
665 view_data->out = NULL;
668 view_data->zoom = 43.0; /* 86.0; Must be small for demos :-) */
672 GTK_OBJECT (view_data->drawing_area),
674 GTK_SIGNAL_FUNC (drawing_area_realize), view_data);
677 GTK_OBJECT (view_data->drawing_area),
679 GTK_SIGNAL_FUNC (drawing_area_exposed), view_data);
681 gtk_widget_show (view_data->drawing_area);
683 setup_size (bed, view_data);
685 view = gnome_view_new (view_data->drawing_area);
686 view_data->view = view;
689 GTK_OBJECT (view), "destroy",
690 GTK_SIGNAL_FUNC (destroy_view), view_data);
693 uih = gnome_ui_handler_new ();
694 gnome_view_set_ui_handler (view, uih);
696 gtk_signal_connect (GTK_OBJECT (view), "view_activate",
697 GTK_SIGNAL_FUNC (view_activate), view_data);
699 gtk_signal_connect (GTK_OBJECT (view), "size_query",
700 GTK_SIGNAL_FUNC (view_size_query), view_data);
702 gtk_signal_connect (GTK_OBJECT (view), "set_zoom_factor",
703 GTK_SIGNAL_FUNC (view_zoom_query), view_data);
705 bed->views = g_list_prepend (bed->views, view_data);
708 gnome_view_register_verb (view, "FirstPage",
709 view_switch_page, view_data);
710 gnome_view_register_verb (view, "PrevPage",
711 view_switch_page, view_data);
712 gnome_view_register_verb (view, "NextPage",
713 view_switch_page, view_data);
714 gnome_view_register_verb (view, "LastPage",
715 view_switch_page, view_data);
721 embeddable_factory (GnomeEmbeddableFactory *This, void *data)
723 GnomeEmbeddable *embeddable;
724 GnomePersistStream *stream;
725 bed_t *bed = (bed_t *)data;
727 bed = g_new0 (bed_t, 1);
732 printf ("Created new bonobo object %p\n", bed);
735 * Creates the BonoboObject server
737 embeddable = gnome_embeddable_new (view_factory, bed);
738 if (embeddable == NULL){
746 * Interface GNOME::PersistStream
748 stream = gnome_persist_stream_new ("bonobo-object:image-x-pdf",
749 load_image_from_stream,
752 if (stream == NULL) {
753 gtk_object_unref (GTK_OBJECT (embeddable));
758 bed->embeddable = embeddable;
761 * Bind the interfaces
763 gnome_object_add_interface (GNOME_OBJECT (embeddable),
764 GNOME_OBJECT (stream));
766 GTK_OBJECT (embeddable), "destroy",
767 GTK_SIGNAL_FUNC (destroy_embed), bed);
769 embeddable_servers++;
771 /* Setup some verbs */
772 gnome_embeddable_add_verb (embeddable,
775 _("goto the first page"));
776 gnome_embeddable_add_verb (embeddable,
779 _("goto the previous page"));
780 gnome_embeddable_add_verb (embeddable,
783 _("goto the next page"));
784 gnome_embeddable_add_verb (embeddable,
787 _("goto the last page"));
789 return (GnomeObject *) embeddable;
793 init_bonobo_image_x_pdf_factory (void)
795 factory = gnome_embeddable_factory_new (
796 "bonobo-object-factory:image-x-pdf",
797 embeddable_factory, NULL);
806 init_server_factory (int argc, char **argv)
808 gnome_CORBA_init_with_popt_table (
809 "bonobo-image-x-pdf", "1.0",
810 &argc, argv, NULL, 0, NULL, GNORBA_INIT_SERVER_FUNC, &ev);
812 if (bonobo_init (CORBA_OBJECT_NIL, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL) == FALSE)
813 g_error (_("I could not initialize Bonobo"));
817 main (int argc, char *argv [])
819 CORBA_exception_init (&ev);
821 init_server_factory (argc, argv);
822 if (!init_bonobo_image_x_pdf_factory ()) {
823 fprintf (stderr, "Could not initialize the Bonobo PDF factory\n"
824 "probably a server is already running?");
830 initParams (xpdfConfigFile); /* Init font path */
832 gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
833 gtk_widget_set_default_visual (gdk_rgb_get_visual ());
838 CORBA_exception_free (&ev);