root/tags/pdfcube-0.0.1/pdfcube.cc

Revision 1, 36.6 KB (checked in by mirko, 5 years ago)

Public release

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