Skip to content
1 change: 1 addition & 0 deletions graf2d/gpad/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@

ROOT_ADD_GTEST(TRatioPlot ratioplot.cxx LIBRARIES Gpad)
ROOT_ADD_GTEST(TPad pdftitle.cxx LIBRARIES Gpad)
ROOT_ADD_GTEST(TPDF pdfurl.cxx LIBRARIES Gpad)
2 changes: 1 addition & 1 deletion graf2d/gpad/test/pdftitle.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ TEST(TPad, PDFTitle)
Long64_t actualSize = fileStat.fSize;

// Reference file size in bytes (adjust to match your expected output)
const Long64_t referenceSize = 13601;
const Long64_t referenceSize = 13763;
const double tolerance = 0.01; // Allow 1% deviation

// Compute acceptable size range
Expand Down
52 changes: 52 additions & 0 deletions graf2d/gpad/test/pdfurl.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "gtest/gtest.h"
#include "TSystem.h"
#include "TCanvas.h"
#include "TString.h"
#include "TLatex.h"

TEST(TPad, PDFUrl)
{
const TString pdfFile = "output.pdf";

// Generate a multi-page PDF with page titles and #url in TLatex
TCanvas c1;
TCanvas c2;

TLatex l1(.1, .4, "Link on #color[4]{#url[https://root.cern]{root.cern}} web site");
TLatex l2(.1, .5, "Link on #color[2]{#url[https://cern.ch]{CERN}} web site");

c1.cd();
l1.Draw();
l2.Draw();

c2.cd();
l2.Draw();

c1.Print(pdfFile + "["); // Start multi-page PDF
c2.Print(pdfFile, "Title:Page 1");
c1.Print(pdfFile, "Title:Page 2");
c1.Print(pdfFile + "]"); // Close multi-page PDF

// Check if the file was created successfully
FileStat_t fileStat;
int statCode = gSystem->GetPathInfo(pdfFile, fileStat);
ASSERT_EQ(statCode, 0) << "PDF file was not created.";

// Get the actual size of the generated file
Long64_t actualSize = fileStat.fSize;

// Reference file size in bytes (adjust to match your expected output)
const Long64_t referenceSize = 13927;
const double tolerance = 0.01; // Allow 1% deviation

// Compute acceptable size range
Long64_t minSize = referenceSize * (1.0 - tolerance);
Long64_t maxSize = referenceSize * (1.0 + tolerance);

// Assert that the actual size is within acceptable range
EXPECT_GE(actualSize, minSize) << "PDF file is smaller than expected.";
EXPECT_LE(actualSize, maxSize) << "PDF file is larger than expected.";

// Cleanup: delete the test file
gSystem->Unlink(pdfFile);
}
5 changes: 3 additions & 2 deletions graf2d/graf/src/TLatex.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,8 @@ Therefore, as histograms' titles, axis titles, labels etc ... are drawn using

\anchor L15
## URL links
JSROOT and standard SVG output support the syntax '#url[link]{label}'.
This can be combined with other LaTeX commands, such as color or font settings.
JSROOT, standard PDF output and standard SVG output support the syntax '#url[link]{label}'.
This can be combined with other TLatex commands, such as color or font settings.
Begin_Macro(source)
{
auto cl = new TCanvas("cl", "Use of #url in TLatex", 1200, 800);
Expand All @@ -407,6 +407,7 @@ Begin_Macro(source)
latex->SetTextAlign(22);
latex->Draw();
cl->Print("cl.svg");
cl->Print("cl.pdf");
}
End_Macro
*/
Expand Down
164 changes: 92 additions & 72 deletions graf2d/postscript/inc/TPDF.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,97 +23,117 @@

#include "TVirtualPS.h"
#include <vector>
#include <string>


class TPoints;

