// @(#)root/postscript:$Id: TPDF.cxx,v 1.0 // Author: Olivier Couet /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ //______________________________________________________________________________ /* Begin_Html

TPDF: Graphics interface to PDF

Like PostScript, PDF is a vector graphics output format allowing a very high graphics output quality. The functionnalities provided by this class are very similar to those provided by TPostScript.

Compare to PostScript output, the PDF files are usually smaller because some parts of them can be compressed.

PDF also allows to define table of contents. This facility can be used in ROOT. The following example shows how to proceed:

{
   TCanvas* canvas = new TCanvas("canvas");
   TH1F* histo = new TH1F("histo","test 1",10,0.,10.);
   histo->SetFillColor(2);
   histo->Fill(2.);
   histo->Draw();
   canvas->Print("plots.pdf(","Title:One bin filled");
   histo->Fill(4.);
   histo->Draw();
   canvas->Print("plots.pdf","Title:Two bins filled");
   histo->Fill(6.);
   histo->Draw();
   canvas->Print("plots.pdf","Title:Three bins filled");
   histo->Fill(8.);
   histo->Draw();
   canvas->Print("plots.pdf","Title:Four bins filled");
   histo->Fill(8.);
   histo->Draw();
   canvas->Print("plots.pdf)","Title:The fourth bin content is 2");
}
Each character string following the keyword "Title:" makes a new entry in the table of contents. End_Html */ #ifdef WIN32 #pragma optimize("",off) #endif #include #include #include #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 kObjContents = 6; // Table of content const Int_t kObjFont = 7; // First Font object (14 in total) const Int_t kObjColorSpace = 22; // ColorSpace object const Int_t kObjPatternResourses = 23; // Pattern Resources object const Int_t kObjPatternList = 24; // Pattern list object const Int_t kObjTransList = 25; // List of transparencies const Int_t kObjPattern = 26; // First pattern object (25 in total) const Int_t kObjFirstPage = 51; // 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; fPageNotEmpty = kFALSE; gVirtualPS = this; fRed = 0.; fGreen = 0.; fBlue = 0.; fAlpha = 1.; fXsize = 0.; fYsize = 0.; fType = 0; fPageFormat = 0; fPageOrientation = 0; fStartStream = 0; fLineScale = 0.; fObjPosSize = 0; fObjPos = 0; fNbObj = 0; fNbPage = 0; fRange = kFALSE; SetTitle("PDF"); } //______________________________________________________________________________ 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; fPageNotEmpty = kFALSE; fRed = 0.; fGreen = 0.; fBlue = 0.; fAlpha = 1.; fXsize = 0.; fYsize = 0.; fType = 0; fPageFormat = 0; fPageOrientation = 0; fStartStream = 0; fLineScale = 0.; fObjPosSize = 0; fNbObj = 0; fNbPage = 0; fRange = kFALSE; SetTitle("PDF"); 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(4*(fNbPage-1)+kObjFirstPage+2); WriteInteger(streamLength, 0); PrintStr("@"); PrintStr("endobj@"); NewObject(4*(fNbPage-1)+kObjFirstPage+3); PrintStr("<<@"); if (!strstr(GetTitle(),"PDF")) { PrintStr("/Title ("); PrintStr(GetTitle()); PrintStr(")@"); } else { PrintStr("/Title (Page"); WriteInteger(fNbPage); PrintStr(")@"); } PrintStr("/Dest ["); WriteInteger(4*(fNbPage-1)+kObjFirstPage); PrintStr(" 0 R /XYZ null null 0]@"); PrintStr("/Parent"); WriteInteger(kObjContents); PrintStr(" 0 R"); PrintStr("@"); if (fNbPage > 1) { PrintStr("/Prev"); WriteInteger(4*(fNbPage-2)+kObjFirstPage+3); PrintStr(" 0 R"); PrintStr("@"); } PrintStr(">>@"); NewObject(kObjOutlines); PrintStr("<<@"); PrintStr("/Type /Outlines@"); PrintStr("/Count"); WriteInteger(fNbPage+1); PrintStr("@"); PrintStr("/First"); WriteInteger(kObjContents); PrintStr(" 0 R"); PrintStr("@"); PrintStr("/Last"); WriteInteger(kObjContents); PrintStr(" 0 R"); PrintStr("@"); PrintStr(">>@"); PrintStr("endobj@"); NewObject(kObjContents); PrintStr("<<@"); PrintStr("/Title (Contents)@"); PrintStr("/Dest ["); WriteInteger(kObjFirstPage); PrintStr(" 0 R /XYZ null null 0]@"); PrintStr("/Count"); WriteInteger(fNbPage); PrintStr("@"); PrintStr("/Parent"); WriteInteger(kObjOutlines); PrintStr(" 0 R"); PrintStr("@"); PrintStr("/First"); WriteInteger(kObjFirstPage+3); PrintStr(" 0 R"); PrintStr("@"); PrintStr("/Last"); WriteInteger(4*(fNbPage-1)+kObjFirstPage+3); PrintStr(" 0 R"); PrintStr("@"); PrintStr(">>@"); // 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(4*(i-1)+kObjFirstPage); PrintStr(" 0 R"); } PrintStr(" ]"); PrintStr("@"); PrintStr(">>@"); PrintStr("endobj@"); NewObject(kObjTransList); PrintStr("<<@"); for (i=0; i<(int)fAlphas.size(); i++) { PrintStr( Form("/ca%3.2f << /Type /ExtGState /ca %3.2f >> /CA%3.2f << /Type /ExtGState /CA %3.2f >>@", fAlphas[i],fAlphas[i],fAlphas[i],fAlphas[i])); } PrintStr(">>@"); PrintStr("endobj@"); if (fAlphas.size()) fAlphas.clear(); // 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>@"); 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 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 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.; } else if (fMarkerStyle == 7) { msize = 1.5; } 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 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 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 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; fAlpha = -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 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; fAlpha = -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>@"); 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. if (!fPageNotEmpty) return; // 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(4*(fNbPage-2)+kObjFirstPage+2); WriteInteger(streamLength, 0); PrintStr("@"); PrintStr("endobj@"); NewObject(4*(fNbPage-2)+kObjFirstPage+3); PrintStr("<<@"); if (!strstr(GetTitle(),"PDF")) { PrintStr("/Title ("); PrintStr(GetTitle()); PrintStr(")@"); } else { PrintStr("/Title (Page"); WriteInteger(fNbPage-1); PrintStr(")@"); } PrintStr("/Dest ["); WriteInteger(4*(fNbPage-2)+kObjFirstPage); PrintStr(" 0 R /XYZ null null 0]@"); PrintStr("/Parent"); WriteInteger(kObjContents); PrintStr(" 0 R"); PrintStr("@"); PrintStr("/Next"); WriteInteger(4*(fNbPage-1)+kObjFirstPage+3); PrintStr(" 0 R"); PrintStr("@"); if (fNbPage>2) { PrintStr("/Prev"); WriteInteger(4*(fNbPage-3)+kObjFirstPage+3); PrintStr(" 0 R"); PrintStr("@"); } PrintStr(">>@"); } // Start a new page NewObject(4*(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(4*(fNbPage-1)+kObjFirstPage+1); PrintStr(" 0 R@"); PrintStr(">>@"); PrintStr("endobj@"); NewObject(4*(fNbPage-1)+kObjFirstPage+1); PrintStr("<<@"); PrintStr("/Length"); WriteInteger(4*(fNbPage-1)+kObjFirstPage+2); PrintStr(" 0 R@"); PrintStr("/Filter [/FlateDecode]@"); PrintStr(">>@"); PrintStr("stream@"); fStartStream = fNByte; fCompress = kTRUE; // Force the line width definition next time TPDF::SetLineWidth will be called. fLineWidth = -1; // Force the color definition next time TPDF::SetColor will be called. fRed = -1; fGreen = -1; fBlue = -1; fAlpha = -1.; 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; fAlpha = -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 || !fStream->good()) { printf("ERROR in TPDF::Open: Cannot open file:%s\n",fname); if (fStream == 0) return; } gVirtualPS = this; for (i=0; i 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("/Pages"); WriteInteger(kObjPages); PrintStr(" 0 R@"); PrintStr("/Outlines"); WriteInteger(kObjOutlines); PrintStr(" 0 R@"); PrintStr("/PageMode /UseOutlines@"); PrintStr(">>@"); PrintStr("endobj@"); NewObject(kObjInfo); PrintStr("<<@"); PrintStr("/Creator (ROOT Version "); PrintStr(gROOT->GetVersion()); PrintStr(")"); PrintStr("@"); PrintStr("/CreationDate ("); TDatime t; char str[17]; snprintf(str,17,"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(kObjPageResources); PrintStr("<<@"); PrintStr("/ProcSet [/PDF /Text]@"); PrintStr("/Font@"); PrintStr("<<@"); for (i=0; i>@"); PrintStr("/ExtGState"); WriteInteger(kObjTransList); PrintStr(" 0 R @"); if (fAlphas.size()) fAlphas.clear(); PrintStr("/ColorSpace << /Cs8"); WriteInteger(kObjColorSpace); PrintStr(" 0 R >>"); PrintStr("@"); PrintStr("/Pattern"); WriteInteger(kObjPatternList); PrintStr(" 0 R"); PrintStr("@"); PrintStr(">>@"); PrintStr("endobj@"); FontEncode(); PatternEncode(); NewPage(); fPageNotEmpty = kFALSE; } //______________________________________________________________________________ void TPDF::PatternEncode() { // Patterns encoding Int_t patternNb = kObjPattern; NewObject(kObjColorSpace); if (gStyle->GetColorModelPS()) { PrintStr("[/Pattern /DeviceCMYK]@"); } else { PrintStr("[/Pattern /DeviceRGB]@"); } PrintStr("endobj@"); NewObject(kObjPatternResourses); PrintStr("<>@"); PrintStr("endobj@"); NewObject(kObjPatternList); PrintStr("<<@"); PrintStr(" /P01"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P02"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P03"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P04"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P05"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P06"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P07"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P08"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P09"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P10"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P11"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P12"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P13"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P14"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P15"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P16"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P17"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P18"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P19"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P20"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P21"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P22"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P23"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P24"); WriteInteger(patternNb++); PrintStr(" 0 R"); PrintStr(" /P25"); WriteInteger(patternNb++); PrintStr(" 0 R@"); PrintStr(">>@"); PrintStr("endobj@"); patternNb = kObjPattern; // P01 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301P\241\034(\254\340\253\020m\250\020k\240\220\302e\244`\242\220\313ei\t\244r\200\272\215A\034\v \225\003\2241\202\310\030\201e\f!2\206@N0W \027@\200\001\0|c\024\357\n", 93); fNByte += 93; PrintStr("endstream@"); PrintStr("endobj@"); // P02 NewObject(patternNb++); PrintStr("<>@"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211$\2121\n\2000\024C\367\234\"G\370\277\025\321+\b\016\342\340P\334tP\252\240\213\3277\332!\204\274\227\v\316\2150\032\335J\356\025\023O\241Np\247\363\021f\317\344\214\234\215\v\002+\036h\033U\326/~\243Ve\231PL\370\215\027\343\032#\006\274\002\f\0\242`\025:\n", 94); fNByte += 94; PrintStr("endstream@"); PrintStr("endobj@"); // P03 NewObject(patternNb++); PrintStr("<>@"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211$\2121\n\2000\024C\367\234\"G\370\261(\366\n\202\20388\210\233\016J\025t\361\372\376\332!\204\274\227\033\342N\030\215\262\222g\303\304\313Q\347\360\240\370:f\317Y\f\\\214+**\360Dls'\177\306\274\032\257\344\256.\252\376\215\212\221\217\021\003>\001\006\0\317\243\025\254\n", 95); fNByte += 95; PrintStr("endstream@"); PrintStr("endobj@"); // P04 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020\035k\240\220\002V\231\313\005S\233\303\025\314\025\310\005\020`\0\344\270\r\274\n", 65); fNByte += 65; PrintStr("endstream@"); PrintStr("endobj@"); // P05 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020\035k\240\220\302\005Q\223\313\005\"\r\024r\270\202\271\002\271\0\002\f\0\344\320\r\274\n", 68); fNByte += 68; PrintStr("endstream@"); PrintStr("endobj@"); // P06 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020\035k\240\220\302e\nR\232\v\242@js\270\202\271\002\271\0\002\f\0\345X\r\305\n", 68); fNByte += 68; PrintStr("endstream@"); PrintStr("endobj@"); // P07 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020\035k\240\220\002\02465P\310\345\002)\0042r\270\202\271\002\271\0\002\f\0\345=\r\305\n", 70); fNByte += 70; PrintStr("endstream@"); PrintStr("endobj@"); // P08 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211D\217\261\016\3020\fDw\177\305\315L6Q\225|\003\022C\305\300Puk+\201\032$\272\360\373\330\265\323\016\271\330\367\234\344\"x\201\030\214\252\232\030+%\353VZ.jd\367\205\003x\241({]\311\324]\323|\342\006\033J\201:\306\325\230Jg\226J\261\275D\257#\337=\220\260\354k\233\351\211\217Z75\337\020\374\324\306\035\303\310\230\342x=\303\371\275\307o\332s\331\223\224\240G\330\a\365\364\027`\0\nX1}\n",141); fNByte += 141; PrintStr("endstream@"); PrintStr("endobj@"); // P09 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020\035k\240\220\002\02465P\310\005RFFz&\020\002,d\240\220\314en\256g\0065\b,\001b\230\202$\240\232\214@\362\246`\2169H\336\024\2426\231\v&\200,\n\326\030\314\025\310\005\020`\0\f@\036\227\n", 110); fNByte += 110; PrintStr("endstream@"); PrintStr("endobj@"); // P10 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020\035k\240\220\002\02465P\310\345\002)\0042r\200\332\r\241\\C \017dN.\027L\312\0\302\205\2535\205j6\205X\224\303\025\314\025\310\005\020`\0\2127\031\t\n", 95); fNByte += 95; PrintStr("endstream@"); PrintStr("endobj@"); // P11 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211\\\2171\016\3020\fEw\237\342\037\301ip\223^\001\211\001u`@l0\200(\022,\\\037;v\204\332\241\211\336\373\337V\363\246\204;\210\301H\354\337\347F'\274T\355U>\220\360U\215\003\316\027\306\2655\027=\a\306\223\304I\002m\332\330\356&\030\325\333fZ\275F\337\205\235\265O\270\032\004\331\214\336\305\270\004\227`\357i\256\223\342;]\344\255(!\372\356\205j\030\377K\335\220\344\377\210\274\306\022\330\337T{\214,\212;\301\3508\006\346\206\021O=\216|\212|\246#\375\004\030\0\216FF\207\n", 166); fNByte += 166; PrintStr("endstream@"); PrintStr("endobj@"); // P12 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211\351\203\236\002\f\0d}e\216\n", 228); fNByte += 228; PrintStr("endstream@"); PrintStr("endobj@"); // P13 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020\035k\240\220\002V\231\313\005S\233\303\005\241!\" ~0W \027@\200\001\0\331\227\020\253\n", 71); fNByte += 71; PrintStr("endstream@"); PrintStr("endobj@"); // P14 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\2114\214=\n\2000\f\205\367\234\342\035!-\241\364\f\202\20388\210\233\016J+\350\342\365M\3723\224\327\367}I\036r8A\f\206\343\372\336\203\026\334\212\006\205\027\004\237b\214X7\306\256\33032\331\240~\022y[\315\026\206\222\372\330}\264\036\253\217\335\353\240\030\b%\223\245o=X\227\346\245\355K\341\345@\3613M\364\v0\0\207o\"\261\n", 116); fNByte += 116; PrintStr("endstream@"); PrintStr("endobj@"); // P15 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211<\2211\016\3020\fEw\237\302'@\211c\267w@b@\f\f\210\2510\200(\022,\\\037\347\307\256Z\325\221\375\337\377\225\363\241\312\017\246\302\205'\274\337;\235\371\355\215\275\267\236\\\371\307\265\360\201/\327\3027o\233\361J\262\233\247~\362g\336\211zur!A]{\035}\031S\343\006p\241\226dKI\v\326\202\265\3153\331)X)\335fE\205M\235\373\327\r*\374\026\252\022\216u\223\200\361I\211\177\031\022\001#``\342GI\211\004c\221gi\246\231\247\221\247\231\247\233$XM3\315<\215<\315>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020\035k\240\220\302ej\240\0D\271 \332\314X\317B\301\330\002H\230\233*\030\231\202\310d.CC=#\020\v*\rV\235\214\254\v\210r@\264\261\031P\241\031H5D\253\021H\267\005\3104 \v\344\016\260\002\020\003lB0W \027@\200\001\0hU \305\n", 125); fNByte += 125; PrintStr("endstream@"); PrintStr("endobj@"); // P17 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020md\242\020k\240\220\002V\234\313\005S\236\303\025\314\025\310\005\020`\0\r\351\016B\n", 68); fNByte += 68; PrintStr("endstream@"); PrintStr("endobj@"); // P18 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211*\3442T\310T\3402P0P04\200\340\242T\256p\205<\240\220\027P0K\301D\241\034(\254\340\253\020md\242\020k\240\220\302\005Q\226\313\005\"\r\024r\270\202\271\002\271\0\002\f\0\016\001\016B\n", 71); fNByte += 71; PrintStr("endstream@"); PrintStr("endobj@"); // P19 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211L\216;\016\302@\fD{\237bN\020\331+6a\257\200D\201((P\252@\001R\220\240\341\372\370\263\216(\326\266f\336\330\373&\301\003\304`\b\307\373\334\351\202\227J\a\025\237\020|U\306\021\327\231q\243\306\250\214\325\372T\006\336\367\032\262\326\205\3124\264b\243$\"n.\244=\314\250!\2139\033\327\022i=\323\317\2518\332T}\347.\202\346W\373\372j\315\221\344\266\213=\237\241\344\034\361\264!\236w\344\177\271o8\323\211~\002\f\0\366\3026\233\n", 151); fNByte += 151; PrintStr("endstream@"); PrintStr("endobj@"); // P20 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211D\2151\n\2000\fE\367\234\342\037!)\224\336Ap\020\a\aq\323A\251\202.^\337$-\025\022^\372\033^n\022\354 \006CX\274\237\215&\\\032u\032\036\020\274\032\243\307\2740V]\027\234\024\242\"\033\2642En\324\312\224bc\262\\\230\377\301\332WM\224\212(U\221\375\265\301\025\016?\350\317P\215\221\033\213o\244\201>\001\006\0\031I'f\n", 119); fNByte += 119; PrintStr("endstream@"); PrintStr("endobj@"); // P22 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211<\215=\n\204P\f\204\373\234b\216\220<\b\357\016\302\026ba!vZ(\273\v\332x}\223\274\237\"|\223a\230\271Hp\200\030\fa\211\273w\232\3617k0\363\204\3401\033\037,+c#\3170~\2244\304\327EV\243r\247\272oOcr\337\323]H\t\226\252\334\252r\255\362\257\213(\t\304\250\326\315T\267\032\275q\242\221^\001\006\0\272\367(&\n", 120); fNByte += 120; PrintStr("endstream@"); PrintStr("endobj@"); // P23 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211<\220\273\n\0021\020E\373\371\212[[M\326\331\354\344\027\004\v\261\260\020;\025\224D\320\306\337w\036\254p\363\230\223\341$\344M\005\017\020\203Q8\307\347F'\274\f\355\f>Q\3605\214=\316\005\v.\214kt\217\230;)\324\366\245Fa\213e\320v\212r\022X\006\211Fi\3242\250J\224\302\020\367h\212\254I\\\325R\225o\03143\346U\235@a\t[\202Za\tA\202E`\351~O\002\235`\351~S\202\306h.m\253\264)\232K\217t\310\017q\354\a\353\247\364\377C\356\033\372\t0\0\bm:\375\n", 171); fNByte += 171; PrintStr("endstream@"); PrintStr("endobj@"); // P24 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\211DQ9N\004A\f\314\373\025\216\211\326\343v\037_@\"@\004\004\210\f\220@\003\022$|\177\335\345j\220v\345\251\303\343*\215\312\273\024\275\\d\375?\361dM\3162\306\337\214\337Y\336n\240m\217\036\301y\343\\<,i\250\0038F\035)\347l\322\026o\377\023\353|[\254\177\343\005;\315\317ky\224\257\240n\203\374\020\225\337\240\345N\236T\272<_\344\245\304^\3238\030\tc\236E\233xO\034\363\204>\251\317\324\233\023{\352\235\376\336S\357Fl\251\017\372\207\247>xoh&_\366Ud\331\253\314D\023\332\241\211\016\205\246\235\326\236*\275\307\204z8!s\031\335\306\\\306C\306\\\225\376\312\\\225\307\252\246\356\364\273Q\347\271:\371\341l\177\311e\210\3571\211\251#\374\302H\037:\342c\241\323\2617\320 \034\250\0\302\323a{\005%\302a\373(Zx\313\026\213@\215p\324}\026=\274e\217E8s\326}\026M\036\312}\271\n0\0\215\263\207\016\n", 282); fNByte += 282; PrintStr("endstream@"); PrintStr("endobj@"); // P25 NewObject(patternNb++); PrintStr("<>"); PrintStr("@"); fStream->write("stream",6); fNByte += 6; fStream->write("\r\nH\2112T\310T\3402P0P\310\34526P\0\242\034.s\004m\016\242\r\r\f\024@\030\302\002\321iZP\305`M\346\310\212\201R\0\001\006\0\206\322\017\200\n", 56); fNByte += 56; PrintStr("endstream@"); PrintStr("endobj@"); } //______________________________________________________________________________ void TPDF::PrintStr(const char *str) { // Output the string str in the output buffer Int_t len = strlen(str); if (len == 0) return; fPageNotEmpty = kTRUE; if (fCompress) { if (fLenBuffer+len >= fSizBuffer) { fBuffer = TStorage::ReAllocChar(fBuffer, 2*fSizBuffer, fSizBuffer); fSizBuffer = 2*fSizBuffer; } strcpy(fBuffer + fLenBuffer, str); fLenBuffer += len; return; } TVirtualPS::PrintStr(str); } //______________________________________________________________________________ void TPDF::PrintFast(Int_t len, const char *str) { // Fast version of Print fPageNotEmpty = kTRUE; if (fCompress) { if (fLenBuffer+len >= fSizBuffer) { fBuffer = TStorage::ReAllocChar(fBuffer, 2*fSizBuffer, fSizBuffer); fSizBuffer = 2*fSizBuffer; } strcpy(fBuffer + fLenBuffer, str); fLenBuffer += len; return; } TVirtualPS::PrintFast(len, str); } //______________________________________________________________________________ void TPDF::Range(Float_t xsize, Float_t ysize) { // Set the range for the paper in centimetres Float_t xps, yps, xncm, yncm, dxwn, dywn, xwkwn, ywkwn, xymax; fXsize = xsize; fYsize = ysize; xps = xsize; yps = ysize; if (xsize <= xps && ysize < yps) { if ( xps > yps) xymax = xps; else xymax = yps; xncm = xsize/xymax; yncm = ysize/xymax; dxwn = ((xps/xymax)-xncm)/2; dywn = ((yps/xymax)-yncm)/2; } else { if (xps/yps < 1) xwkwn = xps/yps; else xwkwn = 1; if (yps/xps < 1) ywkwn = yps/xps; else ywkwn = 1; if (xsize < ysize) { xncm = ywkwn*xsize/ysize; yncm = ywkwn; dxwn = (xwkwn-xncm)/2; dywn = 0; if (dxwn < 0) { xncm = xwkwn; dxwn = 0; yncm = xwkwn*ysize/xsize; dywn = (ywkwn-yncm)/2; } } else { xncm = xwkwn; yncm = xwkwn*ysize/xsize; dxwn = 0; dywn = (ywkwn-yncm)/2; if (dywn < 0) { yncm = ywkwn; dywn = 0; xncm = ywkwn*xsize/ysize; dxwn = (xwkwn-xncm)/2; } } } fRange = kTRUE; } //______________________________________________________________________________ void TPDF::SetAlpha(Float_t a) { // Set the alpha channel value. if (a == fAlpha) return; fAlpha = a; if (fAlpha <= 0.000001) fAlpha = 0; Bool_t known = kFALSE; for (int i=0; i<(int)fAlphas.size(); i++) { if (fAlpha == fAlphas[i]) { known = kTRUE; break; } } if (!known) fAlphas.push_back(fAlpha); PrintStr(Form(" /ca%3.2f gs /CA%3.2f gs",fAlpha,fAlpha)); } //______________________________________________________________________________ void TPDF::SetColor(Int_t color) { // Set color with its color index. if (color < 0) color = 0; TColor *col = gROOT->GetColor(color); if (col) { SetColor(col->GetRed(), col->GetGreen(), col->GetBlue()); SetAlpha(col->GetAlpha()); } else { SetColor(1., 1., 1.); SetAlpha(1.); } } //______________________________________________________________________________ void TPDF::SetColor(Float_t r, Float_t g, Float_t b) { // Set color with its R G B components: // // r: % of red in [0,1] // g: % of green in [0,1] // b: % of blue in [0,1] if (r == fRed && g == fGreen && b == fBlue) return; fRed = r; fGreen = g; fBlue = b; if (fRed <= 0.000001) fRed = 0; if (fGreen <= 0.000001) fGreen = 0; if (fBlue <= 0.000001) fBlue = 0; if (gStyle->GetColorModelPS()) { Double_t colCyan, colMagenta, colYellow; Double_t colBlack = TMath::Min(TMath::Min(1-fRed,1-fGreen),1-fBlue); if (colBlack==1) { colCyan = 0; colMagenta = 0; colYellow = 0; } else { colCyan = (1-fRed-colBlack)/(1-colBlack); colMagenta = (1-fGreen-colBlack)/(1-colBlack); colYellow = (1-fBlue-colBlack)/(1-colBlack); } if (colCyan <= 0.000001) colCyan = 0; if (colMagenta <= 0.000001) colMagenta = 0; if (colYellow <= 0.000001) colYellow = 0; if (colBlack <= 0.000001) colBlack = 0; WriteReal(colCyan); WriteReal(colMagenta); WriteReal(colYellow); WriteReal(colBlack); PrintFast(2," K"); WriteReal(colCyan); WriteReal(colMagenta); WriteReal(colYellow); WriteReal(colBlack); PrintFast(2," k"); } else { WriteReal(fRed); WriteReal(fGreen); WriteReal(fBlue); PrintFast(3," RG"); WriteReal(fRed); WriteReal(fGreen); WriteReal(fBlue); PrintFast(3," rg"); } } //______________________________________________________________________________ void TPDF::SetFillColor( Color_t cindex ) { // Set color index for fill areas fFillColor = cindex; if (gStyle->GetFillColor() <= 0) cindex = 0; } //______________________________________________________________________________ void TPDF::SetFillPatterns(Int_t ipat, Int_t color) { // Set the fill patterns (1 to 25) for fill areas char cpat[10]; TColor *col = gROOT->GetColor(color); if (!col) return; PrintStr(" /Cs8 cs"); Double_t colRed = col->GetRed(); Double_t colGreen = col->GetGreen(); Double_t colBlue = col->GetBlue(); if (gStyle->GetColorModelPS()) { Double_t colBlack = TMath::Min(TMath::Min(1-colRed,1-colGreen),1-colBlue); if (colBlack==1) { WriteReal(0); WriteReal(0); WriteReal(0); WriteReal(colBlack); } else { Double_t colCyan = (1-colRed-colBlack)/(1-colBlack); Double_t colMagenta = (1-colGreen-colBlack)/(1-colBlack); Double_t colYellow = (1-colBlue-colBlack)/(1-colBlack); WriteReal(colCyan); WriteReal(colMagenta); WriteReal(colYellow); WriteReal(colBlack); } } else { WriteReal(colRed); WriteReal(colGreen); WriteReal(colBlue); } snprintf(cpat,10," /P%2.2d scn", ipat); PrintStr(cpat); } //______________________________________________________________________________ void TPDF::SetLineColor( Color_t cindex ) { // Set color index for lines fLineColor = cindex; } //______________________________________________________________________________ void TPDF::SetLineStyle(Style_t linestyle) { // Change the line style // // linestyle = 2 dashed // = 3 dotted // = 4 dash-dotted // = else solid (1 in is used most of the time) if ( linestyle == fLineStyle) return; fLineStyle = linestyle; TString st = (TString)gStyle->GetLineStyleString(linestyle); PrintFast(2," ["); TObjArray *tokens = st.Tokenize(" "); for (Int_t j = 0; jGetEntries(); j++) { Int_t it; sscanf(((TObjString*)tokens->At(j))->GetName(), "%d", &it); WriteInteger((Int_t)(it/4)); } delete tokens; PrintFast(5,"] 0 d"); } //______________________________________________________________________________ void TPDF::SetLineWidth(Width_t linewidth) { // Change the line width if (linewidth == fLineWidth) return; fLineWidth = linewidth; WriteReal(fLineScale*fLineWidth); PrintFast(2," w"); } //______________________________________________________________________________ void TPDF::SetMarkerColor( Color_t cindex ) { // Set color index for markers. fMarkerColor = cindex; } //______________________________________________________________________________ void TPDF::SetTextColor( Color_t cindex ) { // Set color index for text fTextColor = cindex; } //______________________________________________________________________________ void TPDF::Text(Double_t xx, Double_t yy, const char *chars) { // Draw text // // xx: x position of the text // yy: y position of the text // chars: text to be drawn if (fTextSize <= 0) return; const Double_t kDEGRAD = TMath::Pi()/180.; char str[8]; Double_t x = xx; Double_t y = yy; // Text color SetColor(Int_t(fTextColor)); // Clipping PrintStr(" q"); Double_t x1 = XtoPDF(gPad->GetX1()); Double_t x2 = XtoPDF(gPad->GetX2()); Double_t y1 = YtoPDF(gPad->GetY1()); Double_t y2 = YtoPDF(gPad->GetY2()); WriteReal(x1); WriteReal(y1); WriteReal(x2 - x1); WriteReal(y2 - y1); PrintStr(" re W n"); // Start the text if (!fCompress) PrintStr("@"); // Font and text size Int_t font = abs(fTextFont)/10; if (font > kNumberOfFonts || font < 1) font = 1; Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2()); Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1()); Float_t tsize, ftsize; if (wh < hh) { tsize = fTextSize*wh; Int_t sizeTTF = (Int_t)(tsize*kScale+0.5); // TTF size ftsize = (sizeTTF*fXsize*gPad->GetAbsWNDC())/wh; } else { tsize = fTextSize*hh; Int_t sizeTTF = (Int_t)(tsize*kScale+0.5); // TTF size ftsize = (sizeTTF*fYsize*gPad->GetAbsHNDC())/hh; } Double_t fontsize = 72*(ftsize)/2.54; if (fontsize <= 0) return; // Text alignment Float_t tsizex = gPad->AbsPixeltoX(Int_t(tsize))-gPad->AbsPixeltoX(0); Float_t tsizey = gPad->AbsPixeltoY(0)-gPad->AbsPixeltoY(Int_t(tsize)); Int_t txalh = fTextAlign/10; if (txalh < 1) txalh = 1; if (txalh > 3) txalh = 3; Int_t txalv = fTextAlign%10; if (txalv < 1) txalv = 1; if (txalv > 3) txalv = 3; if (txalv == 3) { y -= 0.8*tsizey*TMath::Cos(kDEGRAD*fTextAngle); x += 0.8*tsizex*TMath::Sin(kDEGRAD*fTextAngle); } else if (txalv == 2) { y -= 0.4*tsizey*TMath::Cos(kDEGRAD*fTextAngle); x += 0.4*tsizex*TMath::Sin(kDEGRAD*fTextAngle); } if (txalh > 1) { TText t; UInt_t w=0, h; t.SetTextSize(fTextSize); t.SetTextFont(fTextFont); t.GetTextExtent(w, h, chars); Double_t twx = gPad->AbsPixeltoX(w)-gPad->AbsPixeltoX(0); Double_t twy = gPad->AbsPixeltoY(0)-gPad->AbsPixeltoY(w); if (txalh == 2) { x = x-(twx/2)*TMath::Cos(kDEGRAD*fTextAngle); y = y-(twy/2)*TMath::Sin(kDEGRAD*fTextAngle); } if (txalh == 3) { x = x-twx*TMath::Cos(kDEGRAD*fTextAngle); y = y-twy*TMath::Sin(kDEGRAD*fTextAngle); } } // Text angle if (fTextAngle == 0) { PrintStr(" 1 0 0 1"); WriteReal(XtoPDF(x)); WriteReal(YtoPDF(y)); } else if (fTextAngle == 90) { PrintStr(" 0 1 -1 0"); WriteReal(XtoPDF(x)); WriteReal(YtoPDF(y)); } else if (fTextAngle == 270) { PrintStr(" 0 -1 1 0"); WriteReal(XtoPDF(x)); WriteReal(YtoPDF(y)); } else { WriteReal(TMath::Cos(kDEGRAD*fTextAngle)); WriteReal(TMath::Sin(kDEGRAD*fTextAngle)); WriteReal(-TMath::Sin(kDEGRAD*fTextAngle)); WriteReal(TMath::Cos(kDEGRAD*fTextAngle)); WriteReal(XtoPDF(x)); WriteReal(YtoPDF(y)); } PrintStr(" cm"); // Symbol Italic tan(15) = .26794 if (font == 15) PrintStr(" 1 0 0.26794 1 0 0 cm"); PrintStr(" BT"); snprintf(str,8," /F%d",font); PrintStr(str); WriteReal(fontsize); PrintStr(" Tf"); const Int_t len=strlen(chars); // Calculate the individual character placements. // Otherwise, if a string is printed in one line the kerning is not // performed. In order to measure the precise character positions we need to // trick FreeType into rendering high-resolution characters otherwise it will // stick to the screen pixel grid which is far worse than we can achieve on // print. const Float_t scale = 16.0; // Save current text attributes. TText saveAttText; saveAttText.TAttText::operator=(*this); TText t; t.SetTextSize(fTextSize * scale); t.SetTextFont(fTextFont); UInt_t wa1=0, wa0=0; t.GetTextAdvance(wa0, chars, kFALSE); t.GetTextAdvance(wa1, chars); t.TAttText::Modify(); Bool_t kerning; if (wa0-wa1 != 0) kerning = kTRUE; else kerning = kFALSE; Int_t *charDeltas = 0; if (kerning) { charDeltas = new Int_t[len]; for (Int_t i = 0;i < len;i++) { UInt_t ww=0; t.GetTextAdvance(ww, chars + i); charDeltas[i] = wa1 - ww; } for (Int_t i = len - 1;i > 0;i--) { charDeltas[i] -= charDeltas[i-1]; } char tmp[2]; tmp[1] = 0; for (Int_t i = 1;i < len;i++) { tmp[0] = chars[i-1]; UInt_t width=0; t.GetTextAdvance(width, &tmp[0], kFALSE); Double_t wwl = gPad->AbsPixeltoX(width - charDeltas[i]) - gPad->AbsPixeltoX(0); wwl -= 0.5*(gPad->AbsPixeltoX(1) - gPad->AbsPixeltoX(0)); // half a pixel ~ rounding error charDeltas[i] = (Int_t)((1000.0/Float_t(fontsize))*(XtoPDF(wwl) - XtoPDF(0))/scale); } } // Restore text attributes. saveAttText.TAttText::Modify(); // Ouput the text. Escape some characters if needed if (kerning) PrintStr(" ["); else PrintStr(" ("); for (Int_t i=0; iGetX1() + u*(gPad->GetX2() - gPad->GetX1()); Double_t y = gPad->GetY1() + v*(gPad->GetY2() - gPad->GetY1()); Text(x, y, chars); } //______________________________________________________________________________ Double_t TPDF::UtoPDF(Double_t u) { // Convert U from NDC coordinate to PDF Double_t cm = fXsize*(gPad->GetAbsXlowNDC() + u*gPad->GetAbsWNDC()); return 72*cm/2.54; } //______________________________________________________________________________ Double_t TPDF::VtoPDF(Double_t v) { // Convert V from NDC coordinate to PDF Double_t cm = fYsize*(gPad->GetAbsYlowNDC() + v*gPad->GetAbsHNDC()); return 72*cm/2.54; } //______________________________________________________________________________ Double_t TPDF::XtoPDF(Double_t x) { // Convert X from world coordinate to PDF Double_t u = (x - gPad->GetX1())/(gPad->GetX2() - gPad->GetX1()); return UtoPDF(u); } //______________________________________________________________________________ Double_t TPDF::YtoPDF(Double_t y) { // Convert Y from world coordinate to PDF Double_t v = (y - gPad->GetY1())/(gPad->GetY2() - gPad->GetY1()); return VtoPDF(v); } //______________________________________________________________________________ void TPDF::WriteCompressedBuffer() { // Write the buffer in a compressed way z_stream stream; int err; char *out = new char[2*fLenBuffer]; stream.next_in = (Bytef*)fBuffer; stream.avail_in = (uInt)fLenBuffer; stream.next_out = (Bytef*)out; stream.avail_out = (uInt)2*fLenBuffer; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); if (err != Z_OK) { Error("WriteCompressedBuffer", "error in deflateInit (zlib)"); return; } err = deflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { deflateEnd(&stream); Error("WriteCompressedBuffer", "error in deflate (zlib)"); return; } err = deflateEnd(&stream); fStream->write(out, stream.total_out); fNByte += stream.total_out; fStream->write("\n",1); fNByte++; fLenBuffer = 0; delete [] out; fCompress = kFALSE; } //______________________________________________________________________________ void TPDF::WriteReal(Float_t z, Bool_t space) { // Write a Real number to the file. // This method overwrites TVirtualPS::WriteReal. Some PDF reader like // Acrobat do not work when a PDF file contains reals with exponent. This // method writes the real number "z" using the format "%f" instead of the // format "%g" when writing it with "%g" generates a number with exponent. char str[15]; if (space) { snprintf(str,15," %g", z); if (strstr(str,"e") || strstr(str,"E")) snprintf(str,15," %10.8f", z); } else { snprintf(str,15,"%g", z); if (strstr(str,"e") || strstr(str,"E")) snprintf(str,15,"%10.8f", z); } PrintStr(str); }