//========================================================================
//
// GDKSplashOutputDev.cc
//
// Copyright 2003 Glyph & Cog, LLC
// Copyright 2004 Red Hat, Inc. (GDK port)
//
//========================================================================

#include <config.h>

#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif

#include <goo/gmem.h>
#include <splash/SplashTypes.h>
#include <splash/SplashBitmap.h>
#include "Object.h"
#include "GfxState.h"

#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "CairoOutputDev.h"
#include <cairo-xlib.h>
#include <X11/Xutil.h>

#include "PDFDoc.h"
#include "GlobalParams.h"
#include "ErrorCodes.h"
#include <gtk/gtk.h>

class GDKCairoOutputDev: public CairoOutputDev {
public:

  GDKCairoOutputDev(GdkDrawable *drawable,
		    void (*redrawCbkA)(void *data),
		    void *redrawCbkDataA);
  
  virtual ~GDKCairoOutputDev();

  virtual void GDKCairoOutputDev::createCairo(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;
  createCairo (NULL);
}

GDKCairoOutputDev::~GDKCairoOutputDev() {
}

void
GDKCairoOutputDev::createCairo(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);
    cairo = cairo_create (surface);
    cairo_surface_destroy (surface);
  }
}

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, 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");
  globalParams->setupBaseFonts(NULL);
  
  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;
}
