root/branches/pdfcube-0.0.3/src/pdfcube.cc @ 10

Revision 10, 36.9 KB (checked in by mirko, 6 years ago)

version 0.0.3 will have customizable cube top image and background color

Line 
1// -*- mode: C++ -*-
2//
3// PDF-Cube source file - pdfcube.cc
4//
5// Copyright (C) 2006 Mirko Maischberger <mirko.maischberger@gmail.com>
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WAPRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21#include <iostream>
22
23#include <cstdio>
24#include <cstdlib>
25#include <cmath>
26#include <cassert>
27
28// Gtk+ (pkg-config gtk+-2.0)
29#include <gtk/gtk.h>
30#include <gdk/gdkkeysyms.h>
31
32// GtkGLExt (pkg-config gtkglext-1.0)
33#include <gtk/gtkgl.h>
34
35// OpenGL (-lglut)
36#include <GL/gl.h>
37#include <GL/glu.h>
38
39// PDF to GdkPixbuf (pkg-config poppler-glib)
40#include <poppler.h>
41
42using namespace std;
43
44//////////////////////////////////////////////////////////////////////////
45// Macros
46
47#define DEFAULT_WIDTH 640
48#define DEFAULT_HEIGHT 480
49#define DEFAULT_TITLE  "PDF-Cube"
50
51#define TIMEOUT_INTERVAL 38
52
53//////////////////////////////////////////////////////////////////////////
54// Globals (will be moved inside classes some day)
55
56static gboolean fullscreen = TRUE;
57static gboolean animating = FALSE;
58
59enum animation { ANIM_NONE, 
60                 CUBE, 
61                 ZOOM0, ZOOM1, ZOOM2, ZOOM3, ZOOM4, ZOOMC, 
62                 SWITCH_FW, SWITCH_BW
63};
64
65animation active_animation = ANIM_NONE;
66animation previous_animation = ANIM_NONE;
67animation last_animation = ANIM_NONE;
68
69// Cube Transitions on the command line
70// (space advances simply or with the rotating cube)
71// depending on the values in this array
72static bool *page_transition;
73
74// TODO: customize background color on command line
75static float bgcolor[] = {0.4, 0.0, 0.0};
76static GdkPixbuf* cube_top = NULL;
77
78//////////////////////////////////////////////////////////////////////////
79// Forward declarations
80
81static void         timeout_add       (GtkWidget   *widget);
82static void         timeout_remove    (GtkWidget   *widget);
83
84static void         start_animation  (GtkWidget   *widget, animation);
85static void         stop_animation  (GtkWidget   *widget);
86
87static GdkGLConfig *configure_gl      (void);
88
89static GtkWidget   *create_window     (GdkGLConfig *glconfig);
90
91static bool sleeping() { return !animating && active_animation == ANIM_NONE; }
92
93//////////////////////////////////////////////////////////////////////////
94//
95// pdfcube
96//
97// This is an attemp to move some dirtyness inside a class
98// some work still needs to be done to transform this quick
99// hack in a serious pdf-viewer
100//
101class pdfcube 
102{
103public:
104  pdfcube(PopplerDocument *d)
105    : doc(d),
106      current_page(0),
107      current_face(0),
108      total_pages(poppler_document_get_n_pages(d)),
109      frame(0), 
110      lookposx(0.0), lookposy(0.0), lookposz(3.48), 
111      atx(0.0), aty(0.0), atz(0.0), 
112      persp(44.0), angle(0.0),
113      pixmap(0)
114  {
115    texmap[0] = 0; texmap[1] = 1; texmap[2] = 2;
116    pixmap = 
117      gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, tex_width, tex_height);
118  }
119
120  int page() { return current_page; }
121
122  int pages() { return total_pages; }
123
124  void restart(GtkWidget* widget) 
125  { current_page = 0; update_textures(widget); }
126
127  void go_to(GtkWidget* widget, int page) 
128  { 
129    if(page>=0 && page < total_pages)
130      {
131        current_page = page; 
132        update_textures(widget); 
133      }
134  }
135
136  void section(GtkWidget* widget, int section)
137  {
138    cerr << "Section: " << section << " total pages: " << total_pages << endl;
139    int ii;
140    for(ii = 0; ii < total_pages; ++ii)
141      {
142       if(page_transition[ii]) section--;
143       if(section == 0) break;
144      }
145    cerr << "Page: " << ii << endl;
146    if(ii < total_pages)
147      {
148       current_page = ii;
149       update_textures(widget);
150      }
151  }
152
153  void 
154  initialize(GtkWidget *widget)
155  {
156    glClearColor (bgcolor[0], bgcolor[1], bgcolor[2], 0.0);
157   
158    // glEnable(GL_NORMALIZE);
159    glShadeModel(GL_FLAT);
160    glEnable(GL_TEXTURE_RECTANGLE_ARB);
161
162    // glEnable(GL_DEPTH_TEST);
163    // or
164    glEnable(GL_CULL_FACE);
165    glCullFace(GL_FRONT);
166
167    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
168   
169    glGenTextures (3, textures);
170
171    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
172    glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
173                    GL_CLAMP_TO_EDGE );
174    glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
175                    GL_CLAMP_TO_EDGE );
176
177    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, 
178                     GL_LINEAR_MIPMAP_LINEAR);
179    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, 
180                     GL_LINEAR);
181   
182    update_textures(widget);
183   
184    GLint size;
185    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
186    printf("%u\n", size);
187    assert(size >= 512);
188    assert(glIsTexture(textures[0]));
189   
190    // Cube vertex
191    v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1;
192    v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1;
193    v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1;
194    v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1;
195    v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
196    v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;
197   
198   
199    glMatrixMode(GL_PROJECTION);
200    gluPerspective( persp,
201                    1.0,
202                    0.5, 
203                    10.0);
204   
205    glMatrixMode(GL_MODELVIEW);
206
207    gluLookAt(lookposx, lookposy, lookposz,
208              atx, aty, atz,
209              0.0, 1.0, 0.0);      // up is in positive Y direction
210   
211  }
212
213 
214 
215  void 
216  redraw(GtkWidget *widget)
217  {
218    int frames = 17;
219    double yoffset = 0.1;
220    if(animating)
221      {
222        switch(active_animation)
223          {
224          case ANIM_NONE:
225            cerr << "No animation... stopping right now." << endl;
226            frame = 0;
227            stop_animation(widget);
228            break;
229          case CUBE:
230            cerr << "cube " << frame << endl;
231            if(frame == 17)
232              {
233                frame = 0;
234                stop_animation(widget);
235              } 
236            else 
237              {
238                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
239                glMatrixMode(GL_MODELVIEW);
240                glLoadIdentity();
241                lookposz -= zsteps[frame]*4;
242                lookposy = 6*xsteps[frame];
243                gluLookAt(lookposx, lookposy, lookposz, atx,aty,atz, 0,1,0);
244                angle -= steps[frame];
245                glRotatef(angle, 0.0, 1.0, 0.0);
246                drawCube();
247                frame++;
248              }
249            break;
250          case ZOOM0:
251            cerr << "zoom0 " << frame << endl;
252            if(frame == 17)
253              {
254                frame = 0;
255                stop_animation(widget);
256              } 
257            else 
258            {
259              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
260              switch(previous_animation)
261                {
262                case ZOOM1:
263                  persp = perspsteps[16-frame];
264                  atx = lookposx = -(1.3*zoomsteps[16-frame]);
265                  aty = lookposy = zoomsteps[16-frame] - 
266                    yoffset/frames * (16-frame);
267                  break;
268                case ZOOM2:
269                  persp = perspsteps[16-frame];
270                  atx = lookposx = 1.3*zoomsteps[16-frame];
271                  aty = lookposy = zoomsteps[16-frame] - 
272                    yoffset/frames * (16-frame);
273                  break;
274                case ZOOM3:
275                  persp = perspsteps[16-frame];
276                  atx = lookposx = -1.3*zoomsteps[16-frame];
277                  aty = lookposy = -zoomsteps[16-frame] - 
278                    yoffset/frames * (16-frame);
279                  break;
280                case ZOOM4:
281                  persp = perspsteps[16-frame];
282                  atx = lookposx = 1.3*zoomsteps[16-frame];
283                  aty = lookposy = -zoomsteps[16-frame] - 
284                    yoffset/frames * (16-frame);
285                  break;
286                case ZOOMC:
287                  persp = perspstepsc[16-frame];
288                  aty = lookposy = - zoomsteps[16-frame]*0.38;
289                  break;
290                default:
291                  cerr << "Should not reach" << endl;
292                  break;
293                }
294              glMatrixMode(GL_PROJECTION);
295              glLoadIdentity();
296              gluPerspective( persp,
297                              1.0,
298                              0.5, 
299                              10.0);
300              glMatrixMode(GL_MODELVIEW);
301              glLoadIdentity();
302              gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0);
303              glRotatef(angle, 0.0, 1.0, 0.0);
304              drawCube();
305              frame++;
306            }
307            break;
308          case ZOOM1:
309            cerr << "zoom1 " << frame << endl;
310            if(frame == 17)
311              {
312                frame = 0;
313                stop_animation(widget);
314              } 
315            else 
316              { 
317                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
318                glMatrixMode(GL_PROJECTION);
319                glLoadIdentity();
320                persp = perspsteps[frame];
321                gluPerspective(persp,
322                               1.0,
323                               0.5, 
324                               10.0);
325                glMatrixMode(GL_MODELVIEW);
326                glLoadIdentity();
327                atx = lookposx = -1.3*zoomsteps[frame];
328                aty = lookposy = zoomsteps[frame] - yoffset/frames * (frame);
329                gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0);
330                glRotatef(angle, 0.0, 1.0, 0.0);
331                drawCube();
332                frame++;
333              }
334            break;
335          case ZOOM2:
336            cerr << "zoom1 " << frame << endl;
337            if(frame == 17)
338              {
339                frame = 0;
340                stop_animation(widget);
341              } 
342            else 
343              { 
344                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
345                glMatrixMode(GL_PROJECTION);
346                glLoadIdentity();
347                persp = perspsteps[frame];
348                gluPerspective(persp,
349                               1.0,
350                               0.5, 
351                               10.0);
352                glMatrixMode(GL_MODELVIEW);
353                glLoadIdentity();
354                atx = lookposx = 1.3*zoomsteps[frame];
355                aty = lookposy = zoomsteps[frame] - yoffset/frames * (frame);
356                gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0);
357                glRotatef(angle, 0.0, 1.0, 0.0);
358                drawCube();
359                frame++;
360              }
361            break;
362          case ZOOM3:
363            cerr << "zoom1 " << frame << endl;
364            if(frame == 17)
365              {
366                frame = 0;
367                stop_animation(widget);
368              } 
369            else 
370              { 
371                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
372                glMatrixMode(GL_PROJECTION);
373                glLoadIdentity();
374                persp = perspsteps[frame];
375                gluPerspective(persp,
376                               1.0,
377                               0.5, 
378                               10.0);
379                glMatrixMode(GL_MODELVIEW);
380                glLoadIdentity();
381                atx = lookposx = -1.3*zoomsteps[frame];
382                aty = lookposy = -zoomsteps[frame] - yoffset/frames * (frame);
383                gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0);
384                glRotatef(angle, 0.0, 1.0, 0.0);
385                drawCube();
386                frame++;
387              }
388            break;
389          case ZOOM4:
390            cerr << "zoom1 " << frame << endl;
391            if(frame == 17)
392              {
393                frame = 0;
394                stop_animation(widget);
395              } 
396            else 
397              { 
398                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
399                glMatrixMode(GL_PROJECTION);
400                glLoadIdentity();
401                persp = perspsteps[frame];
402                gluPerspective(persp,
403                               1.0,
404                               0.5, 
405                               10.0);
406                glMatrixMode(GL_MODELVIEW);
407                glLoadIdentity();
408                atx = lookposx = 1.3*zoomsteps[frame];
409                aty = lookposy = -zoomsteps[frame] -yoffset/frames * (frame);
410                gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0);
411                glRotatef(angle, 0.0, 1.0, 0.0);
412                drawCube();
413                frame++;
414              }
415            break;
416          case ZOOMC:
417            cerr << "zoomc " << frame << endl;
418            if(frame == 17)
419              {
420                frame = 0;
421                stop_animation(widget);
422              } 
423            else 
424              { 
425                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
426                persp = perspstepsc[frame];
427                aty = lookposy = - zoomsteps[frame]*0.38;
428                glMatrixMode(GL_PROJECTION);
429                glLoadIdentity();
430                gluPerspective(persp,
431                               1.0,
432                               0.5, 
433                               10.0);
434                glMatrixMode(GL_MODELVIEW);
435                glLoadIdentity();
436                gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0);
437                glRotatef(angle, 0.0, 1.0, 0.0);
438                drawCube();
439                frame++;
440              }
441            break;
442          case SWITCH_FW:
443            cerr << "fw " << frame << endl;
444            if(frame == 1)
445              {
446                frame = 0;
447                stop_animation(widget);
448              }
449            else 
450              {
451                glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
452                glMatrixMode(GL_MODELVIEW);
453                glLoadIdentity();
454                gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0);
455                angle -= 90;
456                glRotatef(angle, 0.0, 1.0, 0.0);
457                drawCube();
458                frame++;
459              }
460            break;
461          case SWITCH_BW:
462            cerr << "bw " << frame << endl;
463            if(frame == 1)
464              {
465                frame = 0;
466                stop_animation(widget);
467              }
468            else
469              {
470                glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
471                glMatrixMode(GL_MODELVIEW);
472                glLoadIdentity();
473                gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0);
474                angle += 90;
475                glRotatef(angle, 0.0, 1.0, 0.0);
476                drawCube();
477                frame++;
478              }
479            break;
480          }
481      }
482    else
483      {
484        switch(active_animation)
485          {
486          case ANIM_NONE:
487            cerr << "Redrawing" << endl;
488            break;
489          case CUBE:
490            cerr << "cube stop" << endl;
491            forward(widget);
492            current_face = next_face();
493            break;
494          case SWITCH_FW:
495            cerr << "fw stop" << endl;
496            forward(widget);
497            current_face = next_face();
498            break;
499          case SWITCH_BW:
500            cerr << "bw stop" << endl;
501            backward(widget);
502            current_face = prev_face();
503            break;
504          case ZOOM0:
505          case ZOOM1:
506          case ZOOM2:
507          case ZOOM3:
508          case ZOOM4:
509          case ZOOMC:
510          default:
511            cerr << "default stop" << endl;
512            break;
513           
514          }
515
516        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
517        glMatrixMode(GL_PROJECTION);
518        glLoadIdentity();
519        gluPerspective( persp,
520                        1.0,
521                        0.5, 
522                        10.0);
523        glMatrixMode(GL_MODELVIEW);
524        glLoadIdentity();
525        gluLookAt(lookposx, lookposy, lookposz, atx, aty, atz, 0,1,0); 
526        glRotatef(angle, 0.0, 1.0, 0.0);
527        drawCube();
528
529        glRasterPos3f(0, -1.4, 0);
530        GLuint rcube[] = {
531          0,0,0,127
532        };
533        glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rcube);
534
535        active_animation = ANIM_NONE;
536       
537        cerr << "Ok!" << endl;
538      }   
539  }
540
541  int prev_face()
542  {
543    if(current_face-1 < 0) return 3;
544    else return current_face -1;
545  }
546
547  int next_face()
548  {
549    if(current_face+1 > 3) return 0;
550    else return current_face+1; 
551  }
552
553  int prev_page()
554  {
555    assert(current_page >= 0);
556    if(current_page == 0) return total_pages-1;
557    else return current_page-1;
558  }
559 
560  int next_page()
561  {
562    assert(current_page < total_pages);
563    if(current_page == total_pages-1) return 0;
564    else return current_page+1;
565  }
566 
567  void
568  forward(GtkWidget *widget)
569  {
570    update_textures_dir(widget, true);
571    cerr << "Current page: " << current_page << endl;
572  }
573 
574  void
575  backward(GtkWidget *widget)
576  {
577    update_textures_dir(widget, false);
578    cerr << "Current page: " << current_page << endl;
579  }
580
581  void
582  reset(GtkWidget *widget)
583  {
584    animating = FALSE;
585    frame = 0; 
586    lookposx = 0.0;
587    lookposy = 0.0;
588    lookposz = 3.48; 
589    atx = 0.0;
590    aty = 0.0;
591    atz = 0.0;
592    persp = 44.0; 
593    angle = 0.0;
594    current_face = 0;
595    active_animation = ANIM_NONE;
596    previous_animation = ANIM_NONE;
597    last_animation = ANIM_NONE;
598    update_textures(widget);
599  }
600
601  // shift old textures and render the new page
602  // texmap[0] -> current page
603  // texmap[1] -> prev page
604  // texmap[2] -> next page
605  void update_textures_dir(GtkWidget *widget, bool forward)
606  {
607    assert(current_page >= 0);
608    assert(current_page < total_pages);
609
610    if(forward)
611      {
612        current_page=next_page();
613        int tmp = texmap[2];
614        texmap[2] = texmap[1];
615        texmap[1] = texmap[0];
616        texmap[0] = tmp;
617        render_page(pixmap, next_page(), tex_width, tex_height);
618      }
619    else
620      {
621        current_page=prev_page();
622        int tmp = texmap[0];
623        texmap[0] = texmap[1];
624        texmap[1] = texmap[2];
625        texmap[2] = tmp;
626        render_page(pixmap, prev_page(), tex_width, tex_height);
627      }
628
629    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 
630                   textures[texmap[forward ? 2 : 1]]);
631    glTexImage2D (GL_TEXTURE_RECTANGLE_ARB,
632                  0,
633                  GL_RGBA,
634                  tex_width,
635                  tex_height,
636                  0,
637                  GL_RGBA,
638                  GL_UNSIGNED_BYTE,
639                  gdk_pixbuf_get_pixels(pixmap));
640   
641    gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
642   
643  }
644
645  // render all (3) textures
646  void update_textures(GtkWidget *widget)
647  {
648    assert(current_page >= 0);
649    assert(current_page < total_pages);
650
651    render_page(pixmap, current_page, tex_width, tex_height);
652    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, textures[texmap[0]]);
653    glTexImage2D (GL_TEXTURE_RECTANGLE_ARB,
654                  0,
655                  GL_RGBA,
656                  tex_width,
657                  tex_height,
658                  0,
659                  GL_RGBA,
660                  GL_UNSIGNED_BYTE,
661                  gdk_pixbuf_get_pixels(pixmap));
662   
663    render_page(pixmap, prev_page(), tex_width, tex_height);
664    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, textures[texmap[1]]);
665    glTexImage2D (GL_TEXTURE_RECTANGLE_ARB,
666                  0,
667                  GL_RGBA,
668                  tex_width,
669                  tex_height,
670                  0,
671                  GL_RGBA,
672                  GL_UNSIGNED_BYTE,
673                  gdk_pixbuf_get_pixels(pixmap));
674   
675    render_page(pixmap, next_page(), tex_width, tex_height);
676    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, textures[texmap[2]]);
677    glTexImage2D (GL_TEXTURE_RECTANGLE_ARB,
678                  0,
679                  GL_RGBA,
680                  tex_width,
681                  tex_height,
682                  0,
683                  GL_RGBA,
684                  GL_UNSIGNED_BYTE,
685                  gdk_pixbuf_get_pixels(pixmap));
686
687   
688      gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
689     
690  }
691
692protected:
693  PopplerDocument* doc;
694  int current_page;
695  int current_face;
696  const int total_pages;
697  int frame;
698  double lookposx, lookposy, lookposz;
699  double atx, aty, atz;
700  double persp, angle;
701  GdkPixbuf* pixmap;
702  int texmap[3];
703
704  // OpenGL Textures
705  GLuint textures[3];
706 
707  // Width and Height of the rendered pixmap (aspect
708  // ratio is fixed, should instead depend on the
709  // aspect ratio of the pdf page)
710  static const gint tex_width = (gint)(3*1024/2);
711  static const gint tex_height = (gint)(3*768/2);
712
713  // Cube Normals
714  static const GLfloat n[6][3];
715  // Cube Faces
716  static const GLint faces[6][4];
717  // Cube vertex (filled in pdfcube->initialize())
718  GLfloat v[8][3]; 
719  // Cube texture mapping
720  static const GLfloat mapping[6][8];
721  // Cube Rotation Animation steps (17 frames)
722  // Cube rotation at each frame
723  static const GLfloat steps[17];
724  // x camera movement
725  static const double xsteps[17];
726  // z camera movement
727  static const double zsteps[17];
728  static const double zoomsteps[17];
729  static const double perspsteps[17];
730  static const double perspstepsc[17];
731
732  void 
733  render_page(GdkPixbuf* pm, int i, gint iWidth, gint iHeight)
734  {
735    PopplerPage *page = NULL;
736    page = poppler_document_get_page(doc, i);
737    assert(page);
738    double w, h;
739    poppler_page_get_size(page, &w, &h);
740    poppler_page_render_to_pixbuf(page, 0,0,iWidth,iHeight,1.0*iWidth/w,0,pm);
741  }
742
743  void
744  drawCube(void)
745  {
746    int i;
747
748    for (i = 0; i < 6; i++) 
749      {
750        if(i == current_face)
751          {
752            glEnable (GL_TEXTURE_RECTANGLE_ARB);
753            glBindTexture (GL_TEXTURE_RECTANGLE_ARB, textures[texmap[0]]);
754          }
755        else if(i == prev_face())
756          {
757            glEnable (GL_TEXTURE_RECTANGLE_ARB);
758            glBindTexture (GL_TEXTURE_RECTANGLE_ARB, textures[texmap[1]]);
759          }
760        else if(i == next_face()) 
761          {
762            glEnable (GL_TEXTURE_RECTANGLE_ARB);
763            glBindTexture (GL_TEXTURE_RECTANGLE_ARB, textures[texmap[2]]);
764          }
765        else if(i <= 3)
766          {
767            glDisable(GL_TEXTURE_RECTANGLE_ARB);
768            glColor4f(0.4, 0.0, 0.0, 1.0);
769          } 
770        else
771          {
772            glDisable(GL_TEXTURE_RECTANGLE_ARB);
773            glColor4f(1.0, 1.0, 1.0, 1.0);
774          }
775        glBegin(GL_QUADS);
776        glNormal3fv(&n[i][0]);
777        glTexCoord2f((1.0-mapping[i][4]) * tex_width, 
778                     mapping[i][5] * tex_height); 
779        glVertex3fv(&v[faces[i][0]][0]);
780       
781        glTexCoord2f((1.0-mapping[i][6]) * tex_width, 
782                     mapping[i][7] * tex_height); 
783        glVertex3fv(&v[faces[i][1]][0]);
784       
785        glTexCoord2f((1.0-mapping[i][0]) * tex_width, 
786                     mapping[i][1] * tex_height); 
787        glVertex3fv(&v[faces[i][2]][0]);
788       
789        glTexCoord2f((1.0-mapping[i][2]) * tex_width, 
790                     mapping[i][3] * tex_height); 
791        glVertex3fv(&v[faces[i][3]][0]);
792       
793        glEnd();
794      }
795  }
796};
797
798const GLfloat pdfcube::n[6][3] = { 
799  {0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0},  {-1.0, 0.0, 0.0}, 
800  {0.0, 1.0, 0.0}, {0.0, -1.0, 0.0}
801};
802const GLint pdfcube::faces[6][4] = {
803  {7, 4, 0, 3}, {7, 6, 5, 4}, {5, 6, 2, 1}, {0, 1, 2, 3}, 
804  {3, 2, 6, 7}, {4, 5, 1, 0}
805};
806const GLfloat pdfcube::mapping[6][8] = {
807    {1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0}, 
808    {0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0}, 
809    {0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0}, 
810    {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0}, 
811    {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0}, // top
812    {1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0}, // bottom
813};
814const GLfloat pdfcube::steps[17] = 
815  {  2.0,   2.5,   3,     4,     5,     6,     8,     10,   
816     14,   10,   8,    6,    4,    3,    2.5,   2.0, 0.0  };
817const double pdfcube::xsteps[17] = 
818  {  0.01,  0.03,  0.07,  0.12,  0.16,  0.18,  0.20,  0.21, 
819     0.21, 0.20, 0.18, 0.16, 0.12, 0.07, 0.03, 0.01, 0.00 };
820const double pdfcube::zsteps[17] = 
821  { -0.01, -0.02, -0.04, -0.05, -0.04, -0.02, -0.02, -0.01, 
822    0.01, 0.02, 0.02, 0.04, 0.05, 0.04, 0.02, 0.01, 0.00 };
823const double pdfcube::zoomsteps[17] =
824  { 0.00, 0.01, 0.02, 0.03, 0.05, 0.07, 0.10, 0.13, 0.17, 
825    0.21, 0.25, 0.29, 0.32, 0.35, 0.37, 0.38, 0.38 };
826const double pdfcube::perspsteps[17] =
827  { 44.0, 44.0, 44.0, 44.00, 44.00, 43.00, 42.00, 40.00, 
828    38.00, 36.00, 33.00, 30.00, 27.00, 24.00, 22.00, 21.00, 21.00 };
829const double pdfcube::perspstepsc[17] =
830  { 44.0, 44.0, 44.0, 44.00, 44.00, 43.00, 42.00, 40.00, 
831    38.00, 36.00, 34.00, 32.00, 31.00, 30.00, 30.00, 30.00, 30.00 };
832
833pdfcube* pc;
834
835//////////////////////////////////////////////////////////////////////////
836// Callbacks
837
838/***
839 *** The "realize" signal handler. All the OpenGL initialization
840 *** should be performed here, such as default background colour,
841 *** certain states etc.
842 ***/
843static void
844realize (GtkWidget *widget,
845         gpointer   data)
846{
847  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
848  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
849
850  g_print ("%s: \"realize\"\n", gtk_widget_get_name (widget));
851
852  //g_mutex_lock (gl_mutex);
853
854  /*** OpenGL BEGIN ***/
855  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
856    return;
857
858  pc->initialize(widget);
859
860  gdk_gl_drawable_gl_end (gldrawable);
861  /*** OpenGL END ***/
862  //g_mutex_unlock (gl_mutex);
863}
864
865/***
866 *** The "configure_event" signal handler. Any processing required when
867 *** the OpenGL-capable drawing area is re-configured should be done here.
868 *** Almost always it will be used to resize the OpenGL viewport when
869 *** the window is resized.
870 ***/
871static gboolean
872configure_event (GtkWidget         *widget,
873                 GdkEventConfigure *event,
874                 gpointer           data)
875{
876  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
877  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
878
879  GLsizei w = widget->allocation.width;
880  GLsizei h = widget->allocation.height;
881
882  g_print ("%s: \"configure_event\"\n", gtk_widget_get_name (widget));
883
884  //g_mutex_lock (gl_mutex);
885  /*** OpenGL BEGIN ***/
886  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
887    return FALSE;
888
889  glViewport (0, 0, w, h);
890
891  gdk_gl_drawable_gl_end (gldrawable);
892
893 /*** OpenGL END ***/
894  //g_mutex_unlock (gl_mutex);
895
896  return TRUE;
897}
898
899/***
900 *** The "expose_event" signal handler. All the OpenGL re-drawing should
901 *** be done here. This is repeatedly called as the painting routine
902 *** every time the 'expose'/'draw' event is signalled.
903 ***/
904static gboolean
905expose_event (GtkWidget      *widget,
906              GdkEventExpose *event,
907              gpointer        data)
908{
909  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
910  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
911
912  //g_mutex_lock (gl_mutex);
913  /*** OpenGL BEGIN ***/
914  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
915    return FALSE;
916
917  glDrawBuffer(GL_BACK); 
918
919  pc->redraw(widget);
920 
921  /* Swap buffers */
922  if (gdk_gl_drawable_is_double_buffered (gldrawable))
923    gdk_gl_drawable_swap_buffers (gldrawable);
924  else
925    glFlush ();
926 
927
928  gdk_gl_drawable_gl_end (gldrawable);
929  /*** OpenGL END ***/
930
931  //g_mutex_unlock (gl_mutex);
932
933  return TRUE;
934}
935
936/***
937 *** The timeout function. Often in animations,
938 *** timeout functions are suitable for continous
939 *** frame updates.
940 ***/
941static gboolean
942timeout (GtkWidget *widget)
943{
944  /* Invalidate the whole window. */
945  gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
946
947  /* Update synchronously. */
948  gdk_window_process_updates (widget->window, FALSE);
949
950  return TRUE;
951}
952
953/***
954 *** The "unrealize" signal handler. Any processing required when
955 *** the OpenGL-capable window is unrealized should be done here.
956 ***/
957static void
958unrealize (GtkWidget *widget,
959           gpointer   data)
960{
961  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
962  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
963
964  g_print ("%s: \"unrealize\"\n", gtk_widget_get_name (widget));
965
966  //g_mutex_lock (gl_mutex);
967
968  /*** OpenGL BEGIN ***/
969  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
970    return;
971
972  gdk_gl_drawable_gl_end (gldrawable);
973  /*** OpenGL END ***/
974  //g_mutex_unlock (gl_mutex);
975}
976
977/***
978 *** The "motion_notify_event" signal handler. Any processing required when
979 *** the OpenGL-capable drawing area is under drag motion should be done here.
980 ***/
981static gboolean
982motion_notify_event (GtkWidget      *widget,
983                     GdkEventMotion *event,
984                     gpointer        data)
985{
986  g_print ("%s: \"motion_notify_event\": button", gtk_widget_get_name (widget));
987
988  if (event->state & GDK_BUTTON1_MASK)
989    {
990      g_print (" 1");
991    }
992
993  if (event->state & GDK_BUTTON2_MASK)
994    {
995      g_print (" 2");
996    }
997
998  if (event->state & GDK_BUTTON3_MASK)
999    {
1000      g_print (" 3");
1001    }
1002
1003  g_print ("\n");
1004
1005  return FALSE;
1006}
1007
1008/***
1009 *** The "button_press_event" signal handler. Any processing required when
1010 *** mouse buttons (only left and middle buttons) are pressed on the OpenGL-
1011 *** capable drawing area should be done here.
1012 ***/
1013static gboolean
1014button_press_event (GtkWidget      *widget,
1015                    GdkEventButton *event,
1016                    gpointer        data)
1017{
1018  g_print ("%s: \"button_press_event\": ", gtk_widget_get_name (widget));
1019
1020  if (event->button == 1)
1021    {
1022      g_print ("button 1\n");
1023
1024      return TRUE;
1025    }
1026
1027  if (event->button == 2)
1028    {
1029      g_print ("button 2\n");
1030
1031      return TRUE;
1032    }
1033
1034  g_print ("\n");
1035
1036  return FALSE;
1037}
1038
1039/***
1040 *** The "key_press_event" signal handler. Any processing required when key
1041 *** presses occur should be done here.
1042 ***/
1043static gboolean
1044key_press_event (GtkWidget   *widget,
1045                 GdkEventKey *event,
1046                 gpointer     data)
1047{
1048  g_print ("%s: \"key_press_event\": ", gtk_widget_get_name (widget));
1049
1050  if(event->state == GDK_CONTROL_MASK)
1051
1052    switch (event->keyval)
1053      {
1054      case GDK_1:
1055      case GDK_2:
1056      case GDK_3:
1057      case GDK_4:
1058      case GDK_5:
1059      case GDK_6:
1060      case GDK_7:
1061      case GDK_8:
1062      case GDK_9:
1063        g_print ("n key\n");
1064        if(sleeping())
1065          pc->section(widget, event->keyval - GDK_1 + 1);
1066        break;
1067
1068        // Let's quit
1069      case GDK_q:
1070        g_print ("Escape key\n");
1071        gtk_main_quit ();
1072        break;
1073
1074        // Update all textures
1075      case GDK_l:
1076        g_print ("u key\n");
1077        cerr << "Pagina: " << pc->page() << endl;
1078        pc->reset(widget);
1079        break;
1080      }
1081  else
1082    switch (event->keyval)
1083      {
1084       
1085        // return to page 1
1086      case GDK_1:
1087      case GDK_2:
1088      case GDK_3:
1089      case GDK_4:
1090      case GDK_5:
1091      case GDK_6:
1092      case GDK_7:
1093      case GDK_8:
1094      case GDK_9:
1095        g_print ("n key\n");
1096        if(sleeping())
1097          pc->go_to(widget, (event->keyval - GDK_1) * 5);
1098        break;
1099       
1100        // Animated Cube Advancement
1101      case GDK_a:
1102      case GDK_c:
1103        g_print ("c key\n");
1104        if(sleeping())
1105          start_animation(widget, CUBE);
1106        break;
1107       
1108      // Quick switch to next page
1109      case GDK_Page_Down:
1110      case GDK_Right:
1111        g_print ("s key\n");
1112        if(sleeping())
1113          start_animation(widget, SWITCH_FW);
1114        break;
1115       
1116      // Quick switch to previous page
1117      case GDK_Page_Up:
1118      case GDK_Left:
1119        g_print ("q key\n");
1120        if(sleeping())
1121          start_animation(widget, SWITCH_BW);
1122        break;
1123
1124
1125
1126      case GDK_g:
1127        if(sleeping())
1128          if(last_animation >= ZOOM1 and last_animation <= ZOOMC)
1129            start_animation(widget, ZOOM0);
1130        break;
1131
1132      case GDK_h:
1133        if(sleeping())
1134          if(last_animation >= ZOOM1 and last_animation <= ZOOMC)
1135            start_animation(widget, ZOOM0);
1136          else
1137            start_animation(widget, ZOOM1);
1138        break;
1139
1140      case GDK_j:
1141        if(sleeping())
1142          if(last_animation >= ZOOM1 and last_animation <= ZOOMC)
1143            start_animation(widget, ZOOM0);
1144          else
1145            start_animation(widget, ZOOM2);
1146        break;
1147
1148      case GDK_k:
1149        if(sleeping())
1150          if(last_animation >= ZOOM1 and last_animation <= ZOOMC)
1151            start_animation(widget, ZOOM0);
1152          else
1153            start_animation(widget, ZOOM3);
1154        break;
1155
1156      case GDK_l:
1157        if(sleeping())
1158          if(last_animation >= ZOOM1 and last_animation <= ZOOMC)
1159            start_animation(widget, ZOOM0);
1160          else
1161            start_animation(widget, ZOOM4);
1162        break;
1163       
1164      case GDK_z:
1165        if(sleeping())
1166          if(last_animation >= ZOOM1 and last_animation <= ZOOMC)
1167            start_animation(widget, ZOOM0);
1168          else
1169            start_animation(widget, ZOOMC);
1170        break;
1171       
1172       
1173        // Automatic advance (you should se the Animated slides on the command line)
1174      case GDK_space:
1175        if(page_transition[pc->page()] and sleeping())
1176          start_animation(widget, CUBE);
1177        else if(sleeping())
1178          start_animation(widget, SWITCH_FW);
1179       
1180        break;
1181       
1182        // switch fullscreen
1183      case GDK_f:
1184        if( (fullscreen = !fullscreen) == true)
1185          gtk_window_fullscreen((GtkWindow*)(data));
1186        else
1187          gtk_window_unfullscreen((GtkWindow*)(data));
1188        break;
1189       
1190        // Let's quit
1191      case GDK_Escape:
1192        g_print ("Escape key\n");
1193        gtk_main_quit ();
1194        break;
1195
1196      default:
1197        g_print("\n");
1198        return FALSE;
1199    }
1200
1201  return TRUE;
1202}
1203
1204
1205//////////////////////////////////////////////////////////////////////////
1206// Timeout functions
1207
1208/***
1209 *** Helper functions to add or remove the timeout function.
1210 ***/
1211
1212static guint timeout_id = 0;
1213
1214static void
1215timeout_add (GtkWidget *widget)
1216{
1217  if (timeout_id == 0)
1218    {
1219      timeout_id = g_timeout_add (TIMEOUT_INTERVAL,
1220                                  (GSourceFunc) timeout,
1221                                  widget);
1222    }
1223}
1224
1225static void
1226timeout_remove (GtkWidget *widget)
1227{
1228  if (timeout_id != 0)
1229    {
1230      g_source_remove (timeout_id);
1231      timeout_id = 0;
1232    }
1233}
1234
1235/***
1236 *** The "map_event" signal handler. Any processing required when the
1237 *** OpenGL-capable drawing area is mapped should be done here.
1238 ***/
1239static gboolean
1240map_event (GtkWidget *widget,
1241           GdkEvent  *event,
1242           gpointer   data)
1243{
1244  g_print ("%s: \"map_event\":\n", gtk_widget_get_name (widget));
1245  if (animating)
1246    timeout_add (widget);
1247
1248  return TRUE;
1249}
1250
1251/***
1252 *** The "unmap_event" signal handler. Any processing required when the
1253 *** OpenGL-capable drawing area is unmapped should be done here.
1254 ***/
1255static gboolean
1256unmap_event (GtkWidget *widget,
1257             GdkEvent  *event,
1258             gpointer   data)
1259{
1260  g_print ("%s: \"unmap_event\":\n", gtk_widget_get_name (widget));
1261  timeout_remove (widget);
1262
1263  return TRUE;
1264}
1265
1266/***
1267 *** The "visibility_notify_event" signal handler. Any processing required
1268 *** when the OpenGL-capable drawing area is visually obscured should be
1269 *** done here.
1270 ***/
1271static gboolean
1272visibility_notify_event (GtkWidget          *widget,
1273                         GdkEventVisibility *event,
1274                         gpointer            data)
1275{
1276  if (animating)
1277    {
1278      if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
1279        timeout_remove (widget);
1280      else
1281        timeout_add (widget);
1282    }
1283
1284  return TRUE;
1285}
1286
1287
1288/**************************************************************************
1289 * The following section contains some miscellaneous utility functions.
1290 **************************************************************************/
1291
1292/***
1293 *** Toggle animation.
1294 ***/
1295static void
1296start_animation(GtkWidget *widget, enum animation a)
1297{
1298  if(sleeping())
1299    {
1300      animating = true;
1301      previous_animation = last_animation;
1302      last_animation = active_animation = a;
1303      timeout_add(widget);
1304    }
1305}
1306
1307static void
1308stop_animation(GtkWidget *widget)
1309{
1310  animating = false;
1311  timeout_remove(widget);
1312  gdk_window_invalidate_rect(widget->window, &widget->allocation, FALSE);
1313  gdk_window_process_updates (widget->window, FALSE);
1314}
1315
1316//////////////////////////////////////////////////////////////////////////
1317// GTK+ GUI Functions
1318
1319/***
1320 *** Creates the simple application window with one
1321 *** drawing area that has an OpenGL-capable visual.
1322 ***/
1323static GtkWidget *
1324create_window (GdkGLConfig *glconfig)
1325{
1326  GtkWidget *window;
1327  GtkWidget *vbox;
1328  GtkWidget *drawing_area;
1329
1330  /*
1331   * Top-level window.
1332   */
1333
1334  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1335  gtk_window_set_title (GTK_WINDOW (window), DEFAULT_TITLE);
1336
1337  /* Get automatically redrawn if any of their children changed allocation. */
1338  gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
1339
1340  /* Connect signal handlers to the window */
1341  g_signal_connect (G_OBJECT (window), "delete_event",
1342                    G_CALLBACK (gtk_main_quit), NULL);
1343
1344  /*
1345   * VBox.
1346   */
1347
1348  vbox = gtk_vbox_new (FALSE, 0);
1349  gtk_container_add (GTK_CONTAINER (window), vbox);
1350  gtk_widget_show (vbox);
1351
1352  /*
1353   * Drawing area to draw OpenGL scene.
1354   */
1355
1356  drawing_area = gtk_drawing_area_new ();
1357  gtk_widget_set_size_request (drawing_area, DEFAULT_WIDTH, DEFAULT_HEIGHT);
1358
1359  /* Set OpenGL-capability to the widget */
1360  gtk_widget_set_gl_capability (drawing_area,
1361                                glconfig,
1362                                NULL,
1363                                TRUE,
1364                                GDK_GL_RGBA_TYPE);
1365
1366  gtk_widget_add_events (drawing_area,
1367                         GDK_BUTTON1_MOTION_MASK    |
1368                         GDK_BUTTON2_MOTION_MASK    |
1369                         GDK_BUTTON_PRESS_MASK      |
1370                         GDK_VISIBILITY_NOTIFY_MASK);
1371
1372  /* Connect signal handlers to the drawing area */
1373  g_signal_connect_after (G_OBJECT (drawing_area), "realize",
1374                          G_CALLBACK (realize), NULL);
1375  g_signal_connect (G_OBJECT (drawing_area), "configure_event",
1376                    G_CALLBACK (configure_event), NULL);
1377  g_signal_connect (G_OBJECT (drawing_area), "expose_event",
1378                    G_CALLBACK (expose_event), NULL);
1379  g_signal_connect (G_OBJECT (drawing_area), "unrealize",
1380                    G_CALLBACK (unrealize), NULL);
1381
1382  g_signal_connect (G_OBJECT (drawing_area), "motion_notify_event",
1383                    G_CALLBACK (motion_notify_event), NULL);
1384  g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
1385                    G_CALLBACK (button_press_event), NULL);
1386
1387  /* key_press_event handler for top-level window */
1388  g_signal_connect_swapped (G_OBJECT (window), "key_press_event",
1389                            G_CALLBACK (key_press_event), drawing_area);
1390
1391  /* For timeout function. */
1392  g_signal_connect (G_OBJECT (drawing_area), "map_event",
1393                    G_CALLBACK (map_event), NULL);
1394  g_signal_connect (G_OBJECT (drawing_area), "unmap_event",
1395                    G_CALLBACK (unmap_event), NULL);
1396  g_signal_connect (G_OBJECT (drawing_area), "visibility_notify_event",
1397                    G_CALLBACK (visibility_notify_event), NULL);
1398
1399  gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
1400
1401  gtk_widget_show (drawing_area);
1402
1403  return window;
1404}
1405
1406/***
1407 *** Configure the OpenGL framebuffer.
1408 ***/
1409static GdkGLConfig *
1410configure_gl (void)
1411{
1412  GdkGLConfig *glconfig;
1413
1414  /* Try double-buffered visual */
1415  glconfig = gdk_gl_config_new_by_mode ((GdkGLConfigMode)
1416                                        (
1417                                         GDK_GL_MODE_RGBA   |
1418                                         GDK_GL_MODE_ALPHA  |
1419                                         GDK_GL_MODE_DEPTH  |
1420                                         GDK_GL_MODE_DOUBLE));
1421  if (glconfig == NULL)
1422    {
1423      g_print ("\n*** Cannot find the double-buffered visual.\n");
1424      g_print ("\n*** Trying single-buffered visual.\n");
1425
1426      /* Try single-buffered visual */
1427      glconfig = gdk_gl_config_new_by_mode ((GdkGLConfigMode)
1428                                            (
1429                                             GDK_GL_MODE_RGB   |
1430                                             GDK_GL_MODE_DEPTH));
1431      if (glconfig == NULL)
1432        {
1433          g_print ("*** No appropriate OpenGL-capable visual found.\n");
1434          exit (1);
1435        }
1436    }
1437
1438
1439  return glconfig;
1440}
1441
1442///
1443/// @brief Gets the absolute path of a filename.
1444///
1445/// This function checks if the given @a fileName is an absolute path. If
1446/// it is then it returns a copy of it, otherwise it prepends the current
1447/// working directory to it.
1448///
1449/// @param fileName The filename to get the absolute path from.
1450///
1451/// @return A copy of the absolute path to the file name. This copy must be
1452///         freed when no longer needed.
1453///
1454gchar *
1455get_absolute_file_name (const gchar *fileName)
1456{
1457    gchar *absoluteFileName = NULL;
1458    if ( g_path_is_absolute (fileName) )
1459    {
1460        absoluteFileName = g_strdup (fileName);
1461    }
1462    else
1463    {
1464        gchar *currentDir = g_get_current_dir ();
1465        absoluteFileName = g_build_filename (currentDir, fileName, NULL);
1466        g_free (currentDir);
1467    }
1468
1469    return absoluteFileName;
1470}
1471
1472//////////////////////////////////////////////////////////////////////////
1473// Main function: should we use getopts? (who doesn't?)
1474
1475int
1476main (int   argc,
1477      char *argv[])
1478{
1479  GtkWidget *window;
1480  GdkGLConfig *glconfig;
1481
1482  /* Initialize GTK. */
1483  gtk_init (&argc, &argv);
1484
1485  /* Initialize GtkGLExt. */
1486  gtk_gl_init (&argc, &argv);
1487
1488  /* Configure OpenGL framebuffer. */
1489  glconfig = configure_gl();
1490
1491  if(argc < 2)
1492    {
1493      perror("usage: pdfcube file_uri [cube_page ...]");
1494      exit(1);
1495    }
1496  gchar *absoluteFileName = get_absolute_file_name (argv[1]);
1497  gchar *filename_uri = g_filename_to_uri (absoluteFileName, NULL, NULL);
1498  g_free (absoluteFileName);
1499  if ( NULL == filename_uri )
1500    {
1501      cerr << "Errore nel nome del file" << endl;
1502    }
1503
1504  GError* g = NULL;
1505  PopplerDocument* document = 
1506    poppler_document_new_from_file(filename_uri, NULL, &g);
1507 
1508  if(g && g->code)
1509    {
1510      perror(g->message);
1511      exit(2);
1512    }
1513
1514  if(document == NULL)
1515    {
1516      perror("invaild pdf file");
1517      exit(2);
1518    }
1519 
1520  pc = new pdfcube(document);
1521 
1522  page_transition = new bool[pc->pages()];
1523 
1524  for(int ii = 0; ii < pc->pages(); ii++)   
1525    {
1526      page_transition[ii] = false;
1527    }
1528 
1529  for(int ii = 2; ii < argc; ii++)   
1530    {
1531      page_transition[atoi(argv[ii])] = true;
1532    }
1533
1534  /* Create and show the application window. */
1535  window = create_window(glconfig);
1536
1537  if(fullscreen)
1538    gtk_window_fullscreen((GtkWindow*)(window));
1539
1540  gtk_widget_show (window);
1541
1542  gtk_main ();
1543
1544  return 0;
1545}
1546
1547// EOF
1548//////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the browser.