<commit_before>// @(#)root/postscript:$Id: TPDF.cxx,v 1.0
// Author: <NAME>

/*************************************************************************
 * Copyright (C) 1995-2000, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPDF                                                                 //
//                                                                      //
// Graphics interface to PDF.                                           //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifdef WIN32
#pragma optimize("",off)
#endif

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "Riostream.h"
#include "TROOT.h"
#include "TColor.h"
#include "TVirtualPad.h"
#include "TPoints.h"
#include "TPDF.h"
#include "TStyle.h"
#include "TMath.h"
#include "TStorage.h"
#include "TText.h"
#include "zlib.h"
#include "TObjString.h"
#include "TClass.h"
#include "TObjArray.h"

// To scale fonts to the same size as the old TT version
const Float_t kScale = 0.93376068;

// Objects numbers
const Int_t kObjRoot             =  1; // Root object
const Int_t kObjInfo             =  2; // Info object
const Int_t kObjOutlines         =  3; // Outlines object
const Int_t kObjPages            =  4; // Pages object (pages index)
const Int_t kObjPageResources    =  5; // Pages Resources object
const Int_t kObjFont             =  6; // First Font object (14 in total)
const Int_t kObjColorSpace       = 21; // ColorSpace object
const Int_t kObjPatternResourses = 22; // Pattern Resources object
const Int_t kObjPatternList      = 23; // Pattern list object
const Int_t kObjPattern          = 24; // Pattern object
const Int_t kObjFirstPage        = 49; // First page object

// Number of fonts
const Int_t kNumberOfFonts = 15;

ClassImp(TPDF)


//______________________________________________________________________________
//
// PDF driver
//


//______________________________________________________________________________
TPDF::TPDF() : TVirtualPS()
{
   // Default PDF constructor

   fStream          = 0;
   fCompress        = kFALSE;
   gVirtualPS       = this;
   fRed             = 0.;
   fGreen           = 0.;
   fBlue            = 0.;
   fXsize           = 0.;
   fYsize           = 0.;
   fType            = 0;
   fPageFormat      = 0;
   fPageOrientation = 0;
   fStartStream     = 0;
   fLineScale       = 0.;
   fObjPosSize      = 0;
   fNbObj           = 0;
   fNbPage          = 0;
   fRange           = kFALSE;
}


//______________________________________________________________________________
TPDF::TPDF(const char *fname, Int_t wtype) : TVirtualPS(fname, wtype)
{
   // Initialize the PDF interface
   //
   //  fname : PDF file name
   //  wtype : PDF workstation type. Not used in the PDF driver. But as TPDF
   //          inherits from TVirtualPS it should be kept. Anyway it is not
   //          necessary to specify this parameter at creation time because it
   //          has a default value (which is ignore in the PDF case).

   fStream          = 0;
   fCompress        = kFALSE;
   fRed             = 0.;
   fGreen           = 0.;
   fBlue            = 0.;
   fXsize           = 0.;
   fYsize           = 0.;
   fType            = 0;
   fPageFormat      = 0;
   fPageOrientation = 0;
   fStartStream     = 0;
   fLineScale       = 0.;
   fObjPosSize      = 0;
   fNbObj           = 0;
   fNbPage          = 0;
   fRange           = kFALSE;
   Open(fname, wtype);
}


//______________________________________________________________________________
TPDF::~TPDF()
{
   // Default PDF destructor

   Close();

   if (fObjPos) delete [] fObjPos;
}


//______________________________________________________________________________
void TPDF::CellArrayBegin(Int_t, Int_t, Double_t, Double_t, Double_t,
                          Double_t)
{
   // Begin the Cell Array painting
   Warning("TPDF::CellArrayBegin", "not yet implemented");
}


//______________________________________________________________________________
void TPDF::CellArrayFill(Int_t, Int_t, Int_t)
{
   // Paint the Cell Array
   Warning("TPDF::CellArrayFill", "not yet implemented");
}


//______________________________________________________________________________
void TPDF::CellArrayEnd()
{
   // End the Cell Array painting
   Warning("TPDF::CellArrayEnd", "not yet implemented");
}


//______________________________________________________________________________
void TPDF::Close(Option_t *)
{
   // Close a PDF file

   Int_t i;

   if (!gVirtualPS) return;
   if (!fStream) return;
   if (gPad) gPad->Update();

   // Close the currently opened page
   WriteCompressedBuffer();
   PrintStr("endstream@");
   Int_t streamLength = fNByte-fStartStream-10;
   PrintStr("endobj@");
   NewObject(3*(fNbPage-1)+kObjFirstPage+2);
   WriteInteger(streamLength, 0);
   PrintStr("@");
   PrintStr("endobj@");

   // List of all the pages
   NewObject(kObjPages);
   PrintStr("<<@");
   PrintStr("/Type /Pages@");
   PrintStr("/Count");
   WriteInteger(fNbPage);
   PrintStr("@");
   PrintStr("/Kids [");
   for (i=1; i<=fNbPage; i++) {
      WriteInteger(3*(i-1)+kObjFirstPage);
      PrintStr(" 0 R");
   }
   PrintStr(" ]");
   PrintStr("@");
   PrintStr(">>@");
   PrintStr("endobj@");

   // Cross-Reference Table
   Int_t refInd = fNByte;
   PrintStr("xref@");
   PrintStr("0");
   WriteInteger(fNbObj+1);
   PrintStr("@");
   PrintStr("0000000000 65535 f @");
   char str[21];
   for (i=0; i<fNbObj; i++) {
      sprintf(str,"%10.10d 00000 n @",fObjPos[i]);
      PrintStr(str);
   }

   // Trailer
   PrintStr("trailer@");
   PrintStr("<<@");
   PrintStr("/Size");
   WriteInteger(fNbObj+1);
   PrintStr("@");
   PrintStr("/Root");
   WriteInteger(kObjRoot);
   PrintStr(" 0 R");
   PrintStr("@");
   PrintStr("/Info");
   WriteInteger(kObjInfo);
   PrintStr(" 0 R");
   PrintStr(">>@");
   PrintStr("startxref@");
   WriteInteger(refInd, 0);
   PrintStr("@");
   PrintStr("%%EOF@");

   // Close file stream
   if (fStream) { fStream->close(); delete fStream; fStream = 0;}

   gVirtualPS = 0;
}


//______________________________________________________________________________
void TPDF::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t  y2)
{
   // Draw a Box

   static Double_t x[4], y[4];
   Double_t ix1 = XtoPDF(x1);
   Double_t ix2 = XtoPDF(x2);
   Double_t iy1 = YtoPDF(y1);
   Double_t iy2 = YtoPDF(y2);
   Int_t fillis = fFillStyle/1000;
   Int_t fillsi = fFillStyle%1000;

   if (fillis == 3 || fillis == 2) {
      if (fillsi > 99) {
         x[0] = x1;   y[0] = y1;
         x[1] = x2;   y[1] = y1;
         x[2] = x2;   y[2] = y2;
         x[3] = x1;   y[3] = y2;
         return;
      }
      if (fillsi > 0 && fillsi < 26) {
         x[0] = x1;   y[0] = y1;
         x[1] = x2;   y[1] = y1;
         x[2] = x2;   y[2] = y2;
         x[3] = x1;   y[3] = y2;
         DrawPS(-4, &x[0], &y[0]);
      }
      if (fillsi == -3) {
         SetColor(5);
         WriteReal(ix1);
         WriteReal(iy1);
         WriteReal(ix2 - ix1);
         WriteReal(iy2 - iy1);
         PrintFast(6," re f*");
      }
   }
   if (fillis == 1) {
      SetColor(fFillColor);
      WriteReal(ix1);
      WriteReal(iy1);
      WriteReal(ix2 - ix1);
      WriteReal(iy2 - iy1);
      PrintFast(6," re f*");
   }
   if (fillis == 0) {
      SetColor(fLineColor);
      WriteReal(ix1);
      WriteReal(iy1);
      WriteReal(ix2 - ix1);
      WriteReal(iy2 - iy1);
      PrintFast(5," re S");
   }
}


//______________________________________________________________________________
void TPDF::DrawFrame(Double_t xl, Double_t yl, Double_t xt, Double_t  yt,
                            Int_t mode, Int_t border, Int_t dark, Int_t light)
{
   // Draw a Frame around a box
   //
   // mode = -1  box looks as it is behind the screen
   // mode =  1  box looks as it is in front of the screen
   // border is the border size in already precomputed PDF units
   // dark  is the color for the dark part of the frame
   // light is the color for the light part of the frame

   static Double_t xps[7], yps[7];
   Int_t i;

   // Draw top&left part of the box
   if (mode == -1) SetColor(dark);
   else            SetColor(light);
   xps[0] = XtoPDF(xl);          yps[0] = YtoPDF(yl);
   xps[1] = xps[0] + border;     yps[1] = yps[0] + border;
   xps[2] = xps[1];              yps[2] = YtoPDF(yt) - border;
   xps[3] = XtoPDF(xt) - border; yps[3] = yps[2];
   xps[4] = XtoPDF(xt);          yps[4] = YtoPDF(yt);
   xps[5] = xps[0];              yps[5] = yps[4];
   xps[6] = xps[0];              yps[6] = yps[0];

   MoveTo(xps[0], yps[0]);
   for (i=1;i<7;i++) LineTo(xps[i], yps[i]);
   PrintFast(3," f*");

   // Draw bottom&right part of the box
   if (mode == -1) SetColor(light);
   else            SetColor(dark);
   xps[0] = XtoPDF(xl);          yps[0] = YtoPDF(yl);
   xps[1] = xps[0] + border;     yps[1] = yps[0] + border;
   xps[2] = XtoPDF(xt) - border; yps[2] = yps[1];
   xps[3] = xps[2];              yps[3] = YtoPDF(yt) - border;
   xps[4] = XtoPDF(xt);          yps[4] = YtoPDF(yt);
   xps[5] = xps[4];              yps[5] = yps[0];
   xps[6] = xps[0];              yps[6] = yps[0];

   MoveTo(xps[0], yps[0]);
   for (i=1;i<7;i++) LineTo(xps[i], yps[i]);
   PrintFast(3," f*");
}


//______________________________________________________________________________
void TPDF::DrawHatch(Float_t, Float_t, Int_t, Float_t *, Float_t *)
{
   // Draw Fill area with hatch styles

   Warning("DrawHatch", "hatch fill style not yet implemented");
}


//______________________________________________________________________________
void TPDF::DrawHatch(Float_t, Float_t, Int_t, Double_t *, Double_t *)
{
   // Draw Fill area with hatch styles

   Warning("DrawHatch", "hatch fill style not yet implemented");
}


//______________________________________________________________________________
void TPDF::DrawPolyLine(Int_t nn, TPoints *xy)
{
   // Draw a PolyLine
   //
   //  Draw a polyline through  the points xy.
   //  If NN=1 moves only to point x,y.
   //  If NN=0 the x,y are  written  in the PDF file
   //     according to the current transformation.
   //  If NN>0 the line is clipped as a line.
   //  If NN<0 the line is clipped as a fill area.

   Int_t  n;

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;

   if (nn > 0) {
      n = nn;
      SetLineStyle(fLineStyle);
      SetLineWidth(fLineWidth);
      SetColor(Int_t(fLineColor));
   } else {
      n = -nn;
      SetLineStyle(1);
      SetLineWidth(1);
      SetColor(Int_t(fLineColor));
   }

   WriteReal(XtoPDF(xy[0].GetX()));
   WriteReal(YtoPDF(xy[0].GetY()));
   if( n <= 1) {
      if( n == 0) return;
      PrintFast(2," m");
      return;
   }

   PrintFast(2," m");

   for (Int_t i=1;i<n;i++) LineTo(XtoPDF(xy[i].GetX()), YtoPDF(xy[i].GetY()));

   if (nn > 0 ) {
      if (xy[0].GetX() == xy[n-1].GetX() && xy[0].GetY() == xy[n-1].GetY()) PrintFast(3," cl");
      PrintFast(2," S");
   } else {
      PrintFast(3," f*");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPolyLineNDC(Int_t nn, TPoints *xy)
{
   // Draw a PolyLine in NDC space
   //
   //  Draw a polyline through  the points  xy.
   //  If NN=1 moves only to point x,y.
   //  If NN=0 the x,y are  written  in the PDF        file
   //     according to the current transformation.
   //  If NN>0 the line is clipped as a line.
   //  If NN<0 the line is clipped as a fill area.

   Int_t  n;

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;

   if (nn > 0) {
      n = nn;
      SetLineStyle(fLineStyle);
      SetLineWidth(fLineWidth);
      SetColor(Int_t(fLineColor));
   } else {
      n = -nn;
      SetLineStyle(1);
      SetLineWidth(1);
      SetColor(Int_t(fLineColor));
   }

   WriteReal(UtoPDF(xy[0].GetX()));
   WriteReal(VtoPDF(xy[0].GetY()));
   if( n <= 1) {
      if( n == 0) return;
      PrintFast(2," m");
      return;
   }

   PrintFast(2," m");

   for (Int_t i=1;i<n;i++) LineTo(UtoPDF(xy[i].GetX()), VtoPDF(xy[i].GetY()));

   if (nn > 0 ) {
      if (xy[0].GetX() == xy[n-1].GetX() && xy[0].GetY() == xy[n-1].GetY()) PrintFast(3," cl");
      PrintFast(2," S");
   } else {
      PrintFast(3," f*");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPolyMarker(Int_t n, Float_t *xw, Float_t *yw)
{
   // Draw markers at the n WC points xw, yw

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;
   SetLineStyle(1);
   SetLineWidth(1);
   SetColor(Int_t(fMarkerColor));
   Int_t ms = abs(fMarkerStyle);

   if (ms >= 6 && ms <= 19) ms = 20;
   if (ms == 4) ms = 24;

   // Define the marker size
   Float_t msize  = fMarkerSize;
   if (fMarkerStyle == 1) {
     msize = 1.;
   } else if (fMarkerStyle == 6) {
     msize = 1.5;
   } else if (fMarkerStyle == 7) {
     msize = 3.;
   } else {
      const Int_t kBASEMARKER = 8;
      Float_t sbase = msize*kBASEMARKER;
      Float_t s2x = sbase / Float_t(gPad->GetWw() * gPad->GetAbsWNDC());
      msize = this->UtoPDF(s2x) - this->UtoPDF(0);
   }

   Double_t m  = msize;
   Double_t m2 = m/2;
   Double_t m3 = m/3;
   Double_t m4 = m2*1.333333333333;
   Double_t m6 = m/6;

   // Draw the marker according to the type
   Double_t ix,iy;
   for (Int_t i=0;i<n;i++) {
      ix = XtoPDF(xw[i]);
      iy = YtoPDF(yw[i]);
      // Dot (.)
      if (ms == 1) {
         MoveTo(ix-1, iy);
         LineTo(ix  , iy);
      // Plus (+)
      } else if (ms == 2) {
         MoveTo(ix-m2, iy);
         LineTo(ix+m2, iy);
         MoveTo(ix   , iy-m2);
         LineTo(ix   , iy+m2);
      // X shape (X)
      } else if (ms == 5) {
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy+m2);
         MoveTo(ix-m2, iy+m2);
         LineTo(ix+m2, iy-m2);
      // Asterisk shape (*)
      } else if (ms == 3 || ms == 31) {
         MoveTo(ix-m2, iy);
         LineTo(ix+m2, iy);
         MoveTo(ix   , iy-m2);
         LineTo(ix   , iy+m2);
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy+m2);
         MoveTo(ix-m2, iy+m2);
         LineTo(ix+m2, iy-m2);
      // Circle
      } else if (ms == 24 || ms == 20) {
         MoveTo(ix-m2, iy);
         WriteReal(ix-m2); WriteReal(iy+m4);
         WriteReal(ix+m2); WriteReal(iy+m4);
         WriteReal(ix+m2); WriteReal(iy)   ; PrintFast(2," c");
         WriteReal(ix+m2); WriteReal(iy-m4);
         WriteReal(ix-m2); WriteReal(iy-m4);
         WriteReal(ix-m2); WriteReal(iy)   ; PrintFast(4," c h");
      // Square
      } else if (ms == 25 || ms == 21) {
         WriteReal(ix-m2); WriteReal(iy-m2);
         WriteReal(m)    ; WriteReal(m)    ; PrintFast(3," re");
      // Down triangle
      } else if (ms == 23 || ms == 32) {
         MoveTo(ix   , iy-m2);
         LineTo(ix+m2, iy+m2);
         LineTo(ix-m2, iy+m2);
         PrintFast(2," h");
      // Up triangle
      } else if (ms == 26 || ms == 22) {
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy-m2);
         LineTo(ix   , iy+m2);
         PrintFast(2," h");
      } else if (ms == 27 || ms == 33) {
         MoveTo(ix   , iy-m2);
         LineTo(ix+m3, iy);
         LineTo(ix   , iy+m2);
         LineTo(ix-m3, iy)   ;
         PrintFast(2," h");
      } else if (ms == 28 || ms == 34) {
         MoveTo(ix-m6, iy-m6);
         LineTo(ix-m6, iy-m2);
         LineTo(ix+m6, iy-m2);
         LineTo(ix+m6, iy-m6);
         LineTo(ix+m2, iy-m6);
         LineTo(ix+m2, iy+m6);
         LineTo(ix+m6, iy+m6);
         LineTo(ix+m6, iy+m2);
         LineTo(ix-m6, iy+m2);
         LineTo(ix-m6, iy+m6);
         LineTo(ix-m2, iy+m6);
         LineTo(ix-m2, iy-m6);
         PrintFast(2," h");
      } else if (ms == 29 || ms == 30) {
         MoveTo(ix           , iy+m2);
         LineTo(ix+0.112255*m, iy+0.15451*m);
         LineTo(ix+0.47552*m , iy+0.15451*m);
         LineTo(ix+0.181635*m, iy-0.05902*m);
         LineTo(ix+0.29389*m , iy-0.40451*m);
         LineTo(ix           , iy-0.19098*m);
         LineTo(ix-0.29389*m , iy-0.40451*m);
         LineTo(ix-0.181635*m, iy-0.05902*m);
         LineTo(ix-0.47552*m , iy+0.15451*m);
         LineTo(ix-0.112255*m, iy+0.15451*m);
         PrintFast(2," h");
      } else {
         MoveTo(ix-1, iy);
         LineTo(ix  , iy);
      }
   }

   if ((ms > 19 && ms < 24) || ms == 29 || ms == 33 || ms == 34) {
      PrintFast(2," f");
   } else {
      PrintFast(2," S");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPolyMarker(Int_t n, Double_t *xw, Double_t *yw)
{
   // Draw markers at the n WC points xw, yw

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;
   SetLineStyle(1);
   SetLineWidth(1);
   SetColor(Int_t(fMarkerColor));
   Int_t ms = abs(fMarkerStyle);

   if (ms >= 6 && ms <= 19) ms = 20;
   if (ms == 4) ms = 24;

   // Define the marker size
   Float_t msize  = fMarkerSize;
   if (fMarkerStyle == 1) {
     msize = 1.;
   } else if (fMarkerStyle == 6) {
     msize = 1.5;
   } else if (fMarkerStyle == 7) {
     msize = 3.;
   } else {
      const Int_t kBASEMARKER = 8;
      Float_t sbase = msize*kBASEMARKER;
      Float_t s2x = sbase / Float_t(gPad->GetWw() * gPad->GetAbsWNDC());
      msize = this->UtoPDF(s2x) - this->UtoPDF(0);
   }

   Double_t m  = msize;
   Double_t m2 = m/2;
   Double_t m3 = m/3;
   Double_t m4 = m2*1.333333333333;
   Double_t m6 = m/6;

   // Draw the marker according to the type
   Double_t ix,iy;
   for (Int_t i=0;i<n;i++) {
      ix = XtoPDF(xw[i]);
      iy = YtoPDF(yw[i]);
      // Dot (.)
      if (ms == 1) {
         MoveTo(ix-1, iy);
         LineTo(ix  , iy);
      // Plus (+)
      } else if (ms == 2) {
         MoveTo(ix-m2, iy);
         LineTo(ix+m2, iy);
         MoveTo(ix   , iy-m2);
         LineTo(ix   , iy+m2);
      // X shape (X)
      } else if (ms == 5) {
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy+m2);
         MoveTo(ix-m2, iy+m2);
         LineTo(ix+m2, iy-m2);
      // Asterisk shape (*)
      } else if (ms == 3 || ms == 31) {
         MoveTo(ix-m2, iy);
         LineTo(ix+m2, iy);
         MoveTo(ix   , iy-m2);
         LineTo(ix   , iy+m2);
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy+m2);
         MoveTo(ix-m2, iy+m2);
         LineTo(ix+m2, iy-m2);
      // Circle
      } else if (ms == 24 || ms == 20) {
         MoveTo(ix-m2, iy);
         WriteReal(ix-m2); WriteReal(iy+m4);
         WriteReal(ix+m2); WriteReal(iy+m4);
         WriteReal(ix+m2); WriteReal(iy)   ; PrintFast(2," c");
         WriteReal(ix+m2); WriteReal(iy-m4);
         WriteReal(ix-m2); WriteReal(iy-m4);
         WriteReal(ix-m2); WriteReal(iy)   ; PrintFast(4," c h");
      // Square
      } else if (ms == 25 || ms == 21) {
         WriteReal(ix-m2); WriteReal(iy-m2);
         WriteReal(m)    ; WriteReal(m)    ; PrintFast(3," re");
      // Down triangle
      } else if (ms == 23 || ms == 32) {
         MoveTo(ix   , iy-m2);
         LineTo(ix+m2, iy+m2);
         LineTo(ix-m2, iy+m2);
         PrintFast(2," h");
      // Up triangle
      } else if (ms == 26 || ms == 22) {
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy-m2);
         LineTo(ix   , iy+m2);
         PrintFast(2," h");
      } else if (ms == 27 || ms == 33) {
         MoveTo(ix   , iy-m2);
         LineTo(ix+m3, iy);
         LineTo(ix   , iy+m2);
         LineTo(ix-m3, iy)   ;
         PrintFast(2," h");
      } else if (ms == 28 || ms == 34) {
         MoveTo(ix-m6, iy-m6);
         LineTo(ix-m6, iy-m2);
         LineTo(ix+m6, iy-m2);
         LineTo(ix+m6, iy-m6);
         LineTo(ix+m2, iy-m6);
         LineTo(ix+m2, iy+m6);
         LineTo(ix+m6, iy+m6);
         LineTo(ix+m6, iy+m2);
         LineTo(ix-m6, iy+m2);
         LineTo(ix-m6, iy+m6);
         LineTo(ix-m2, iy+m6);
         LineTo(ix-m2, iy-m6);
         PrintFast(2," h");
      } else if (ms == 29 || ms == 30) {
         MoveTo(ix           , iy+m2);
         LineTo(ix+0.112255*m, iy+0.15451*m);
         LineTo(ix+0.47552*m , iy+0.15451*m);
         LineTo(ix+0.181635*m, iy-0.05902*m);
         LineTo(ix+0.29389*m , iy-0.40451*m);
         LineTo(ix           , iy-0.19098*m);
         LineTo(ix-0.29389*m , iy-0.40451*m);
         LineTo(ix-0.181635*m, iy-0.05902*m);
         LineTo(ix-0.47552*m , iy+0.15451*m);
         LineTo(ix-0.112255*m, iy+0.15451*m);
         PrintFast(2," h");
      } else {
         MoveTo(ix-1, iy);
         LineTo(ix  , iy);
      }
   }

   if ((ms > 19 && ms < 24) || ms == 29 || ms == 33 || ms == 34) {
      PrintFast(2," f");
   } else {
      PrintFast(2," S");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPS(Int_t nn, Float_t *xw, Float_t *yw)
{
   // Draw a PolyLine
   //
   //  Draw a polyline through the points xw,yw.
   //  If nn=1 moves only to point xw,yw.
   //  If nn=0 the XW(1) and YW(1) are  written  in the PDF file
   //          according to the current NT.
   //  If nn>0 the line is clipped as a line.
   //  If nn<0 the line is clipped as a fill area.

   static Float_t dyhatch[24] = {.0075,.0075,.0075,.0075,.0075,.0075,.0075,.0075,
                                 .01  ,.01  ,.01  ,.01  ,.01  ,.01  ,.01  ,.01  ,
                                 .015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015};
   static Float_t anglehatch[24] = {180, 90,135, 45,150, 30,120, 60,
                                    180, 90,135, 45,150, 30,120, 60,
                                    180, 90,135, 45,150, 30,120, 60};
   Int_t  n = 0, fais = 0 , fasi = 0;

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;

   if (nn > 0) {
      n = nn;
      SetLineStyle(fLineStyle);
      SetLineWidth(fLineWidth);
      SetColor(Int_t(fLineColor));
   }
   if (nn < 0) {
      n = -nn;
      SetLineStyle(1);
      SetLineWidth(1);
      SetColor(Int_t(fFillColor));
      fais = fFillStyle/1000;
      fasi = fFillStyle%1000;
      if (fais == 3 || fais == 2) {
         if (fasi > 100 && fasi <125) {
            DrawHatch(dyhatch[fasi-101],anglehatch[fasi-101], n, xw, yw);
            SetLineStyle(linestylesav);
            SetLineWidth(linewidthsav);
            return;
         }
         if (fasi > 0 && fasi < 26) {
            SetFillPatterns(fasi, Int_t(fFillColor));
         }
      }
   }

   WriteReal(XtoPDF(xw[0]));
   WriteReal(YtoPDF(yw[0]));
   if( n <= 1) {
      if( n == 0) return;
      PrintFast(2," m");
      return;
   }

   PrintFast(2," m");

   for (Int_t i=1;i<n;i++) LineTo(XtoPDF(xw[i]), YtoPDF(yw[i]));

   if (nn > 0 ) {
      if (xw[0] == xw[n-1] && yw[0] == yw[n-1]) PrintFast(2," h");
      PrintFast(2," S");
   } else {
      if (fais == 0) {PrintFast(2," s"); return;}
      if (fais == 3 || fais == 2) {
         if (fasi > 0 && fasi < 26) {
            PrintFast(3," f*");
            fRed   = -1;
            fGreen = -1;
            fBlue  = -1;
         }
         SetLineStyle(linestylesav);
         SetLineWidth(linewidthsav);
         return;
      }
      PrintFast(3," f*");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPS(Int_t nn, Double_t *xw, Double_t *yw)
{
   // Draw a PolyLine
   //
   // Draw a polyline through  the points xw,yw.
   // If nn=1 moves only to point xw,yw.
   // If nn=0 the xw(1) and YW(1) are  written  in the PDF file
   //         according to the current NT.
   // If nn>0 the line is clipped as a line.
   // If nn<0 the line is clipped as a fill area.

   static Float_t dyhatch[24] = {.0075,.0075,.0075,.0075,.0075,.0075,.0075,.0075,
                                 .01  ,.01  ,.01  ,.01  ,.01  ,.01  ,.01  ,.01  ,
                                 .015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015};
   static Float_t anglehatch[24] = {180, 90,135, 45,150, 30,120, 60,
                                    180, 90,135, 45,150, 30,120, 60,
                                    180, 90,135, 45,150, 30,120, 60};
   Int_t  n = 0, fais = 0, fasi = 0;

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;

   if (nn > 0) {
      n = nn;
      SetLineStyle(fLineStyle);
      SetLineWidth(fLineWidth);
      SetColor(Int_t(fLineColor));
   }
   if (nn < 0) {
      n = -nn;
      SetLineStyle(1);
      SetLineWidth(1);
      SetColor(Int_t(fFillColor));
      fais = fFillStyle/1000;
      fasi = fFillStyle%1000;
      if (fais == 3 || fais == 2) {
         if (fasi > 100 && fasi <125) {
            DrawHatch(dyhatch[fasi-101],anglehatch[fasi-101], n, xw, yw);
            SetLineStyle(linestylesav);
            SetLineWidth(linewidthsav);
            return;
         }
         if (fasi > 0 && fasi < 26) {
            SetFillPatterns(fasi, Int_t(fFillColor));
         }
      }
   }

   WriteReal(XtoPDF(xw[0]));
   WriteReal(YtoPDF(yw[0]));
   if( n <= 1) {
      if( n == 0) return;
      PrintFast(2," m");
      return;
   }

   PrintFast(2," m");

   for (Int_t i=1;i<n;i++) LineTo(XtoPDF(xw[i]), YtoPDF(yw[i]));

   if (nn > 0 ) {
      if (xw[0] == xw[n-1] && yw[0] == yw[n-1]) PrintFast(2," h");
      PrintFast(2," S");
   } else {
      if (fais == 0) {PrintFast(2," s"); return;}
      if (fais == 3 || fais == 2) {
         if (fasi > 0 && fasi < 26) {
            PrintFast(3," f*");
            fRed   = -1;
            fGreen = -1;
            fBlue  = -1;
         }
         SetLineStyle(linestylesav);
         SetLineWidth(linewidthsav);
         return;
      }
      PrintFast(3," f*");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::FontEncode()
{
   // Font encoding

   static const char *sdtfonts[] = {
   "/Times-Italic"         , "/Times-Bold"         , "/Times-BoldItalic",
   "/Helvetica"            , "/Helvetica-Oblique"  , "/Helvetica-Bold"  ,
   "/Helvetica-BoldOblique", "/Courier"            , "/Courier-Oblique" ,
   "/Courier-Bold"         , "/Courier-BoldOblique", "/Symbol"          ,
   "/Times-Roman"          , "/ZapfDingbats"       , "/Symbol"};

   for (Int_t i=0; i<kNumberOfFonts; i++) {
      NewObject(kObjFont+i);
      PrintStr("<<@");
      PrintStr("/Type /Font@");
      PrintStr("/Subtype /Type1@");
      PrintStr("/Name /F");
      WriteInteger(i+1,0);
      PrintStr("@");
      PrintStr("/BaseFont ");
      PrintStr(sdtfonts[i]);
      PrintStr("@");
      if (i!=11 && i!=13 && i!=14) {
         PrintStr("/Encoding /WinAnsiEncoding");
         PrintStr("@");
      }
      PrintStr(">>@");
      PrintStr("endobj@");
   }
}


//______________________________________________________________________________
void TPDF::LineTo(Double_t x, Double_t y)
{
   // Draw a line to a new position

   WriteReal(x);
   WriteReal(y);
   PrintFast(2," l");
}


//______________________________________________________________________________
void TPDF::MoveTo(Double_t x, Double_t y)
{
   // Move to a new position

   WriteReal(x);
   WriteReal(y);
   PrintFast(2," m");
}


//______________________________________________________________________________
void TPDF::NewObject(Int_t n)
{
   // Create a new object in the PDF file

   if (!fObjPos || n >= fObjPosSize) {
      Int_t newN = TMath::Max(2*fObjPosSize,n+1);
      Int_t *saveo = new Int_t [newN];
      if (fObjPos && fObjPosSize) {
         memcpy(saveo,fObjPos,fObjPosSize*sizeof(Int_t));
         memset(&saveo[fObjPosSize],0,(newN-fObjPosSize)*sizeof(Int_t));
         delete [] fObjPos;
      }
      fObjPos     = saveo;
      fObjPosSize = newN;
   }
   fObjPos[n-1] = fNByte;
   fNbObj       = TMath::Max(fNbObj,n);
   WriteInteger(n, 0);
   PrintStr(" 0 obj");
   PrintStr("@");
}


//______________________________________________________________________________
void TPDF::NewPage()
{
   // Start a new PDF page.

   // Compute pad conversion coefficients
   if (gPad) {
      Double_t ww   = gPad->GetWw();
      Double_t wh   = gPad->GetWh();
      fYsize        = fXsize*wh/ww;
   } else {
      fYsize = 27;
   }

   fNbPage++;

   if (fNbPage>1) {
      // Close the currently opened page
      WriteCompressedBuffer();
      PrintStr("endstream@");
      Int_t streamLength = fNByte-fStartStream-10;
      PrintStr("endobj@");
      NewObject(3*(fNbPage-2)+kObjFirstPage+2);
      WriteInteger(streamLength, 0);
      PrintStr("endobj@");
   }

   // Start a new page
   NewObject(3*(fNbPage-1)+kObjFirstPage);
   PrintStr("<<@");
   PrintStr("/Type /Page@");
   PrintStr("@");
   PrintStr("/Parent");
   WriteInteger(kObjPages);
   PrintStr(" 0 R");
   PrintStr("@");

   Double_t xlow=0, ylow=0, xup=1, yup=1;
   if (gPad) {
      xlow = gPad->GetAbsXlowNDC();
      xup  = xlow + gPad->GetAbsWNDC();
      ylow = gPad->GetAbsYlowNDC();
      yup  = ylow + gPad->GetAbsHNDC();
   }

   PrintStr("/MediaBox [");
   Double_t width, height;
   switch (fPageFormat) {
      case 100 :
         width  = 8.5*2.54;
         height = 11.*2.54;
         break;
      case 200 :
         width  = 8.5*2.54;
         height = 14.*2.54;
         break;
      case 300 :
         width  = 11.*2.54;
         height = 17.*2.54;
         break;
      default  :
         width  = 21.0*TMath::Power(TMath::Sqrt(2.), 4-fPageFormat);
         height = 29.7*TMath::Power(TMath::Sqrt(2.), 4-fPageFormat);
   };
   WriteReal(CMtoPDF(fXsize*xlow));
   WriteReal(CMtoPDF(fYsize*ylow));
   WriteReal(CMtoPDF(width));
   WriteReal(CMtoPDF(height));
   PrintStr("]");
   PrintStr("@");

   Double_t xmargin = CMtoPDF(0.7);
   Double_t ymargin = 0;
   if (fPageOrientation == 1) ymargin = CMtoPDF(TMath::Sqrt(2.)*0.7);
   if (fPageOrientation == 2) ymargin = CMtoPDF(height)-CMtoPDF(0.7);

   PrintStr("/CropBox [");
   if (fPageOrientation == 1) {
      WriteReal(xmargin);
      WriteReal(ymargin);
      WriteReal(xmargin+CMtoPDF(fXsize*xup));
      WriteReal(ymargin+CMtoPDF(fYsize*yup));
   }
   if (fPageOrientation == 2) {
      WriteReal(xmargin);
      WriteReal(CMtoPDF(height)-CMtoPDF(fXsize*xup)-xmargin);
      WriteReal(xmargin+CMtoPDF(fYsize*yup));
      WriteReal(CMtoPDF(height)-xmargin);
   }
   PrintStr("]");
   PrintStr("@");

   if (fPageOrientation == 1) PrintStr("/Rotate 0@");
   if (fPageOrientation == 2) PrintStr("/Rotate 90@");

   PrintStr("/Resources");
   WriteInteger(kObjPageResources);
   PrintStr(" 0 R");
   PrintStr("@");

   PrintStr("/Contents");
   WriteInteger(3*(fNbPage-1)+kObjFirstPage+1);
   PrintStr(" 0 R@");
   PrintStr(">>@");
   PrintStr("endobj@");

   NewObject(3*(fNbPage-1)+kObjFirstPage+1);
   PrintStr("<<@");
   PrintStr("/Length");
   WriteInteger(3*(fNbPage-1)+kObjFirstPage+2);
   PrintStr(" 0 R");
   PrintStr("/Filter [/FlateDecode]@");
   PrintStr(">>@");
   PrintStr("stream@");
   fStartStream = fNByte;
   fCompress = kTRUE;

   PrintStr("1 0 0 1");
   if (fPageOrientation == 2) {
      ymargin = CMtoPDF(height)-CMtoPDF(fXsize*xup)-xmargin;
      xmargin = xmargin+CMtoPDF(fYsize*yup);
   }
   WriteReal(xmargin);
   WriteReal(ymargin);
   PrintStr(" cm");
   if (fPageOrientation == 2) PrintStr(" 0 1 -1 0 0 0 cm");
}


//______________________________________________________________________________
void TPDF::Off()
{
   // Deactivate an already open PDF file

   gVirtualPS = 0;
}


//______________________________________________________________________________
void TPDF::On()
{
   // Activate an already open PDF file

   // fType is used to know if the PDF file is open. Unlike TPostScript, TPDF
   // has no "workstation type".

   if (!fType) {
      Error("On", "no PDF file open");
      Off();
      return;
   }
   gVirtualPS = this;
}


//______________________________________________________________________________
void TPDF::Open(const char *fname, Int_t wtype)
{
   // Open a PDF file

   Int_t i;

   if (fStream) {
      Warning("Open", "PDF file already open");
      return;
   }

   fLenBuffer = 0;
   fRed       = -1;
   fGreen     = -1;
   fBlue      = -1;
   fType      = abs(wtype);
   SetLineScale(gStyle->GetLineScalePS()/4.);
   gStyle->GetPaperSize(fXsize, fYsize);
   Float_t xrange, yrange;
   if (gPad) {
      Double_t ww = gPad->GetWw();
      Double_t wh = gPad->GetWh();
      if (fType == 113) {
         ww *= gPad->GetWNDC();
         wh *= gPad->GetHNDC();
      }
      Double_t ratio = wh/ww;
      xrange = fXsize;
      yrange = fXsize*ratio;
      if (yrange > fYsize) { yrange = fYsize; xrange = yrange/ratio;}
      fXsize = xrange; fYsize = yrange;
   }

   // Open OS file
   fStream = new ofstream();
#ifdef R__WIN32
      fStream->open(fname, ofstream::out | ofstream::binary);
#else
      fStream->open(fname, ofstream::out);
#endif
   if (fStream == 0) {
      printf("ERROR in TPDF::Open: Cannot open file:%s\n",fname);
      return;
   }

   gVirtualPS = this;

   for (i=0; i<fSizBuffer; i++) fBuffer[i] = ' ';

   // The page orientation is last digit of PDF workstation type
   //  orientation = 1 for portrait
   //  orientation = 2 for landscape
   fPageOrientation = fType%10;
   if( fPageOrientation < 1 || fPageOrientation > 2) {
      Error("Open", "Invalid page orientation %d", fPageOrientation);
      return;
   }

   // format = 0-99 is the European page format (A4,A3 ...)
   // format = 100 is the US format  8.5x11.0 inch
   // format = 200 is the US format  8.5x14.0 inch
   // format = 300 is the US format 11.0x17.0 inch
   fPageFormat = fType/1000;
   if( fPageFormat == 0 )  fPageFormat = 4;
   if( fPageFormat == 99 ) fPageFormat = 0;

   fRange = kFALSE;

   // Set a default range
   Range(fXsize, fYsize);

   fObjPos = 0;
   fObjPosSize = 0;
   fNbObj = 0;
   fNbPage = 0;

   PrintStr("%PDF-1.4@");
   PrintStr("%\342\343\317\323");
   PrintStr("@");

   NewObject(kObjRoot);
   PrintStr("<<@");
   PrintStr("/Type /Catalog@");
   PrintStr("/Outlines");
   WriteInteger(kObjOutlines);
   PrintStr(" 0 R");
   PrintStr("@");
   PrintStr("/Pages");
   WriteInteger(kObjPages);
   PrintStr(" 0 R");
   PrintStr(">>@");
   PrintStr("endobj@");

   NewObject(kObjInfo);
   PrintStr("<<@");
   PrintStr("/Creator (ROOT Version ");
   PrintStr(gROOT->GetVersion());
   PrintStr(")");
   PrintStr("@");
   PrintStr("/CreationDate (");
   TDatime t;
   char str[17];
   sprintf(str,"D:%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d",
                t.GetYear()  , t.GetMonth(),
                t.GetDay()   , t.GetHour(),
                t.GetMinute(), t.GetSecond());
   PrintStr(str);
   PrintStr(")");
   PrintStr("@");
   PrintStr("/Title (");
   if (strlen(GetName())<=80) PrintStr(GetName());
   PrintStr(")");
   PrintStr("@");
   PrintStr("/Keywords (ROOT)");
   PrintStr(">>@");
   PrintStr("endobj@");

   NewObject(kObjOutlines);
   PrintStr("<<@");
   PrintStr("/Type /Outlines@");
   PrintStr("/Count 0@");
   PrintStr(">>@");
   PrintStr("endobj@");

   NewObject(kObjPageResources);
   PrintStr("<<@");
   PrintStr("/ProcSet [/PDF /Text]@");

   PrintStr("/Font@");
   PrintStr("<<@");
   for (i=0; i<kNumberOfFonts; i++) {
      PrintStr(" /F");
      WriteInteger(i+1,0);
      WriteInteger(kObjFont+i);
      PrintStr(" 0 R");
   }
   PrintStr(">>@");
<commit_msg>- More fixes. Some missing <CR> in case of multiple pages.<commit_after>// @(#)root/postscript:$Id: TPDF.cxx,v 1.0
// Author: <NAME>

/*************************************************************************
 * Copyright (C) 1995-2000, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPDF                                                                 //
//                                                                      //
// Graphics interface to PDF.                                           //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifdef WIN32
#pragma optimize("",off)
#endif

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "Riostream.h"
#include "TROOT.h"
#include "TColor.h"
#include "TVirtualPad.h"
#include "TPoints.h"
#include "TPDF.h"
#include "TStyle.h"
#include "TMath.h"
#include "TStorage.h"
#include "TText.h"
#include "zlib.h"
#include "TObjString.h"
#include "TClass.h"
#include "TObjArray.h"

// To scale fonts to the same size as the old TT version
const Float_t kScale = 0.93376068;

// Objects numbers
const Int_t kObjRoot             =  1; // Root object
const Int_t kObjInfo             =  2; // Info object
const Int_t kObjOutlines         =  3; // Outlines object
const Int_t kObjPages            =  4; // Pages object (pages index)
const Int_t kObjPageResources    =  5; // Pages Resources object
const Int_t kObjFont             =  6; // First Font object (14 in total)
const Int_t kObjColorSpace       = 21; // ColorSpace object
const Int_t kObjPatternResourses = 22; // Pattern Resources object
const Int_t kObjPatternList      = 23; // Pattern list object
const Int_t kObjPattern          = 24; // Pattern object
const Int_t kObjFirstPage        = 49; // First page object

// Number of fonts
const Int_t kNumberOfFonts = 15;

ClassImp(TPDF)


//______________________________________________________________________________
//
// PDF driver
//


//______________________________________________________________________________
TPDF::TPDF() : TVirtualPS()
{
   // Default PDF constructor

   fStream          = 0;
   fCompress        = kFALSE;
   gVirtualPS       = this;
   fRed             = 0.;
   fGreen           = 0.;
   fBlue            = 0.;
   fXsize           = 0.;
   fYsize           = 0.;
   fType            = 0;
   fPageFormat      = 0;
   fPageOrientation = 0;
   fStartStream     = 0;
   fLineScale       = 0.;
   fObjPosSize      = 0;
   fNbObj           = 0;
   fNbPage          = 0;
   fRange           = kFALSE;
}


//______________________________________________________________________________
TPDF::TPDF(const char *fname, Int_t wtype) : TVirtualPS(fname, wtype)
{
   // Initialize the PDF interface
   //
   //  fname : PDF file name
   //  wtype : PDF workstation type. Not used in the PDF driver. But as TPDF
   //          inherits from TVirtualPS it should be kept. Anyway it is not
   //          necessary to specify this parameter at creation time because it
   //          has a default value (which is ignore in the PDF case).

   fStream          = 0;
   fCompress        = kFALSE;
   fRed             = 0.;
   fGreen           = 0.;
   fBlue            = 0.;
   fXsize           = 0.;
   fYsize           = 0.;
   fType            = 0;
   fPageFormat      = 0;
   fPageOrientation = 0;
   fStartStream     = 0;
   fLineScale       = 0.;
   fObjPosSize      = 0;
   fNbObj           = 0;
   fNbPage          = 0;
   fRange           = kFALSE;
   Open(fname, wtype);
}


//______________________________________________________________________________
TPDF::~TPDF()
{
   // Default PDF destructor

   Close();

   if (fObjPos) delete [] fObjPos;
}


//______________________________________________________________________________
void TPDF::CellArrayBegin(Int_t, Int_t, Double_t, Double_t, Double_t,
                          Double_t)
{
   // Begin the Cell Array painting
   Warning("TPDF::CellArrayBegin", "not yet implemented");
}


//______________________________________________________________________________
void TPDF::CellArrayFill(Int_t, Int_t, Int_t)
{
   // Paint the Cell Array
   Warning("TPDF::CellArrayFill", "not yet implemented");
}


//______________________________________________________________________________
void TPDF::CellArrayEnd()
{
   // End the Cell Array painting
   Warning("TPDF::CellArrayEnd", "not yet implemented");
}


//______________________________________________________________________________
void TPDF::Close(Option_t *)
{
   // Close a PDF file

   Int_t i;

   if (!gVirtualPS) return;
   if (!fStream) return;
   if (gPad) gPad->Update();

   // Close the currently opened page
   WriteCompressedBuffer();
   PrintStr("endstream@");
   Int_t streamLength = fNByte-fStartStream-10;
   PrintStr("endobj@");
   NewObject(3*(fNbPage-1)+kObjFirstPage+2);
   WriteInteger(streamLength, 0);
   PrintStr("@");
   PrintStr("endobj@");

   // List of all the pages
   NewObject(kObjPages);
   PrintStr("<<@");
   PrintStr("/Type /Pages@");
   PrintStr("/Count");
   WriteInteger(fNbPage);
   PrintStr("@");
   PrintStr("/Kids [");
   for (i=1; i<=fNbPage; i++) {
      WriteInteger(3*(i-1)+kObjFirstPage);
      PrintStr(" 0 R");
   }
   PrintStr(" ]");
   PrintStr("@");
   PrintStr(">>@");
   PrintStr("endobj@");

   // Cross-Reference Table
   Int_t refInd = fNByte;
   PrintStr("xref@");
   PrintStr("0");
   WriteInteger(fNbObj+1);
   PrintStr("@");
   PrintStr("0000000000 65535 f @");
   char str[21];
   for (i=0; i<fNbObj; i++) {
      sprintf(str,"%10.10d 00000 n @",fObjPos[i]);
      PrintStr(str);
   }

   // Trailer
   PrintStr("trailer@");
   PrintStr("<<@");
   PrintStr("/Size");
   WriteInteger(fNbObj+1);
   PrintStr("@");
   PrintStr("/Root");
   WriteInteger(kObjRoot);
   PrintStr(" 0 R");
   PrintStr("@");
   PrintStr("/Info");
   WriteInteger(kObjInfo);
   PrintStr(" 0 R");
   PrintStr(">>@");
   PrintStr("startxref@");
   WriteInteger(refInd, 0);
   PrintStr("@");
   PrintStr("%%EOF@");

   // Close file stream
   if (fStream) { fStream->close(); delete fStream; fStream = 0;}

   gVirtualPS = 0;
}


//______________________________________________________________________________
void TPDF::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t  y2)
{
   // Draw a Box

   static Double_t x[4], y[4];
   Double_t ix1 = XtoPDF(x1);
   Double_t ix2 = XtoPDF(x2);
   Double_t iy1 = YtoPDF(y1);
   Double_t iy2 = YtoPDF(y2);
   Int_t fillis = fFillStyle/1000;
   Int_t fillsi = fFillStyle%1000;

   if (fillis == 3 || fillis == 2) {
      if (fillsi > 99) {
         x[0] = x1;   y[0] = y1;
         x[1] = x2;   y[1] = y1;
         x[2] = x2;   y[2] = y2;
         x[3] = x1;   y[3] = y2;
         return;
      }
      if (fillsi > 0 && fillsi < 26) {
         x[0] = x1;   y[0] = y1;
         x[1] = x2;   y[1] = y1;
         x[2] = x2;   y[2] = y2;
         x[3] = x1;   y[3] = y2;
         DrawPS(-4, &x[0], &y[0]);
      }
      if (fillsi == -3) {
         SetColor(5);
         WriteReal(ix1);
         WriteReal(iy1);
         WriteReal(ix2 - ix1);
         WriteReal(iy2 - iy1);
         PrintFast(6," re f*");
      }
   }
   if (fillis == 1) {
      SetColor(fFillColor);
      WriteReal(ix1);
      WriteReal(iy1);
      WriteReal(ix2 - ix1);
      WriteReal(iy2 - iy1);
      PrintFast(6," re f*");
   }
   if (fillis == 0) {
      SetColor(fLineColor);
      WriteReal(ix1);
      WriteReal(iy1);
      WriteReal(ix2 - ix1);
      WriteReal(iy2 - iy1);
      PrintFast(5," re S");
   }
}


//______________________________________________________________________________
void TPDF::DrawFrame(Double_t xl, Double_t yl, Double_t xt, Double_t  yt,
                            Int_t mode, Int_t border, Int_t dark, Int_t light)
{
   // Draw a Frame around a box
   //
   // mode = -1  box looks as it is behind the screen
   // mode =  1  box looks as it is in front of the screen
   // border is the border size in already precomputed PDF units
   // dark  is the color for the dark part of the frame
   // light is the color for the light part of the frame

   static Double_t xps[7], yps[7];
   Int_t i;

   // Draw top&left part of the box
   if (mode == -1) SetColor(dark);
   else            SetColor(light);
   xps[0] = XtoPDF(xl);          yps[0] = YtoPDF(yl);
   xps[1] = xps[0] + border;     yps[1] = yps[0] + border;
   xps[2] = xps[1];              yps[2] = YtoPDF(yt) - border;
   xps[3] = XtoPDF(xt) - border; yps[3] = yps[2];
   xps[4] = XtoPDF(xt);          yps[4] = YtoPDF(yt);
   xps[5] = xps[0];              yps[5] = yps[4];
   xps[6] = xps[0];              yps[6] = yps[0];

   MoveTo(xps[0], yps[0]);
   for (i=1;i<7;i++) LineTo(xps[i], yps[i]);
   PrintFast(3," f*");

   // Draw bottom&right part of the box
   if (mode == -1) SetColor(light);
   else            SetColor(dark);
   xps[0] = XtoPDF(xl);          yps[0] = YtoPDF(yl);
   xps[1] = xps[0] + border;     yps[1] = yps[0] + border;
   xps[2] = XtoPDF(xt) - border; yps[2] = yps[1];
   xps[3] = xps[2];              yps[3] = YtoPDF(yt) - border;
   xps[4] = XtoPDF(xt);          yps[4] = YtoPDF(yt);
   xps[5] = xps[4];              yps[5] = yps[0];
   xps[6] = xps[0];              yps[6] = yps[0];

   MoveTo(xps[0], yps[0]);
   for (i=1;i<7;i++) LineTo(xps[i], yps[i]);
   PrintFast(3," f*");
}


//______________________________________________________________________________
void TPDF::DrawHatch(Float_t, Float_t, Int_t, Float_t *, Float_t *)
{
   // Draw Fill area with hatch styles

   Warning("DrawHatch", "hatch fill style not yet implemented");
}


//______________________________________________________________________________
void TPDF::DrawHatch(Float_t, Float_t, Int_t, Double_t *, Double_t *)
{
   // Draw Fill area with hatch styles

   Warning("DrawHatch", "hatch fill style not yet implemented");
}


//______________________________________________________________________________
void TPDF::DrawPolyLine(Int_t nn, TPoints *xy)
{
   // Draw a PolyLine
   //
   //  Draw a polyline through  the points xy.
   //  If NN=1 moves only to point x,y.
   //  If NN=0 the x,y are  written  in the PDF file
   //     according to the current transformation.
   //  If NN>0 the line is clipped as a line.
   //  If NN<0 the line is clipped as a fill area.

   Int_t  n;

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;

   if (nn > 0) {
      n = nn;
      SetLineStyle(fLineStyle);
      SetLineWidth(fLineWidth);
      SetColor(Int_t(fLineColor));
   } else {
      n = -nn;
      SetLineStyle(1);
      SetLineWidth(1);
      SetColor(Int_t(fLineColor));
   }

   WriteReal(XtoPDF(xy[0].GetX()));
   WriteReal(YtoPDF(xy[0].GetY()));
   if( n <= 1) {
      if( n == 0) return;
      PrintFast(2," m");
      return;
   }

   PrintFast(2," m");

   for (Int_t i=1;i<n;i++) LineTo(XtoPDF(xy[i].GetX()), YtoPDF(xy[i].GetY()));

   if (nn > 0 ) {
      if (xy[0].GetX() == xy[n-1].GetX() && xy[0].GetY() == xy[n-1].GetY()) PrintFast(3," cl");
      PrintFast(2," S");
   } else {
      PrintFast(3," f*");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPolyLineNDC(Int_t nn, TPoints *xy)
{
   // Draw a PolyLine in NDC space
   //
   //  Draw a polyline through  the points  xy.
   //  If NN=1 moves only to point x,y.
   //  If NN=0 the x,y are  written  in the PDF        file
   //     according to the current transformation.
   //  If NN>0 the line is clipped as a line.
   //  If NN<0 the line is clipped as a fill area.

   Int_t  n;

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;

   if (nn > 0) {
      n = nn;
      SetLineStyle(fLineStyle);
      SetLineWidth(fLineWidth);
      SetColor(Int_t(fLineColor));
   } else {
      n = -nn;
      SetLineStyle(1);
      SetLineWidth(1);
      SetColor(Int_t(fLineColor));
   }

   WriteReal(UtoPDF(xy[0].GetX()));
   WriteReal(VtoPDF(xy[0].GetY()));
   if( n <= 1) {
      if( n == 0) return;
      PrintFast(2," m");
      return;
   }

   PrintFast(2," m");

   for (Int_t i=1;i<n;i++) LineTo(UtoPDF(xy[i].GetX()), VtoPDF(xy[i].GetY()));

   if (nn > 0 ) {
      if (xy[0].GetX() == xy[n-1].GetX() && xy[0].GetY() == xy[n-1].GetY()) PrintFast(3," cl");
      PrintFast(2," S");
   } else {
      PrintFast(3," f*");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPolyMarker(Int_t n, Float_t *xw, Float_t *yw)
{
   // Draw markers at the n WC points xw, yw

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;
   SetLineStyle(1);
   SetLineWidth(1);
   SetColor(Int_t(fMarkerColor));
   Int_t ms = abs(fMarkerStyle);

   if (ms >= 6 && ms <= 19) ms = 20;
   if (ms == 4) ms = 24;

   // Define the marker size
   Float_t msize  = fMarkerSize;
   if (fMarkerStyle == 1) {
     msize = 1.;
   } else if (fMarkerStyle == 6) {
     msize = 1.5;
   } else if (fMarkerStyle == 7) {
     msize = 3.;
   } else {
      const Int_t kBASEMARKER = 8;
      Float_t sbase = msize*kBASEMARKER;
      Float_t s2x = sbase / Float_t(gPad->GetWw() * gPad->GetAbsWNDC());
      msize = this->UtoPDF(s2x) - this->UtoPDF(0);
   }

   Double_t m  = msize;
   Double_t m2 = m/2;
   Double_t m3 = m/3;
   Double_t m4 = m2*1.333333333333;
   Double_t m6 = m/6;

   // Draw the marker according to the type
   Double_t ix,iy;
   for (Int_t i=0;i<n;i++) {
      ix = XtoPDF(xw[i]);
      iy = YtoPDF(yw[i]);
      // Dot (.)
      if (ms == 1) {
         MoveTo(ix-1, iy);
         LineTo(ix  , iy);
      // Plus (+)
      } else if (ms == 2) {
         MoveTo(ix-m2, iy);
         LineTo(ix+m2, iy);
         MoveTo(ix   , iy-m2);
         LineTo(ix   , iy+m2);
      // X shape (X)
      } else if (ms == 5) {
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy+m2);
         MoveTo(ix-m2, iy+m2);
         LineTo(ix+m2, iy-m2);
      // Asterisk shape (*)
      } else if (ms == 3 || ms == 31) {
         MoveTo(ix-m2, iy);
         LineTo(ix+m2, iy);
         MoveTo(ix   , iy-m2);
         LineTo(ix   , iy+m2);
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy+m2);
         MoveTo(ix-m2, iy+m2);
         LineTo(ix+m2, iy-m2);
      // Circle
      } else if (ms == 24 || ms == 20) {
         MoveTo(ix-m2, iy);
         WriteReal(ix-m2); WriteReal(iy+m4);
         WriteReal(ix+m2); WriteReal(iy+m4);
         WriteReal(ix+m2); WriteReal(iy)   ; PrintFast(2," c");
         WriteReal(ix+m2); WriteReal(iy-m4);
         WriteReal(ix-m2); WriteReal(iy-m4);
         WriteReal(ix-m2); WriteReal(iy)   ; PrintFast(4," c h");
      // Square
      } else if (ms == 25 || ms == 21) {
         WriteReal(ix-m2); WriteReal(iy-m2);
         WriteReal(m)    ; WriteReal(m)    ; PrintFast(3," re");
      // Down triangle
      } else if (ms == 23 || ms == 32) {
         MoveTo(ix   , iy-m2);
         LineTo(ix+m2, iy+m2);
         LineTo(ix-m2, iy+m2);
         PrintFast(2," h");
      // Up triangle
      } else if (ms == 26 || ms == 22) {
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy-m2);
         LineTo(ix   , iy+m2);
         PrintFast(2," h");
      } else if (ms == 27 || ms == 33) {
         MoveTo(ix   , iy-m2);
         LineTo(ix+m3, iy);
         LineTo(ix   , iy+m2);
         LineTo(ix-m3, iy)   ;
         PrintFast(2," h");
      } else if (ms == 28 || ms == 34) {
         MoveTo(ix-m6, iy-m6);
         LineTo(ix-m6, iy-m2);
         LineTo(ix+m6, iy-m2);
         LineTo(ix+m6, iy-m6);
         LineTo(ix+m2, iy-m6);
         LineTo(ix+m2, iy+m6);
         LineTo(ix+m6, iy+m6);
         LineTo(ix+m6, iy+m2);
         LineTo(ix-m6, iy+m2);
         LineTo(ix-m6, iy+m6);
         LineTo(ix-m2, iy+m6);
         LineTo(ix-m2, iy-m6);
         PrintFast(2," h");
      } else if (ms == 29 || ms == 30) {
         MoveTo(ix           , iy+m2);
         LineTo(ix+0.112255*m, iy+0.15451*m);
         LineTo(ix+0.47552*m , iy+0.15451*m);
         LineTo(ix+0.181635*m, iy-0.05902*m);
         LineTo(ix+0.29389*m , iy-0.40451*m);
         LineTo(ix           , iy-0.19098*m);
         LineTo(ix-0.29389*m , iy-0.40451*m);
         LineTo(ix-0.181635*m, iy-0.05902*m);
         LineTo(ix-0.47552*m , iy+0.15451*m);
         LineTo(ix-0.112255*m, iy+0.15451*m);
         PrintFast(2," h");
      } else {
         MoveTo(ix-1, iy);
         LineTo(ix  , iy);
      }
   }

   if ((ms > 19 && ms < 24) || ms == 29 || ms == 33 || ms == 34) {
      PrintFast(2," f");
   } else {
      PrintFast(2," S");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPolyMarker(Int_t n, Double_t *xw, Double_t *yw)
{
   // Draw markers at the n WC points xw, yw

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;
   SetLineStyle(1);
   SetLineWidth(1);
   SetColor(Int_t(fMarkerColor));
   Int_t ms = abs(fMarkerStyle);

   if (ms >= 6 && ms <= 19) ms = 20;
   if (ms == 4) ms = 24;

   // Define the marker size
   Float_t msize  = fMarkerSize;
   if (fMarkerStyle == 1) {
     msize = 1.;
   } else if (fMarkerStyle == 6) {
     msize = 1.5;
   } else if (fMarkerStyle == 7) {
     msize = 3.;
   } else {
      const Int_t kBASEMARKER = 8;
      Float_t sbase = msize*kBASEMARKER;
      Float_t s2x = sbase / Float_t(gPad->GetWw() * gPad->GetAbsWNDC());
      msize = this->UtoPDF(s2x) - this->UtoPDF(0);
   }

   Double_t m  = msize;
   Double_t m2 = m/2;
   Double_t m3 = m/3;
   Double_t m4 = m2*1.333333333333;
   Double_t m6 = m/6;

   // Draw the marker according to the type
   Double_t ix,iy;
   for (Int_t i=0;i<n;i++) {
      ix = XtoPDF(xw[i]);
      iy = YtoPDF(yw[i]);
      // Dot (.)
      if (ms == 1) {
         MoveTo(ix-1, iy);
         LineTo(ix  , iy);
      // Plus (+)
      } else if (ms == 2) {
         MoveTo(ix-m2, iy);
         LineTo(ix+m2, iy);
         MoveTo(ix   , iy-m2);
         LineTo(ix   , iy+m2);
      // X shape (X)
      } else if (ms == 5) {
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy+m2);
         MoveTo(ix-m2, iy+m2);
         LineTo(ix+m2, iy-m2);
      // Asterisk shape (*)
      } else if (ms == 3 || ms == 31) {
         MoveTo(ix-m2, iy);
         LineTo(ix+m2, iy);
         MoveTo(ix   , iy-m2);
         LineTo(ix   , iy+m2);
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy+m2);
         MoveTo(ix-m2, iy+m2);
         LineTo(ix+m2, iy-m2);
      // Circle
      } else if (ms == 24 || ms == 20) {
         MoveTo(ix-m2, iy);
         WriteReal(ix-m2); WriteReal(iy+m4);
         WriteReal(ix+m2); WriteReal(iy+m4);
         WriteReal(ix+m2); WriteReal(iy)   ; PrintFast(2," c");
         WriteReal(ix+m2); WriteReal(iy-m4);
         WriteReal(ix-m2); WriteReal(iy-m4);
         WriteReal(ix-m2); WriteReal(iy)   ; PrintFast(4," c h");
      // Square
      } else if (ms == 25 || ms == 21) {
         WriteReal(ix-m2); WriteReal(iy-m2);
         WriteReal(m)    ; WriteReal(m)    ; PrintFast(3," re");
      // Down triangle
      } else if (ms == 23 || ms == 32) {
         MoveTo(ix   , iy-m2);
         LineTo(ix+m2, iy+m2);
         LineTo(ix-m2, iy+m2);
         PrintFast(2," h");
      // Up triangle
      } else if (ms == 26 || ms == 22) {
         MoveTo(ix-m2, iy-m2);
         LineTo(ix+m2, iy-m2);
         LineTo(ix   , iy+m2);
         PrintFast(2," h");
      } else if (ms == 27 || ms == 33) {
         MoveTo(ix   , iy-m2);
         LineTo(ix+m3, iy);
         LineTo(ix   , iy+m2);
         LineTo(ix-m3, iy)   ;
         PrintFast(2," h");
      } else if (ms == 28 || ms == 34) {
         MoveTo(ix-m6, iy-m6);
         LineTo(ix-m6, iy-m2);
         LineTo(ix+m6, iy-m2);
         LineTo(ix+m6, iy-m6);
         LineTo(ix+m2, iy-m6);
         LineTo(ix+m2, iy+m6);
         LineTo(ix+m6, iy+m6);
         LineTo(ix+m6, iy+m2);
         LineTo(ix-m6, iy+m2);
         LineTo(ix-m6, iy+m6);
         LineTo(ix-m2, iy+m6);
         LineTo(ix-m2, iy-m6);
         PrintFast(2," h");
      } else if (ms == 29 || ms == 30) {
         MoveTo(ix           , iy+m2);
         LineTo(ix+0.112255*m, iy+0.15451*m);
         LineTo(ix+0.47552*m , iy+0.15451*m);
         LineTo(ix+0.181635*m, iy-0.05902*m);
         LineTo(ix+0.29389*m , iy-0.40451*m);
         LineTo(ix           , iy-0.19098*m);
         LineTo(ix-0.29389*m , iy-0.40451*m);
         LineTo(ix-0.181635*m, iy-0.05902*m);
         LineTo(ix-0.47552*m , iy+0.15451*m);
         LineTo(ix-0.112255*m, iy+0.15451*m);
         PrintFast(2," h");
      } else {
         MoveTo(ix-1, iy);
         LineTo(ix  , iy);
      }
   }

   if ((ms > 19 && ms < 24) || ms == 29 || ms == 33 || ms == 34) {
      PrintFast(2," f");
   } else {
      PrintFast(2," S");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPS(Int_t nn, Float_t *xw, Float_t *yw)
{
   // Draw a PolyLine
   //
   //  Draw a polyline through the points xw,yw.
   //  If nn=1 moves only to point xw,yw.
   //  If nn=0 the XW(1) and YW(1) are  written  in the PDF file
   //          according to the current NT.
   //  If nn>0 the line is clipped as a line.
   //  If nn<0 the line is clipped as a fill area.

   static Float_t dyhatch[24] = {.0075,.0075,.0075,.0075,.0075,.0075,.0075,.0075,
                                 .01  ,.01  ,.01  ,.01  ,.01  ,.01  ,.01  ,.01  ,
                                 .015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015};
   static Float_t anglehatch[24] = {180, 90,135, 45,150, 30,120, 60,
                                    180, 90,135, 45,150, 30,120, 60,
                                    180, 90,135, 45,150, 30,120, 60};
   Int_t  n = 0, fais = 0 , fasi = 0;

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;

   if (nn > 0) {
      n = nn;
      SetLineStyle(fLineStyle);
      SetLineWidth(fLineWidth);
      SetColor(Int_t(fLineColor));
   }
   if (nn < 0) {
      n = -nn;
      SetLineStyle(1);
      SetLineWidth(1);
      SetColor(Int_t(fFillColor));
      fais = fFillStyle/1000;
      fasi = fFillStyle%1000;
      if (fais == 3 || fais == 2) {
         if (fasi > 100 && fasi <125) {
            DrawHatch(dyhatch[fasi-101],anglehatch[fasi-101], n, xw, yw);
            SetLineStyle(linestylesav);
            SetLineWidth(linewidthsav);
            return;
         }
         if (fasi > 0 && fasi < 26) {
            SetFillPatterns(fasi, Int_t(fFillColor));
         }
      }
   }

   WriteReal(XtoPDF(xw[0]));
   WriteReal(YtoPDF(yw[0]));
   if( n <= 1) {
      if( n == 0) return;
      PrintFast(2," m");
      return;
   }

   PrintFast(2," m");

   for (Int_t i=1;i<n;i++) LineTo(XtoPDF(xw[i]), YtoPDF(yw[i]));

   if (nn > 0 ) {
      if (xw[0] == xw[n-1] && yw[0] == yw[n-1]) PrintFast(2," h");
      PrintFast(2," S");
   } else {
      if (fais == 0) {PrintFast(2," s"); return;}
      if (fais == 3 || fais == 2) {
         if (fasi > 0 && fasi < 26) {
            PrintFast(3," f*");
            fRed   = -1;
            fGreen = -1;
            fBlue  = -1;
         }
         SetLineStyle(linestylesav);
         SetLineWidth(linewidthsav);
         return;
      }
      PrintFast(3," f*");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::DrawPS(Int_t nn, Double_t *xw, Double_t *yw)
{
   // Draw a PolyLine
   //
   // Draw a polyline through  the points xw,yw.
   // If nn=1 moves only to point xw,yw.
   // If nn=0 the xw(1) and YW(1) are  written  in the PDF file
   //         according to the current NT.
   // If nn>0 the line is clipped as a line.
   // If nn<0 the line is clipped as a fill area.

   static Float_t dyhatch[24] = {.0075,.0075,.0075,.0075,.0075,.0075,.0075,.0075,
                                 .01  ,.01  ,.01  ,.01  ,.01  ,.01  ,.01  ,.01  ,
                                 .015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015};
   static Float_t anglehatch[24] = {180, 90,135, 45,150, 30,120, 60,
                                    180, 90,135, 45,150, 30,120, 60,
                                    180, 90,135, 45,150, 30,120, 60};
   Int_t  n = 0, fais = 0, fasi = 0;

   Style_t linestylesav = fLineStyle;
   Width_t linewidthsav = fLineWidth;

   if (nn > 0) {
      n = nn;
      SetLineStyle(fLineStyle);
      SetLineWidth(fLineWidth);
      SetColor(Int_t(fLineColor));
   }
   if (nn < 0) {
      n = -nn;
      SetLineStyle(1);
      SetLineWidth(1);
      SetColor(Int_t(fFillColor));
      fais = fFillStyle/1000;
      fasi = fFillStyle%1000;
      if (fais == 3 || fais == 2) {
         if (fasi > 100 && fasi <125) {
            DrawHatch(dyhatch[fasi-101],anglehatch[fasi-101], n, xw, yw);
            SetLineStyle(linestylesav);
            SetLineWidth(linewidthsav);
            return;
         }
         if (fasi > 0 && fasi < 26) {
            SetFillPatterns(fasi, Int_t(fFillColor));
         }
      }
   }

   WriteReal(XtoPDF(xw[0]));
   WriteReal(YtoPDF(yw[0]));
   if( n <= 1) {
      if( n == 0) return;
      PrintFast(2," m");
      return;
   }

   PrintFast(2," m");

   for (Int_t i=1;i<n;i++) LineTo(XtoPDF(xw[i]), YtoPDF(yw[i]));

   if (nn > 0 ) {
      if (xw[0] == xw[n-1] && yw[0] == yw[n-1]) PrintFast(2," h");
      PrintFast(2," S");
   } else {
      if (fais == 0) {PrintFast(2," s"); return;}
      if (fais == 3 || fais == 2) {
         if (fasi > 0 && fasi < 26) {
            PrintFast(3," f*");
            fRed   = -1;
            fGreen = -1;
            fBlue  = -1;
         }
         SetLineStyle(linestylesav);
         SetLineWidth(linewidthsav);
         return;
      }
      PrintFast(3," f*");
   }

   SetLineStyle(linestylesav);
   SetLineWidth(linewidthsav);
}


//______________________________________________________________________________
void TPDF::FontEncode()
{
   // Font encoding

   static const char *sdtfonts[] = {
   "/Times-Italic"         , "/Times-Bold"         , "/Times-BoldItalic",
   "/Helvetica"            , "/Helvetica-Oblique"  , "/Helvetica-Bold"  ,
   "/Helvetica-BoldOblique", "/Courier"            , "/Courier-Oblique" ,
   "/Courier-Bold"         , "/Courier-BoldOblique", "/Symbol"          ,
   "/Times-Roman"          , "/ZapfDingbats"       , "/Symbol"};

   for (Int_t i=0; i<kNumberOfFonts; i++) {
      NewObject(kObjFont+i);
      PrintStr("<<@");
      PrintStr("/Type /Font@");
      PrintStr("/Subtype /Type1@");
      PrintStr("/Name /F");
      WriteInteger(i+1,0);
      PrintStr("@");
      PrintStr("/BaseFont ");
      PrintStr(sdtfonts[i]);
      PrintStr("@");
      if (i!=11 && i!=13 && i!=14) {
         PrintStr("/Encoding /WinAnsiEncoding");
         PrintStr("@");
      }
      PrintStr(">>@");
      PrintStr("endobj@");
   }
}


//______________________________________________________________________________
void TPDF::LineTo(Double_t x, Double_t y)
{
   // Draw a line to a new position

   WriteReal(x);
   WriteReal(y);
   PrintFast(2," l");
}


//______________________________________________________________________________
void TPDF::MoveTo(Double_t x, Double_t y)
{
   // Move to a new position

   WriteReal(x);
   WriteReal(y);
   PrintFast(2," m");
}


//______________________________________________________________________________
void TPDF::NewObject(Int_t n)
{
   // Create a new object in the PDF file

   if (!fObjPos || n >= fObjPosSize) {
      Int_t newN = TMath::Max(2*fObjPosSize,n+1);
      Int_t *saveo = new Int_t [newN];
      if (fObjPos && fObjPosSize) {
         memcpy(saveo,fObjPos,fObjPosSize*sizeof(Int_t));
         memset(&saveo[fObjPosSize],0,(newN-fObjPosSize)*sizeof(Int_t));
         delete [] fObjPos;
      }
      fObjPos     = saveo;
      fObjPosSize = newN;
   }
   fObjPos[n-1] = fNByte;
   fNbObj       = TMath::Max(fNbObj,n);
   WriteInteger(n, 0);
   PrintStr(" 0 obj");
   PrintStr("@");
}


//______________________________________________________________________________
void TPDF::NewPage()
{
   // Start a new PDF page.

   // Compute pad conversion coefficients
   if (gPad) {
      Double_t ww   = gPad->GetWw();
      Double_t wh   = gPad->GetWh();
      fYsize        = fXsize*wh/ww;
   } else {
      fYsize = 27;
   }

   fNbPage++;

   if (fNbPage>1) {
      // Close the currently opened page
      WriteCompressedBuffer();
      PrintStr("endstream@");
      Int_t streamLength = fNByte-fStartStream-10;
      PrintStr("endobj@");
      NewObject(3*(fNbPage-2)+kObjFirstPage+2);
      WriteInteger(streamLength, 0);
      PrintStr("@");
      PrintStr("endobj@");
   }

   // Start a new page
   NewObject(3*(fNbPage-1)+kObjFirstPage);
   PrintStr("<<@");
   PrintStr("/Type /Page@");
   PrintStr("@");
   PrintStr("/Parent");
   WriteInteger(kObjPages);
   PrintStr(" 0 R");
   PrintStr("@");

   Double_t xlow=0, ylow=0, xup=1, yup=1;
   if (gPad) {
      xlow = gPad->GetAbsXlowNDC();
      xup  = xlow + gPad->GetAbsWNDC();
      ylow = gPad->GetAbsYlowNDC();
      yup  = ylow + gPad->GetAbsHNDC();
   }

   PrintStr("/MediaBox [");
   Double_t width, height;
   switch (fPageFormat) {
      case 100 :
         width  = 8.5*2.54;
         height = 11.*2.54;
         break;
      case 200 :
         width  = 8.5*2.54;
         height = 14.*2.54;
         break;
      case 300 :
         width  = 11.*2.54;
         height = 17.*2.54;
         break;
      default  :
         width  = 21.0*TMath::Power(TMath::Sqrt(2.), 4-fPageFormat);
         height = 29.7*TMath::Power(TMath::Sqrt(2.), 4-fPageFormat);
   };
   WriteReal(CMtoPDF(fXsize*xlow));
   WriteReal(CMtoPDF(fYsize*ylow));
   WriteReal(CMtoPDF(width));
   WriteReal(CMtoPDF(height));
   PrintStr("]");
   PrintStr("@");

   Double_t xmargin = CMtoPDF(0.7);
   Double_t ymargin = 0;
   if (fPageOrientation == 1) ymargin = CMtoPDF(TMath::Sqrt(2.)*0.7);
   if (fPageOrientation == 2) ymargin = CMtoPDF(height)-CMtoPDF(0.7);

   PrintStr("/CropBox [");
   if (fPageOrientation == 1) {
      WriteReal(xmargin);
      WriteReal(ymargin);
      WriteReal(xmargin+CMtoPDF(fXsize*xup));
      WriteReal(ymargin+CMtoPDF(fYsize*yup));
   }
   if (fPageOrientation == 2) {
      WriteReal(xmargin);
      WriteReal(CMtoPDF(height)-CMtoPDF(fXsize*xup)-xmargin);
      WriteReal(xmargin+CMtoPDF(fYsize*yup));
      WriteReal(CMtoPDF(height)-xmargin);
   }
   PrintStr("]");
   PrintStr("@");

   if (fPageOrientation == 1) PrintStr("/Rotate 0@");
   if (fPageOrientation == 2) PrintStr("/Rotate 90@");

   PrintStr("/Resources");
   WriteInteger(kObjPageResources);
   PrintStr(" 0 R");
   PrintStr("@");

   PrintStr("/Contents");
   WriteInteger(3*(fNbPage-1)+kObjFirstPage+1);
   PrintStr(" 0 R@");
   PrintStr(">>@");
   PrintStr("endobj@");

   NewObject(3*(fNbPage-1)+kObjFirstPage+1);
   PrintStr("<<@");
   PrintStr("/Length");
   WriteInteger(3*(fNbPage-1)+kObjFirstPage+2);
   PrintStr(" 0 R@");
   PrintStr("/Filter [/FlateDecode]@");
   PrintStr(">>@");
   PrintStr("stream@");
   fStartStream = fNByte;
   fCompress = kTRUE;

   PrintStr("1 0 0 1");
   if (fPageOrientation == 2) {
      ymargin = CMtoPDF(height)-CMtoPDF(fXsize*xup)-xmargin;
      xmargin = xmargin+CMtoPDF(fYsize*yup);
   }
   WriteReal(xmargin);
   WriteReal(ymargin);
   PrintStr(" cm");
   if (fPageOrientation == 2) PrintStr(" 0 1 -1 0 0 0 cm");
}


//______________________________________________________________________________
void TPDF::Off()
{
   // Deactivate an already open PDF file

   gVirtualPS = 0;
}


//______________________________________________________________________________
void TPDF::On()
{
   // Activate an already open PDF file

   // fType is used to know if the PDF file is open. Unlike TPostScript, TPDF
   // has no "workstation type".

   if (!fType) {
      Error("On", "no PDF file open");
      Off();
      return;
   }
   gVirtualPS = this;
}


//______________________________________________________________________________
void TPDF::Open(const char *fname, Int_t wtype)
{
   // Open a PDF file

   Int_t i;

   if (fStream) {
      Warning("Open", "PDF file already open");
      return;
   }

   fLenBuffer = 0;
   fRed       = -1;
   fGreen     = -1;
   fBlue      = -1;
   fType      = abs(wtype);
   SetLineScale(gStyle->GetLineScalePS()/4.);
   gStyle->GetPaperSize(fXsize, fYsize);
   Float_t xrange, yrange;
   if (gPad) {
      Double_t ww = gPad->GetWw();
      Double_t wh = gPad->GetWh();
      if (fType == 113) {
         ww *= gPad->GetWNDC();
         wh *= gPad->GetHNDC();
      }
      Double_t ratio = wh/ww;
      xrange = fXsize;
      yrange = fXsize*ratio;
      if (yrange > fYsize) { yrange = fYsize; xrange = yrange/ratio;}
      fXsize = xrange; fYsize = yrange;
   }

   // Open OS file
   fStream = new ofstream();
#ifdef R__WIN32
      fStream->open(fname, ofstream::out | ofstream::binary);
#else
      fStream->open(fname, ofstream::out);
#endif
   if (fStream == 0) {
      printf("ERROR in TPDF::Open: Cannot open file:%s\n",fname);
      return;
   }

   gVirtualPS = this;

   for (i=0; i<fSizBuffer; i++) fBuffer[i] = ' ';

   // The page orientation is last digit of PDF workstation type
   //  orientation = 1 for portrait
   //  orientation = 2 for landscape
   fPageOrientation = fType%10;
   if( fPageOrientation < 1 || fPageOrientation > 2) {
      Error("Open", "Invalid page orientation %d", fPageOrientation);
      return;
   }

   // format = 0-99 is the European page format (A4,A3 ...)
   // format = 100 is the US format  8.5x11.0 inch
   // format = 200 is the US format  8.5x14.0 inch
   // format = 300 is the US format 11.0x17.0 inch
   fPageFormat = fType/1000;
   if( fPageFormat == 0 )  fPageFormat = 4;
   if( fPageFormat == 99 ) fPageFormat = 0;

   fRange = kFALSE;

   // Set a default range
   Range(fXsize, fYsize);

   fObjPos = 0;
   fObjPosSize = 0;
   fNbObj = 0;
   fNbPage = 0;

   PrintStr("%PDF-1.4@");
   PrintStr("%\342\343\317\323");
   PrintStr("@");

   NewObject(kObjRoot);
   PrintStr("<<@");
   PrintStr("/Type /Catalog@");
   PrintStr("/Outlines");
   WriteInteger(kObjOutlines);
   PrintStr(" 0 R");
   PrintStr("@");
   PrintStr("/Pages");
   WriteInteger(kObjPages);
   PrintStr(" 0 R");
   PrintStr(">>@");
   PrintStr("endobj@");

   NewObject(kObjInfo);
   PrintStr("<<@");
   PrintStr("/Creator (ROOT Version ");
   PrintStr(gROOT->GetVersion());
   PrintStr(")");
   PrintStr("@");
   PrintStr("/CreationDate (");
   TDatime t;
   char str[17];
   sprintf(str,"D:%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d",
                t.GetYear()  , t.GetMonth(),
                t.GetDay()   , t.GetHour(),
                t.GetMinute(), t.GetSecond());
   PrintStr(str);
   PrintStr(")");
   PrintStr("@");
   PrintStr("/Title (");
   if (strlen(GetName())<=80) PrintStr(GetName());
   PrintStr(")");
   PrintStr("@");
   PrintStr("/Keywords (ROOT)@");
   PrintStr(">>@");
   PrintStr("endobj@");

   NewObject(kObjOutlines);
   PrintStr("<<@");
   PrintStr("/Type /Outlines@");
   PrintStr("/Count 0@");
   PrintStr(">>@");
   PrintStr("endobj@");

   NewObject(kObjPageResources);
   PrintStr("<<@");
   PrintStr("/ProcSet [/PDF /Text]@");

   PrintStr("/Font@");
   PrintStr("<<@");
   for (i=0; i<kNumberOfFonts; i++) {
      PrintStr(" /F");
      WriteInteger(i+1,0);
      WriteInteger(kObjFont+i);
      PrintStr(" 0 R");
   }
   PrintStr(">>@");

{'fraction_non_alphanumeric': 0.16601530018293698, 'fraction_numerical': 0.04135484228615777, 'mean_word_length': 2.1439588688946016, 'pattern_counts': {'":': 0, '<': 128, '<?xml version=': 0, '>': 158, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 64, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1530483', 'n_tokens_mistral': 28087, 'n_tokens_neox': 26153, 'n_words': 5661}