1 //========================================================================
2 //
3 // GDKSplashOutputDev.cc
4 //
5 // Copyright 2003 Glyph & Cog, LLC
6 // Copyright 2004 Red Hat, Inc. (GDK port)
7 //
8 //========================================================================
9 
10 #include <config.h>
11 
12 #ifdef USE_GCC_PRAGMAS
13 #pragma implementation
14 #endif
15 
16 #include <goo/gmem.h>
17 #include <splash/SplashTypes.h>
18 #include <splash/SplashBitmap.h>
19 #include "Object.h"
20 #include "SplashOutputDev.h"
21 #include "GfxState.h"
22 
23 #include <gdk/gdk.h>
24 
25 #include "PDFDoc.h"
26 #include "GlobalParams.h"
27 #include "ErrorCodes.h"
28 #include <gtk/gtk.h>
29 
30 //------------------------------------------------------------------------
31 
32 #define xOutMaxRGBCube 6	// max size of RGB color cube
33 
34 //------------------------------------------------------------------------
35 // GDKSplashOutputDev
36 //------------------------------------------------------------------------
37 
38 class GDKSplashOutputDev: public SplashOutputDev {
39 public:
40 
41   GDKSplashOutputDev(GdkScreen *screen,
42                      void (*redrawCbkA)(void *data),
43                      void *redrawCbkDataA, SplashColor sc);
44 
45   virtual ~GDKSplashOutputDev();
46 
47   //----- initialization and control
48 
49   // End a page.
50   virtual void endPage();
51 
52   // Dump page contents to display.
53   virtual void dump();
54 
55   //----- update text state
56   virtual void updateFont(GfxState *state);
57 
58   //----- special access
59 
60   // Clear out the document (used when displaying an empty window).
61   void clear();
62 
63   // Copy the rectangle (srcX, srcY, width, height) to (destX, destY)
64   // in destDC.
65   void redraw(int srcX, int srcY,
66               GdkDrawable *drawable,
67 	      int destX, int destY,
68 	      int width, int height);
69 
70 private:
71 
72   int incrementalUpdate;
73   void (*redrawCbk)(void *data);
74   void *redrawCbkData;
75 };
76 
77 //------------------------------------------------------------------------
78 // Constants and macros
79 //------------------------------------------------------------------------
80 
81 #define xoutRound(x) ((int)(x + 0.5))
82 
83 //------------------------------------------------------------------------
84 // GDKSplashOutputDev
85 //------------------------------------------------------------------------
86 
GDKSplashOutputDev(GdkScreen * screen,void (* redrawCbkA)(void * data),void * redrawCbkDataA,SplashColor sc)87 GDKSplashOutputDev::GDKSplashOutputDev(GdkScreen *screen,
88                                        void (*redrawCbkA)(void *data),
89                                        void *redrawCbkDataA, SplashColor sc):
90   SplashOutputDev(splashModeRGB8, 4, gFalse, sc),
91   incrementalUpdate (1)
92 {
93   redrawCbk = redrawCbkA;
94   redrawCbkData = redrawCbkDataA;
95 }
96 
~GDKSplashOutputDev()97 GDKSplashOutputDev::~GDKSplashOutputDev() {
98 }
99 
clear()100 void GDKSplashOutputDev::clear() {
101   startDoc(NULL);
102   startPage(0, NULL);
103 }
104 
endPage()105 void GDKSplashOutputDev::endPage() {
106   SplashOutputDev::endPage();
107   if (!incrementalUpdate) {
108     (*redrawCbk)(redrawCbkData);
109   }
110 }
111 
dump()112 void GDKSplashOutputDev::dump() {
113   if (incrementalUpdate && redrawCbk) {
114     (*redrawCbk)(redrawCbkData);
115   }
116 }
117 
updateFont(GfxState * state)118 void GDKSplashOutputDev::updateFont(GfxState *state) {
119   SplashOutputDev::updateFont(state);
120 }
121 
redraw(int srcX,int srcY,GdkDrawable * drawable,int destX,int destY,int width,int height)122 void GDKSplashOutputDev::redraw(int srcX, int srcY,
123                                 GdkDrawable *drawable,
124                                 int destX, int destY,
125                                 int width, int height) {
126   GdkGC *gc;
127   int gdk_rowstride;
128 
129   gdk_rowstride = getBitmap()->getRowSize();
130   gc = gdk_gc_new (drawable);
131 
132   gdk_draw_rgb_image (drawable, gc,
133                       destX, destY,
134                       width, height,
135                       GDK_RGB_DITHER_NORMAL,
136                       getBitmap()->getDataPtr() + srcY * gdk_rowstride + srcX * 3,
137                       gdk_rowstride);
138 
139   g_object_unref (gc);
140 }
141 
142 
143 typedef struct
144 {
145   GtkWidget *window;
146   GtkWidget *sw;
147   GtkWidget *drawing_area;
148   GDKSplashOutputDev *out;
149   PDFDoc *doc;
150 } View;
151 
152 static void
drawing_area_expose(GtkWidget * drawing_area,GdkEventExpose * event,void * data)153 drawing_area_expose (GtkWidget      *drawing_area,
154                      GdkEventExpose *event,
155                      void           *data)
156 {
157   View *v = (View*) data;
158   GdkRectangle document;
159   GdkRectangle draw;
160 
161   gdk_window_clear (drawing_area->window);
162 
163   document.x = 0;
164   document.y = 0;
165   document.width = v->out->getBitmapWidth();
166   document.height = v->out->getBitmapHeight();
167 
168   if (gdk_rectangle_intersect (&document, &event->area, &draw))
169     {
170       v->out->redraw (draw.x, draw.y,
171                       drawing_area->window,
172                       draw.x, draw.y,
173                       draw.width, draw.height);
174     }
175 }
176 
177 static int
view_load(View * v,const char * filename)178 view_load (View       *v,
179            const char *filename)
180 {
181   PDFDoc *newDoc;
182   int err;
183   GooString *filename_g;
184   int w, h;
185 
186   filename_g = new GooString (filename);
187 
188   // open the PDF file
189   newDoc = new PDFDoc(filename_g, 0, 0);
190 
191   delete filename_g;
192 
193   if (!newDoc->isOk())
194     {
195       err = newDoc->getErrorCode();
196       delete newDoc;
197       return err;
198     }
199 
200   if (v->doc)
201     delete v->doc;
202   v->doc = newDoc;
203 
204   v->out->startDoc(v->doc->getXRef());
205 
206   v->doc->displayPage (v->out, 1, 72, 72, 0, gFalse, gTrue, gTrue);
207 
208   w = v->out->getBitmapWidth();
209   h = v->out->getBitmapHeight();
210 
211   gtk_widget_set_size_request (v->drawing_area, w, h);
212 
213   return errNone;
214 }
215 
216 static void
view_show(View * v)217 view_show (View *v)
218 {
219   gtk_widget_show (v->window);
220 }
221 
222 static void
redraw_callback(void * data)223 redraw_callback (void *data)
224 {
225   View *v = (View*) data;
226 
227   gtk_widget_queue_draw (v->drawing_area);
228 }
229 
230 static View*
view_new(void)231 view_new (void)
232 {
233   View *v;
234   GtkWidget *window;
235   GtkWidget *drawing_area;
236   GtkWidget *sw;
237 
238   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
239 
240   drawing_area = gtk_drawing_area_new ();
241 
242   sw = gtk_scrolled_window_new (NULL, NULL);
243 
244   gtk_container_add (GTK_CONTAINER (window), sw);
245   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), drawing_area);
246 
247   gtk_widget_show_all (sw);
248 
249   v = g_new0 (View, 1);
250 
251   v->window = window;
252   v->drawing_area = drawing_area;
253   v->sw = sw;
254   SplashColor sc;
255   sc[0] = 255;
256   sc[1] = 255;
257   sc[2] = 255;
258   v->out = new GDKSplashOutputDev (gtk_widget_get_screen (window),
259                                    redraw_callback, (void*) v, sc);
260   v->doc = 0;
261 
262   g_signal_connect (drawing_area,
263                     "expose_event",
264                     G_CALLBACK (drawing_area_expose),
265                     (void*) v);
266 
267   return v;
268 }
269 
270 int
main(int argc,char * argv[])271 main (int argc, char *argv [])
272 {
273   View *v;
274   int i;
275 
276   gtk_init (&argc, &argv);
277 
278   globalParams = new GlobalParams();
279 
280   if (argc == 1)
281     {
282       fprintf (stderr, "usage: %s PDF-FILES...\n", argv[0]);
283       return -1;
284     }
285 
286 
287   i = 1;
288   while (i < argc)
289     {
290       int err;
291 
292       v = view_new ();
293 
294       err = view_load (v, argv[i]);
295 
296       if (err != errNone)
297         g_printerr ("Error loading document!\n");
298 
299       view_show (v);
300 
301       ++i;
302     }
303 
304   gtk_main ();
305 
306   delete globalParams;
307 
308   return 0;
309 }
310