class TPDF : public TVirtualPS {

protected:
Float_t fRed; ///< Per cent of red
Float_t fGreen; ///< Per cent of green
Float_t fBlue; ///< Per cent of blue
Float_t fAlpha; ///< Per cent of transparency
std::vector<float> fAlphas; ///< List of alpha values used
Float_t fXsize; ///< Page size along X
Float_t fYsize; ///< Page size along Y
Int_t fType; ///< Workstation type used to know if the PDF is open
Int_t fPageFormat; ///< Page format (A4, Letter etc ...)
Int_t fPageOrientation; ///< Page orientation (Portrait, Landscape)
Int_t fStartStream; ///<
Float_t fLineScale; ///< Line width scale factor
Int_t *fObjPos{nullptr}; ///< Objects position
Int_t fObjPosSize{0}; ///< Real size of fObjPos
Int_t fNbObj{0}; ///< Number of objects
Int_t fNbPage; ///< Number of pages
Bool_t fPageNotEmpty; ///< True if the current page is not empty
Bool_t fCompress; ///< True when fBuffer must be compressed
Bool_t fRange; ///< True when a range has been defined
Float_t fRed; ///< Per cent of red
Float_t fGreen; ///< Per cent of green
Float_t fBlue; ///< Per cent of blue
Float_t fAlpha; ///< Per cent of transparency
std::vector<float> fAlphas; ///< List of alpha values used
Float_t fXsize; ///< Page size along X
Float_t fYsize; ///< Page size along Y
Int_t fType; ///< Workstation type used to know if the PDF is open
Int_t fPageFormat; ///< Page format (A4, Letter etc ...)
Int_t fPageOrientation; ///< Page orientation (Portrait, Landscape)
Int_t fStartStream; ///< Stream start
Float_t fLineScale; ///< Line width scale factor
Int_t *fObjPos{nullptr}; ///< Objects position
Int_t fObjPosSize{0}; ///< Real size of fObjPos
Int_t fNbObj{0}; ///< Number of objects
Int_t fNbPage; ///< Number of pages
Int_t fCurrentPage; ///< Object number of the current page
std::vector<int> fPageObjects; ///< Page object numbers
std::vector<std::string> fUrls; ///< URLs
std::vector<float> fRectX1; ///< x1 /Rect coordinates for url annots
std::vector<float> fRectY1; ///< y1 /Rect coordinates for url annots
std::vector<float> fRectX2; ///< x2 /Rect coordinates for url annots
std::vector<float> fRectY2; ///< y2 /Rect coordinates for url annots
Bool_t fObjectIsOpen; ///< True if an object is opened
Bool_t fPageNotEmpty; ///< True if the current page is not empty
Bool_t fCompress; ///< True when fBuffer must be compressed
Bool_t fRange; ///< True when a range has been defined
Bool_t fUrl; ///< True when the text has an URL
Int_t fNbUrl; ///< Number of URLs in the current page
Double_t fA; ///< "a" value of the Current Transformation Matrix (CTM)
Double_t fB; ///< "b" value of the Current Transformation Matrix (CTM)
Double_t fC; ///< "c" value of the Current Transformation Matrix (CTM)
Double_t fD; ///< "d" value of the Current Transformation Matrix (CTM)
Double_t fE; ///< "e" value of the Current Transformation Matrix (CTM)
Double_t fF; ///< "f" value of the Current Transformation Matrix (CTM)

static Int_t fgLineJoin; ///< Appearance of joining lines
static Int_t fgLineCap; ///< Appearance of line caps

static Int_t fgLineJoin; ///< Appearance of joining lines
static Int_t fgLineCap; ///< Appearance of line caps
static Bool_t fgObjectIsOpen; ///< Indicates if an object is open

public:
TPDF();
TPDF(const char *filename, Int_t type=-111);
~TPDF() override;

void CellArrayBegin(Int_t W, Int_t H, Double_t x1, Double_t x2, Double_t y1, Double_t y2) override;
void CellArrayFill(Int_t r, Int_t g, Int_t b) override;
void CellArrayEnd() override;
void Close(Option_t *opt="") override;
Double_t CMtoPDF(Double_t u) { return Int_t(0.5 + 72*u/2.54); }
void DrawBox(Double_t x1, Double_t y1,Double_t x2, Double_t y2) override;
void 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) override;
void DrawHatch(Float_t dy, Float_t angle, Int_t n, Float_t *x, Float_t *y);
void DrawHatch(Float_t dy, Float_t angle, Int_t n, Double_t *x, Double_t *y);
void DrawPolyLine(Int_t n, TPoints *xy);
void DrawPolyLineNDC(Int_t n, TPoints *uv);
void DrawPolyMarker(Int_t n, Float_t *x, Float_t *y) override;
void DrawPolyMarker(Int_t n, Double_t *x, Double_t *y) override;
void DrawPS(Int_t n, Float_t *xw, Float_t *yw) override;
void DrawPS(Int_t n, Double_t *xw, Double_t *yw) override;
void LineTo(Double_t x, Double_t y);
void MoveTo(Double_t x, Double_t y);
void EndObject();
void FontEncode();
void NewObject(Int_t n);
void NewPage() override;
void Off();
void On();
void Open(const char *filename, Int_t type=-111) override;
void PatternEncode();
void PrintFast(Int_t nch, const char *string="") override;
void PrintStr(const char *string="") override;
void Range(Float_t xrange, Float_t yrange);
void SetAlpha(Float_t alpha = 1.);
void SetColor(Int_t color = 1);
void SetColor(Float_t r, Float_t g, Float_t b) override;
void SetFillColor( Color_t cindex=1) override;
void SetFillPatterns(Int_t ipat, Int_t color);
void SetLineColor( Color_t cindex=1) override;
void SetLineJoin(Int_t linejoin=0);
void SetLineCap(Int_t linecap=0);
void SetLineScale(Float_t scale=1) {fLineScale = scale;}
void SetLineStyle(Style_t linestyle = 1) override;
void SetLineWidth(Width_t linewidth = 1) override;
void SetMarkerColor(Color_t cindex=1) override;
void SetTextColor(Color_t cindex=1) override;
void Text(Double_t x, Double_t y, const char *string) override;
void Text(Double_t, Double_t, const wchar_t *) override;
void TextUrl(Double_t x, Double_t y, const char *string, const char *url) override;
void TextNDC(Double_t u, Double_t v, const char *string);
void TextNDC(Double_t, Double_t, const wchar_t *);
void WriteCompressedBuffer();
void WriteReal(Float_t r, Bool_t space=kTRUE) override;
void CellArrayBegin(Int_t W, Int_t H, Double_t x1, Double_t x2, Double_t y1, Double_t y2) override;
void CellArrayFill(Int_t r, Int_t g, Int_t b) override;
void CellArrayEnd() override;
void Close(Option_t *opt = "") override;
Double_t CMtoPDF(Double_t u) { return Int_t(0.5 + 72 * u / 2.54); }
void ComputeRect(const char* chars, Double_t fontsize, Double_t a, Double_t b, Double_t c, Double_t d, Double_t e, Double_t f);
void DrawBox(Double_t x1, Double_t y1,Double_t x2, Double_t y2) override;
void 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) override;
void DrawHatch(Float_t dy, Float_t angle, Int_t n, Float_t *x, Float_t *y);
void DrawHatch(Float_t dy, Float_t angle, Int_t n, Double_t *x, Double_t *y);
void DrawPolyLine(Int_t n, TPoints *xy);
void DrawPolyLineNDC(Int_t n, TPoints *uv);
void DrawPolyMarker(Int_t n, Float_t *x, Float_t *y) override;
void DrawPolyMarker(Int_t n, Double_t *x, Double_t *y) override;
void DrawPS(Int_t n, Float_t *xw, Float_t *yw) override;
void DrawPS(Int_t n, Double_t *xw, Double_t *yw) override;
void LineTo(Double_t x, Double_t y);
void MoveTo(Double_t x, Double_t y);
void EndObject();
void FontEncode();
void NewObject(Int_t n);
void NewPage() override;
void Off();
void On();
void Open(const char *filename, Int_t type = -111) override;
void PatternEncode();
void PrintFast(Int_t nch, const char *string = "") override;
void PrintStr(const char *string = "") override;
void Range(Float_t xrange, Float_t yrange);
void SetAlpha(Float_t alpha = 1.);
void SetColor(Int_t color = 1);
void SetColor(Float_t r, Float_t g, Float_t b) override;
void SetFillColor( Color_t cindex = 1) override;
void SetFillPatterns(Int_t ipat, Int_t color);
void SetLineColor( Color_t cindex = 1) override;
void SetLineJoin(Int_t linejoin = 0);
void SetLineCap(Int_t linecap = 0);
void SetLineScale(Float_t scale = 1) {fLineScale = scale;}
void SetLineStyle(Style_t linestyle = 1) override;
void SetLineWidth(Width_t linewidth = 1) override;
void SetMarkerColor(Color_t cindex = 1) override;
void SetTextColor(Color_t cindex = 1) override;
void Text(Double_t x, Double_t y, const char *string) override;
void Text(Double_t, Double_t, const wchar_t *) override;
void TextUrl(Double_t x, Double_t y, const char *string, const char *url) override;
void TextNDC(Double_t u, Double_t v, const char *string);
void TextNDC(Double_t, Double_t, const wchar_t *);
void WriteCompressedBuffer();
void WriteCM(Double_t a, Double_t b, Double_t c, Double_t d, Double_t e, Double_t f, Bool_t acc = kTRUE);
void WriteReal(Float_t r, Bool_t space = kTRUE) override;
void WriteUrlObjects();
Double_t UtoPDF(Double_t u);
Double_t VtoPDF(Double_t v);
Double_t XtoPDF(Double_t x);
Double_t YtoPDF(Double_t y);

ClassDefOverride(TPDF, 0); //PDF driver
ClassDefOverride(TPDF, 1); // PDF driver
};

#endif
Loading
Loading