ROOT logo
// @(#)root/gl:$Id$
// Author:  Richard Maunder, Olivier Couet  02/07/2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "TVirtualPad.h"
#include "TVirtualPS.h"
#include "TGLOutput.h"
#include "TGLViewer.h"
#include "TSystem.h" // For gSystem
#include "gl2ps.h"
#include "TError.h"
#include <assert.h>

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGLOutput                                                            //
//                                                                      //
// Wrapper class for GL capture & output routines                       //
//////////////////////////////////////////////////////////////////////////

ClassImp(TGLOutput)

//______________________________________________________________________________
Bool_t TGLOutput::Capture(TGLViewer & viewer, EFormat format, const char * filePath)
{
   // Capture viewer to file. Arguments are:
   // 'viewer' - viewer object to capture from
   // 'format' - output format - only postscript types presently.
   //            One of kEPS_SIMPLE, kEPS_BSP, kPDF_SIMPLE or kPDF_BSP
   //             See TGLOutput::CapturePostscript() for meanings
   // 'filePath' - file output name. If null defaults to './viewer.eps' or './viewer.pdf'
   // depending on format requested
   //
   // Note : Output files can be large and take considerable time (up to mins)
   // to generate
   switch(format) {
      case(kEPS_SIMPLE):
      case(kEPS_BSP):
      case(kPDF_SIMPLE):
      case(kPDF_BSP): {
         return CapturePostscript(viewer, format, filePath);
      }
   }

   assert(kFALSE);
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGLOutput::CapturePostscript(TGLViewer & viewer, EFormat format, const char * filePath)
{
   // Capture viewer to postscript file. Arguments are:
   // 'viewer' - viewer object to capture from
   // 'format' - output format
   //                kEPS_SIMPLE - lower quality EPS
   //                kEPS_BSP    - higher quality EPS
   //                kPDF_SIMPLE - lower quality PDF
   //                kPDF_BSP    - higher quality PDF
   // 'filePath' - file output name. If null defaults to './viewer.eps' or './viewer.pdf'
   // depending on format requested
   if (!filePath || strlen(filePath) == 0) {
      if (format == kEPS_SIMPLE || format == kEPS_BSP) {
         filePath = "viewer.eps";
      } else if (format == kPDF_SIMPLE || format == kPDF_BSP) {
         filePath = "viewer.pdf";
      }
   }
   Info("TGLOutput::Postscript()", "Start creating %s.", filePath);
   std::cout << "Please wait.";

   if (FILE *output = fopen (filePath, "w+b"))
   {
      Int_t gl2psFormat;
      Int_t gl2psSort;

      switch(format) {
         case kEPS_SIMPLE:
            gl2psFormat = GL2PS_EPS;
            gl2psSort = GL2PS_SIMPLE_SORT;
            break;
         case kEPS_BSP:
            gl2psFormat = GL2PS_EPS;
            gl2psSort = GL2PS_BSP_SORT;
            break;
         case kPDF_SIMPLE:
            gl2psFormat = GL2PS_PDF;
            gl2psSort = GL2PS_SIMPLE_SORT;
            break;
         case kPDF_BSP:
            gl2psFormat = GL2PS_PDF;
            gl2psSort = GL2PS_BSP_SORT;
            break;
         default:
            assert(kFALSE);
            return kFALSE;
      }
      Int_t buffsize = 0, state = GL2PS_OVERFLOW;
      viewer.DoDraw();
      viewer.fIsPrinting = kTRUE;
      while (state == GL2PS_OVERFLOW) {
         buffsize += 1024*1024;
         gl2psBeginPage ("ROOT Scene Graph", "ROOT", NULL,
         gl2psFormat, gl2psSort, GL2PS_USE_CURRENT_VIEWPORT
         | GL2PS_SILENT | GL2PS_BEST_ROOT | GL2PS_OCCLUSION_CULL | 0,
         GL_RGBA, 0, NULL,0, 0, 0,
         buffsize, output, NULL);
         viewer.DoDraw();
         state = gl2psEndPage();
         std::cout << ".";
      }
      std::cout << std::endl;
      fclose (output);
      viewer.fIsPrinting = kFALSE;
      if (!gSystem->AccessPathName(filePath)) {
         Info("TGLOutput::Postscript", "Finished creating %s.", filePath);
         return kTRUE;
      }
   } else {
      Error("TGLOutput::Postscript", "Failed to create %s. ", filePath);
   }

   return kFALSE;
}

//______________________________________________________________________________
void TGLOutput::StartEmbeddedPS()
{
   //this function used by gl-in-pad
   Info("TGLOutput::StartEmbeddedPS", "PS output started ...");

   gVirtualPS->PrintStr("@");
   gVirtualPS->PrintStr("% Start gl2ps EPS@");
   gVirtualPS->PrintStr("newpath gsave save@");
   Double_t xx[2] = {0.}, yy[2] = {0.};
   xx[0] = gPad->GetUxmin();
   yy[0] = gPad->GetUymin();
   xx[1] = gPad->GetUxmax();
   yy[1] = gPad->GetUymax();
   gVirtualPS->PrintStr("@");
   
///gVirtualPS->DrawPS(0, xx, yy);
///gVirtualPS->WriteInteger(4*gPad->GetBorderSize());
///gVirtualPS->PrintStr(" add exch");
///gVirtualPS->WriteInteger(4*gPad->GetBorderSize());
///gVirtualPS->PrintStr(" add exch translate");
///gVirtualPS->PrintStr("@");

   GLint vp[4];
   glGetIntegerv(GL_VIEWPORT,vp);
   gVirtualPS->DrawPS(0, xx, yy);
   gVirtualPS->PrintStr(" exch");
   xx[0] = xx[1];
   yy[0] = yy[1];
   gVirtualPS->DrawPS(0, xx, yy);
   gVirtualPS->PrintStr(" 4 1 roll exch sub 3 1 roll sub");
   gVirtualPS->WriteInteger(2*4*gPad->GetBorderSize());
   gVirtualPS->PrintStr(" sub exch");
   gVirtualPS->WriteInteger(2*4*gPad->GetBorderSize());
   gVirtualPS->PrintStr(" sub exch");
   gVirtualPS->WriteInteger((Int_t)(vp[3]));
   gVirtualPS->WriteInteger((Int_t)(vp[2]));
   gVirtualPS->PrintStr(" 4 1 roll div 3 1 roll exch div exch scale@");
   gVirtualPS->PrintStr("@");
   gVirtualPS->PrintStr("countdictstack@");
   gVirtualPS->PrintStr("mark@");
   gVirtualPS->PrintStr("/showpage {} def@");

   // Close the gVirtualPS output stream
   ofstream *fs = (ofstream*)gVirtualPS->GetStream();
   fs->close();

}

//______________________________________________________________________________
void TGLOutput::CloseEmbeddedPS()
{
   //this function used by gl-in-pad
   // Restore the gVirtualPS output stream
   ofstream *fs = new ofstream(gVirtualPS->GetName(),ios::app);
   gVirtualPS->SetStream(fs);
   gVirtualPS->PrintStr("@");
   gVirtualPS->PrintStr("cleartomark@");
   gVirtualPS->PrintStr("countdictstack exch sub { end } repeat@");
   gVirtualPS->PrintStr("restore grestore@");
   gVirtualPS->PrintStr("% End gl2ps EPS@");

   Info("TGLOutput::CloseEmbeddedPS", "PS output finished");
}

//______________________________________________________________________________
void TGLOutput::Capture(TGLViewer & viewer)
{
   //this function used by gl-viewer, embedded into pad
   StartEmbeddedPS();

   FILE *output = fopen (gVirtualPS->GetName(), "a");
   if (!output) {
      //Quite stupid fix, since if fopen fails, CloseEmbeddedPS will also
      //fail but still I have to do it.
      Error("TGLOutput::Capture", "can not open file for embedding ps");
      CloseEmbeddedPS();
      return;
   }
   
   Int_t gl2psFormat = GL2PS_EPS;
   Int_t gl2psSort = GL2PS_BSP_SORT;
   Int_t buffsize = 0, state = GL2PS_OVERFLOW;
   viewer.DoDraw();
   viewer.fIsPrinting = kTRUE;

   while (state == GL2PS_OVERFLOW) {
      buffsize += 1024*1024;
      gl2psBeginPage ("ROOT Scene Graph", "ROOT", NULL,
      gl2psFormat, gl2psSort, GL2PS_USE_CURRENT_VIEWPORT
      | GL2PS_SILENT | GL2PS_BEST_ROOT | GL2PS_OCCLUSION_CULL | 0,
      GL_RGBA, 0, NULL,0, 0, 0,
      buffsize, output, NULL);
      viewer.DoDraw();
      state = gl2psEndPage();
      std::cout << ".";
   }

   std::cout << std::endl;
   fclose (output);
   viewer.fIsPrinting = kFALSE;

   CloseEmbeddedPS();
}
 TGLOutput.cxx:1
 TGLOutput.cxx:2
 TGLOutput.cxx:3
 TGLOutput.cxx:4
 TGLOutput.cxx:5
 TGLOutput.cxx:6
 TGLOutput.cxx:7
 TGLOutput.cxx:8
 TGLOutput.cxx:9
 TGLOutput.cxx:10
 TGLOutput.cxx:11
 TGLOutput.cxx:12
 TGLOutput.cxx:13
 TGLOutput.cxx:14
 TGLOutput.cxx:15
 TGLOutput.cxx:16
 TGLOutput.cxx:17
 TGLOutput.cxx:18
 TGLOutput.cxx:19
 TGLOutput.cxx:20
 TGLOutput.cxx:21
 TGLOutput.cxx:22
 TGLOutput.cxx:23
 TGLOutput.cxx:24
 TGLOutput.cxx:25
 TGLOutput.cxx:26
 TGLOutput.cxx:27
 TGLOutput.cxx:28
 TGLOutput.cxx:29
 TGLOutput.cxx:30
 TGLOutput.cxx:31
 TGLOutput.cxx:32
 TGLOutput.cxx:33
 TGLOutput.cxx:34
 TGLOutput.cxx:35
 TGLOutput.cxx:36
 TGLOutput.cxx:37
 TGLOutput.cxx:38
 TGLOutput.cxx:39
 TGLOutput.cxx:40
 TGLOutput.cxx:41
 TGLOutput.cxx:42
 TGLOutput.cxx:43
 TGLOutput.cxx:44
 TGLOutput.cxx:45
 TGLOutput.cxx:46
 TGLOutput.cxx:47
 TGLOutput.cxx:48
 TGLOutput.cxx:49
 TGLOutput.cxx:50
 TGLOutput.cxx:51
 TGLOutput.cxx:52
 TGLOutput.cxx:53
 TGLOutput.cxx:54
 TGLOutput.cxx:55
 TGLOutput.cxx:56
 TGLOutput.cxx:57
 TGLOutput.cxx:58
 TGLOutput.cxx:59
 TGLOutput.cxx:60
 TGLOutput.cxx:61
 TGLOutput.cxx:62
 TGLOutput.cxx:63
 TGLOutput.cxx:64
 TGLOutput.cxx:65
 TGLOutput.cxx:66
 TGLOutput.cxx:67
 TGLOutput.cxx:68
 TGLOutput.cxx:69
 TGLOutput.cxx:70
 TGLOutput.cxx:71
 TGLOutput.cxx:72
 TGLOutput.cxx:73
 TGLOutput.cxx:74
 TGLOutput.cxx:75
 TGLOutput.cxx:76
 TGLOutput.cxx:77
 TGLOutput.cxx:78
 TGLOutput.cxx:79
 TGLOutput.cxx:80
 TGLOutput.cxx:81
 TGLOutput.cxx:82
 TGLOutput.cxx:83
 TGLOutput.cxx:84
 TGLOutput.cxx:85
 TGLOutput.cxx:86
 TGLOutput.cxx:87
 TGLOutput.cxx:88
 TGLOutput.cxx:89
 TGLOutput.cxx:90
 TGLOutput.cxx:91
 TGLOutput.cxx:92
 TGLOutput.cxx:93
 TGLOutput.cxx:94
 TGLOutput.cxx:95
 TGLOutput.cxx:96
 TGLOutput.cxx:97
 TGLOutput.cxx:98
 TGLOutput.cxx:99
 TGLOutput.cxx:100
 TGLOutput.cxx:101
 TGLOutput.cxx:102
 TGLOutput.cxx:103
 TGLOutput.cxx:104
 TGLOutput.cxx:105
 TGLOutput.cxx:106
 TGLOutput.cxx:107
 TGLOutput.cxx:108
 TGLOutput.cxx:109
 TGLOutput.cxx:110
 TGLOutput.cxx:111
 TGLOutput.cxx:112
 TGLOutput.cxx:113
 TGLOutput.cxx:114
 TGLOutput.cxx:115
 TGLOutput.cxx:116
 TGLOutput.cxx:117
 TGLOutput.cxx:118
 TGLOutput.cxx:119
 TGLOutput.cxx:120
 TGLOutput.cxx:121
 TGLOutput.cxx:122
 TGLOutput.cxx:123
 TGLOutput.cxx:124
 TGLOutput.cxx:125
 TGLOutput.cxx:126
 TGLOutput.cxx:127
 TGLOutput.cxx:128
 TGLOutput.cxx:129
 TGLOutput.cxx:130
 TGLOutput.cxx:131
 TGLOutput.cxx:132
 TGLOutput.cxx:133
 TGLOutput.cxx:134
 TGLOutput.cxx:135
 TGLOutput.cxx:136
 TGLOutput.cxx:137
 TGLOutput.cxx:138
 TGLOutput.cxx:139
 TGLOutput.cxx:140
 TGLOutput.cxx:141
 TGLOutput.cxx:142
 TGLOutput.cxx:143
 TGLOutput.cxx:144
 TGLOutput.cxx:145
 TGLOutput.cxx:146
 TGLOutput.cxx:147
 TGLOutput.cxx:148
 TGLOutput.cxx:149
 TGLOutput.cxx:150
 TGLOutput.cxx:151
 TGLOutput.cxx:152
 TGLOutput.cxx:153
 TGLOutput.cxx:154
 TGLOutput.cxx:155
 TGLOutput.cxx:156
 TGLOutput.cxx:157
 TGLOutput.cxx:158
 TGLOutput.cxx:159
 TGLOutput.cxx:160
 TGLOutput.cxx:161
 TGLOutput.cxx:162
 TGLOutput.cxx:163
 TGLOutput.cxx:164
 TGLOutput.cxx:165
 TGLOutput.cxx:166
 TGLOutput.cxx:167
 TGLOutput.cxx:168
 TGLOutput.cxx:169
 TGLOutput.cxx:170
 TGLOutput.cxx:171
 TGLOutput.cxx:172
 TGLOutput.cxx:173
 TGLOutput.cxx:174
 TGLOutput.cxx:175
 TGLOutput.cxx:176
 TGLOutput.cxx:177
 TGLOutput.cxx:178
 TGLOutput.cxx:179
 TGLOutput.cxx:180
 TGLOutput.cxx:181
 TGLOutput.cxx:182
 TGLOutput.cxx:183
 TGLOutput.cxx:184
 TGLOutput.cxx:185
 TGLOutput.cxx:186
 TGLOutput.cxx:187
 TGLOutput.cxx:188
 TGLOutput.cxx:189
 TGLOutput.cxx:190
 TGLOutput.cxx:191
 TGLOutput.cxx:192
 TGLOutput.cxx:193
 TGLOutput.cxx:194
 TGLOutput.cxx:195
 TGLOutput.cxx:196
 TGLOutput.cxx:197
 TGLOutput.cxx:198
 TGLOutput.cxx:199
 TGLOutput.cxx:200
 TGLOutput.cxx:201
 TGLOutput.cxx:202
 TGLOutput.cxx:203
 TGLOutput.cxx:204
 TGLOutput.cxx:205
 TGLOutput.cxx:206
 TGLOutput.cxx:207
 TGLOutput.cxx:208
 TGLOutput.cxx:209
 TGLOutput.cxx:210
 TGLOutput.cxx:211
 TGLOutput.cxx:212
 TGLOutput.cxx:213
 TGLOutput.cxx:214
 TGLOutput.cxx:215
 TGLOutput.cxx:216
 TGLOutput.cxx:217
 TGLOutput.cxx:218
 TGLOutput.cxx:219
 TGLOutput.cxx:220
 TGLOutput.cxx:221
 TGLOutput.cxx:222
 TGLOutput.cxx:223
 TGLOutput.cxx:224
 TGLOutput.cxx:225
 TGLOutput.cxx:226
 TGLOutput.cxx:227
 TGLOutput.cxx:228
 TGLOutput.cxx:229
 TGLOutput.cxx:230
 TGLOutput.cxx:231
 TGLOutput.cxx:232
 TGLOutput.cxx:233
 TGLOutput.cxx:234
 TGLOutput.cxx:235
 TGLOutput.cxx:236