//======================================================================== // // GDKSplashOutputDev.cc // // Copyright 2003 Glyph & Cog, LLC // Copyright 2004 Red Hat, Inc. (GDK port) // //======================================================================== #include #ifdef USE_GCC_PRAGMAS #pragma implementation #endif #include #include #include #include "Object.h" #include "GfxState.h" #include #include #include "CairoOutputDev.h" #include #include #include "PDFDoc.h" #include "GlobalParams.h" #include "ErrorCodes.h" #include class GDKCairoOutputDev: public CairoOutputDev { public: GDKCairoOutputDev(GdkDrawable *drawable, void (*redrawCbkA)(void *data), void *redrawCbkDataA); virtual ~GDKCairoOutputDev(); // Start a page. virtual void startPage(int pageNum, GfxState *state); //----- special access // Clear out the document (used when displaying an empty window). void clear(); // Copy the rectangle (srcX, srcY, width, height) to (destX, destY) // in destDC. void redraw(int srcX, int srcY, GdkDrawable *drawable, int destX, int destY, int width, int height); int getPixmapWidth (void) { return pixmapWidth; } int getPixmapHeight (void) { return pixmapHeight; } private: int incrementalUpdate; void (*redrawCbk)(void *data); void *redrawCbkData; int pixmapWidth, pixmapHeight; GdkPixmap *pixmap, *drawable; }; GDKCairoOutputDev::GDKCairoOutputDev(GdkDrawable *drawableA, void (*redrawCbkA)(void *data), void *redrawCbkDataA): CairoOutputDev() { drawable = drawableA; redrawCbk = redrawCbkA; redrawCbkData = redrawCbkDataA; pixmap = NULL; } GDKCairoOutputDev::~GDKCairoOutputDev() { } void GDKCairoOutputDev::startPage(int pageNum, GfxState *state) { Display *display; Drawable xid; GdkGC *gc; GdkColor white; cairo_surface_t *surface; int w, h; w = state ? (int)(state->getPageWidth() + 0.5) : 1; h = state ? (int)(state->getPageHeight() + 0.5) : 1; if (!pixmap || pixmapWidth != w || h != pixmapHeight != h) { if (pixmap) g_object_unref (G_OBJECT (pixmap)); pixmap = gdk_pixmap_new (drawable, w, h, -1); pixmapWidth = w; pixmapHeight = h; gc = gdk_gc_new (pixmap); white.red = 0xffff; white.green = 0xffff; white.blue = 0xffff; gdk_gc_set_rgb_fg_color (gc, &white); gdk_draw_rectangle (pixmap, gc, TRUE, 0, 0, w, h); g_object_unref (G_OBJECT (gc)); } if (pixmap) { display = gdk_x11_drawable_get_xdisplay (pixmap); xid = gdk_x11_drawable_get_xid (pixmap); surface = cairo_xlib_surface_create(display, xid, DefaultVisual(display, DefaultScreen(display)), w, h); setSurface(surface); cairo_surface_destroy (surface); } CairoOutputDev::startPage(pageNum, state); } void GDKCairoOutputDev::redraw(int srcX, int srcY, GdkDrawable *drawable, int destX, int destY, int width, int height) { GdkGC *gc; gc = gdk_gc_new (drawable); gdk_draw_drawable (drawable, gc, pixmap, srcX, srcY, destX, destY, width, height); g_object_unref (gc); } typedef struct { GtkWidget *window; GtkWidget *sw; GtkWidget *drawing_area; GDKCairoOutputDev *out; PDFDoc *doc; } View; static void drawing_area_expose (GtkWidget *drawing_area, GdkEventExpose *event, void *data) { View *v = (View*) data; GdkRectangle document; GdkRectangle draw; gdk_window_clear (drawing_area->window); document.x = 0; document.y = 0; document.width = v->out->getPixmapWidth(); document.height = v->out->getPixmapHeight(); if (gdk_rectangle_intersect (&document, &event->area, &draw)) { v->out->redraw (draw.x, draw.y, drawing_area->window, draw.x, draw.y, draw.width, draw.height); } } static int view_load (View *v, const char *filename) { PDFDoc *newDoc; int err; GooString *filename_g; int w, h; filename_g = new GooString (filename); // open the PDF file newDoc = new PDFDoc(filename_g, 0, 0); delete filename_g; if (!newDoc->isOk()) { err = newDoc->getErrorCode(); delete newDoc; return err; } if (v->doc) delete v->doc; v->doc = newDoc; v->out->startDoc(v->doc->getXRef()); v->doc->displayPage (v->out, 1, 72, 72, 0, gFalse, gTrue, gTrue); w = v->out->getPixmapWidth(); h = v->out->getPixmapHeight(); gtk_widget_set_size_request (v->drawing_area, w, h); return errNone; } static void view_show (View *v) { gtk_widget_show (v->window); } static void redraw_callback (void *data) { View *v = (View*) data; gtk_widget_queue_draw (v->drawing_area); } static View* view_new (void) { View *v; GtkWidget *window; GtkWidget *drawing_area; GtkWidget *sw; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); drawing_area = gtk_drawing_area_new (); sw = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (window), sw); gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), drawing_area); gtk_widget_show_all (sw); gtk_widget_realize (window); v = g_new0 (View, 1); v->window = window; v->drawing_area = drawing_area; v->sw = sw; v->out = new GDKCairoOutputDev (window->window, redraw_callback, (void*) v); v->doc = 0; g_signal_connect (drawing_area, "expose_event", G_CALLBACK (drawing_area_expose), (void*) v); return v; } int main (int argc, char *argv []) { View *v; int i; gtk_init (&argc, &argv); globalParams = new GlobalParams("/etc/xpdfrc"); if (argc == 1) { fprintf (stderr, "usage: %s PDF-FILES...\n", argv[0]); return -1; } i = 1; while (i < argc) { int err; v = view_new (); err = view_load (v, argv[i]); if (err != errNone) g_printerr ("Error loading document!\n"); view_show (v); ++i; } gtk_main (); delete globalParams; return 0; }