Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTeXDump.cxx
Go to the documentation of this file.
1 // @(#)root/postscript:$Id$
2 // Author: Olivier Couet
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #ifdef WIN32
13 #pragma optimize("",off)
14 #endif
15 
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 
20 #include "Riostream.h"
21 #include "TROOT.h"
22 #include "TColor.h"
23 #include "TVirtualPad.h"
24 #include "TPoints.h"
25 #include "TTeXDump.h"
26 #include "TStyle.h"
27 #include "TMath.h"
28 #include "TObjString.h"
29 #include "TObjArray.h"
30 #include "TClass.h"
31 
32 ClassImp(TTeXDump);
33 
34 /** \class TTeXDump
35 \ingroup PS
36 
37 \brief Interface to TeX.
38 
39 This class allow to generate <b>PGF/TikZ</b> vector graphics output
40 which can be included in TeX and LaTeX documents.
41 
42 PGF is a TeX macro package for generating graphics. It is platform
43 and format-independent and works together with the most important TeX
44 backend drivers, including pdftex and dvips. It comes with a
45 user-friendly syntax layer called TikZ.
46 
47 To generate a such file it is enough to do:
48 ~~~ {.cpp}
49  gStyle->SetPaperSize(10.,10.);
50  hpx->Draw();
51  gPad->Print("hpx.tex");
52 ~~~
53 
54 Then, the generated file (`hpx.tex`) can be included in a
55 LaTeX document (`simple.tex`) in the following way:
56 ~~~ {.cpp}
57 \documentclass{article}
58 \usepackage{tikz}
59 \usetikzlibrary{patterns}
60 \usetikzlibrary{plotmarks}
61 \title{A simple LaTeX example}
62 \date{July 2013}
63 \begin{document}
64 \maketitle
65 The following image as been generated using the TTeXDump class:
66 \par
67 \input{hpx.tex}
68 \end{document}
69 ~~~
70 
71 Note the three directives needed at the top of the LaTeX file:
72 ~~~ {.cpp}
73 \usepackage{tikz}
74 \usetikzlibrary{patterns}
75 \usetikzlibrary{plotmarks}
76 ~~~
77 
78 Then including the picture in the document is done with the
79 `\input` directive.
80 
81  The command `pdflatex simple.tex` will generate the
82 corresponding pdf file `simple.pdf`.
83 */
84 
85 ////////////////////////////////////////////////////////////////////////////////
86 /// Default TeX constructor
87 
88 TTeXDump::TTeXDump() : TVirtualPS()
89 {
90  fStream = 0;
91  fType = 0;
92  gVirtualPS = this;
93  fBoundingBox = kFALSE;
94  fRange = kFALSE;
95  fXsize = 0.;
96  fYsize = 0.;
97  fCurrentRed = -1.;
98  fCurrentGreen = -1.;
99  fCurrentBlue = -1.;
100  fCurrentAlpha = 1.;
101  fLineScale = 0.;
102 }
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Initialize the TeX interface
106 ///
107 /// --fname : TeX file name
108 /// - wtype : TeX workstation type. Not used in the TeX driver. But as TTeXDump
109 /// inherits from TVirtualPS it should be kept. Anyway it is not
110 /// necessary to specify this parameter at creation time because it
111 /// has a default value (which is ignore in the TeX case).
112 
113 TTeXDump::TTeXDump(const char *fname, Int_t wtype) : TVirtualPS(fname, wtype)
114 {
115  fStream = 0;
116  fType = 0;
117  gVirtualPS = this;
118  fBoundingBox = kFALSE;
119  fRange = kFALSE;
120  fXsize = 0.;
121  fYsize = 0.;
122  fCurrentRed = -1.;
123  fCurrentGreen = -1.;
124  fCurrentBlue = -1.;
125  fCurrentAlpha = 1.;
126  fLineScale = 0.;
127 
128  Open(fname, wtype);
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// Open a TeX file
133 
134 void TTeXDump::Open(const char *fname, Int_t wtype)
135 {
136  if (fStream) {
137  Warning("Open", "TeX file already open");
138  return;
139  }
140 
141  SetLineScale(gStyle->GetLineScalePS());
142  fLenBuffer = 0;
143  fType = abs(wtype);
144 
145  gStyle->GetPaperSize(fXsize, fYsize);
146 
147  Float_t xrange, yrange;
148  if (gPad) {
149  Double_t ww = gPad->GetWw();
150  Double_t wh = gPad->GetWh();
151  ww *= gPad->GetWNDC();
152  wh *= gPad->GetHNDC();
153  Double_t ratio = wh/ww;
154  xrange = fXsize;
155  yrange = fXsize*ratio;
156  if (yrange > fYsize) { yrange = fYsize; xrange = yrange/ratio;}
157  fXsize = xrange; fYsize = yrange;
158  }
159 
160  // Open OS file
161  fStream = new std::ofstream(fname,std::ios::out);
162  if (fStream == 0 || !fStream->good()) {
163  printf("ERROR in TTeXDump::Open: Cannot open file:%s\n",fname);
164  if (fStream == 0) return;
165  }
166 
167  gVirtualPS = this;
168 
169  for (Int_t i=0;i<fSizBuffer;i++) fBuffer[i] = ' ';
170 
171  fBoundingBox = kFALSE;
172  fRange = kFALSE;
173 
174  // Set a default range
175  Range(fXsize, fYsize);
176 
177  NewPage();
178 }
179 
180 ////////////////////////////////////////////////////////////////////////////////
181 /// Default TeX destructor
182 
183 TTeXDump::~TTeXDump()
184 {
185  Close();
186 }
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 /// Close a TeX file
190 
191 void TTeXDump::Close(Option_t *)
192 {
193  if (!gVirtualPS) return;
194  if (!fStream) return;
195  if (gPad) gPad->Update();
196  PrintStr("@");
197  PrintStr("\\end{tikzpicture}@");
198 
199  // Close file stream
200  if (fStream) { fStream->close(); delete fStream; fStream = 0;}
201 
202  gVirtualPS = 0;
203 }
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 /// Activate an already open TeX file
207 
208 void TTeXDump::On()
209 {
210  // fType is used to know if the TeX file is open. Unlike TPostScript, TTeXDump
211  // has no "workstation type". In fact there is only one TeX type.
212 
213  if (!fType) {
214  Error("On", "no TeX file open");
215  Off();
216  return;
217  }
218  gVirtualPS = this;
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Deactivate an already open TeX file
223 
224 void TTeXDump::Off()
225 {
226  gVirtualPS = 0;
227 }
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Draw a Box
231 
232 void TTeXDump::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
233 {
234  Float_t x1c = XtoTeX(x1);
235  Float_t y1c = YtoTeX(y1);
236  Float_t x2c = XtoTeX(x2);
237  Float_t y2c = YtoTeX(y2);
238 
239  Int_t fillis = fFillStyle/1000;
240  Int_t fillsi = fFillStyle%1000;
241 
242  if (fillis==1) {
243  SetColor(fFillColor);
244  PrintStr("@");
245  PrintStr("\\draw [color=c, fill=c");
246  if (fCurrentAlpha != 1.) {
247  PrintStr(", fill opacity=");
248  WriteReal(fCurrentAlpha, kFALSE);
249  }
250  PrintStr("] (");
251  WriteReal(x1c, kFALSE);
252  PrintFast(1,",");
253  WriteReal(y1c, kFALSE);
254  PrintStr(") rectangle (");
255  WriteReal(x2c, kFALSE);
256  PrintFast(1,",");
257  WriteReal(y2c, kFALSE);
258  PrintStr(");");
259  }
260  if (fillis>1 && fillis<4) {
261  SetColor(fFillColor);
262  PrintStr("@");
263  PrintStr("\\draw [pattern=");
264  switch (fillsi) {
265  case 1 :
266  PrintStr("crosshatch dots");
267  break;
268  case 2 :
269  case 3 :
270  PrintStr("dots");
271  break;
272  case 4 :
273  PrintStr("north east lines");
274  break;
275  case 5 :
276  PrintStr("north west lines");
277  break;
278  case 6 :
279  PrintStr("vertical lines");
280  break;
281  case 7 :
282  PrintStr("horizontal lines");
283  break;
284  case 10 :
285  PrintStr("bricks");
286  break;
287  case 13 :
288  PrintStr("crosshatch");
289  break;
290  }
291  PrintStr(", draw=none, pattern color=c");
292  if (fCurrentAlpha != 1.) {
293  PrintStr(", fill opacity=");
294  WriteReal(fCurrentAlpha, kFALSE);
295  }
296  PrintStr("] (");
297  WriteReal(x1c, kFALSE);
298  PrintFast(1,",");
299  WriteReal(y1c, kFALSE);
300  PrintStr(") rectangle (");
301  WriteReal(x2c, kFALSE);
302  PrintFast(1,",");
303  WriteReal(y2c, kFALSE);
304  PrintStr(");");
305  }
306  if (fillis == 0) {
307  if (fLineWidth<=0) return;
308  SetColor(fLineColor);
309  PrintStr("@");
310  PrintStr("\\draw [c");
311  PrintStr(",line width=");
312  WriteReal(0.3*fLineScale*fLineWidth, kFALSE);
313  if (fCurrentAlpha != 1.) {
314  PrintStr(", opacity=");
315  WriteReal(fCurrentAlpha, kFALSE);
316  }
317  PrintStr("] (");
318  WriteReal(x1c, kFALSE);
319  PrintFast(1,",");
320  WriteReal(y1c, kFALSE);
321  PrintStr(") -- (");
322  WriteReal(x1c, kFALSE);
323  PrintFast(1,",");
324  WriteReal(y2c, kFALSE);
325  PrintStr(") -- (");
326  WriteReal(x2c, kFALSE);
327  PrintFast(1,",");
328  WriteReal(y2c, kFALSE);
329  PrintStr(") -- (");
330  WriteReal(x2c, kFALSE);
331  PrintFast(1,",");
332  WriteReal(y1c, kFALSE);
333  PrintStr(") -- (");
334  WriteReal(x1c, kFALSE);
335  PrintFast(1,",");
336  WriteReal(y1c, kFALSE);
337  PrintStr(");");
338  }
339 }
340 
341 ////////////////////////////////////////////////////////////////////////////////
342 /// Draw a Frame around a box
343 ///
344 /// mode = -1 the box looks as it is behind the screen
345 /// mode = 1 the box looks as it is in front of the screen
346 /// border is the border size in already pre-computed TeX units dark is the
347 /// color for the dark part of the frame light is the color for the light
348 /// part of the frame
349 
350 void TTeXDump::DrawFrame(Double_t, Double_t, Double_t, Double_t,
351  Int_t, Int_t, Int_t, Int_t)
352 {
353  Warning("DrawFrame", "not yet implemented");
354 }
355 
356 ////////////////////////////////////////////////////////////////////////////////
357 /// Draw a PolyLine
358 ///
359 /// Draw a polyline through the points xy.
360 /// - If NN=1 moves only to point x,y.
361 /// - If NN=0 the x,y are written in the TeX file
362 /// according to the current transformation.
363 /// - If NN>0 the line is clipped as a line.
364 /// - If NN<0 the line is clipped as a fill area.
365 
366 void TTeXDump::DrawPolyLine(Int_t, TPoints *)
367 {
368  Warning("DrawPolyLine", "not yet implemented");
369 }
370 
371 ////////////////////////////////////////////////////////////////////////////////
372 /// Draw a PolyLine in NDC space
373 ///
374 /// Draw a polyline through the points xy.
375 /// - If NN=1 moves only to point x,y.
376 /// - If NN=0 the x,y are written in the TeX file
377 /// according to the current transformation.
378 /// - If NN>0 the line is clipped as a line.
379 /// - If NN<0 the line is clipped as a fill area.
380 
381 void TTeXDump::DrawPolyLineNDC(Int_t, TPoints *)
382 {
383  Warning("DrawPolyLineNDC", "not yet implemented");
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Paint PolyMarker
388 
389 void TTeXDump::DrawPolyMarker(Int_t, Float_t *, Float_t *)
390 {
391  Warning("DrawPolyMarker", "not yet implemented");
392 }
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 /// Paint PolyMarker
396 
397 void TTeXDump::DrawPolyMarker(Int_t n, Double_t *xw, Double_t *yw)
398 {
399  Float_t x, y;
400 
401  SetColor(fMarkerColor);
402 
403  PrintStr("@");
404  PrintStr("\\foreach \\P in {");
405 
406  x = XtoTeX(xw[0]);
407  y = YtoTeX(yw[0]);
408 
409  PrintStr("(");
410  WriteReal(x, kFALSE);
411  PrintFast(1,",");
412  WriteReal(y, kFALSE);
413  PrintStr(")");
414 
415  for (Int_t i=1;i<n;i++) {
416  x = XtoTeX(xw[i]);
417  y = YtoTeX(yw[i]);
418  PrintFast(3,", (");
419  WriteReal(x, kFALSE);
420  PrintFast(1,",");
421  WriteReal(y, kFALSE);
422  PrintFast(1,")");
423  }
424 
425  PrintStr("}{\\draw[mark options={color=c,fill=c");
426 
427  if (fCurrentAlpha != 1.) {
428  PrintStr(",opacity=");
429  WriteReal(fCurrentAlpha, kFALSE);
430  }
431 
432  if (fMarkerStyle == 23 || fMarkerStyle == 32) PrintStr(",rotate=180");
433 
434  PrintStr(Form("},mark size=%fpt,mark=",8./3.33*fMarkerSize));
435  switch (fMarkerStyle) {
436  case 1 :
437  PrintStr("*");
438  PrintStr(",mark size=1pt");
439  break;
440  case 2 :
441  PrintStr("+");
442  break;
443  case 3 :
444  PrintStr("asterisk");
445  break;
446  case 4 :
447  PrintStr("o");
448  break;
449  case 5 :
450  PrintStr("x");
451  break;
452  case 20 :
453  PrintStr("*");
454  break;
455  case 21 :
456  PrintStr("square*");
457  break;
458  case 22 :
459  PrintStr("triangle*");
460  break;
461  case 23 :
462  PrintStr("triangle*");
463  break;
464  case 24 :
465  PrintStr("o");
466  break;
467  case 25 :
468  PrintStr("square");
469  break;
470  case 26 :
471  PrintStr("triangle");
472  break;
473  case 27 :
474  PrintStr("diamond");
475  break;
476  case 28 :
477  PrintStr("cross");
478  break;
479  case 29 :
480  PrintStr("newstar*");
481  break;
482  case 30 :
483  PrintStr("newstar");
484  break;
485  case 31 :
486  PrintStr("10-pointed star");
487  break;
488  case 32 :
489  PrintStr("triangle");
490  break;
491  case 33 :
492  PrintStr("diamond*");
493  break;
494  case 34 :
495  PrintStr("cross*");
496  break;
497  }
498  PrintStr("] plot coordinates {\\P};}");
499 }
500 
501 ////////////////////////////////////////////////////////////////////////////////
502 /// This function defines a path with xw and yw and draw it according the
503 /// value of nn:
504 ///
505 /// - If nn>0 a line is drawn.
506 /// - If nn<0 a closed polygon is drawn.
507 
508 void TTeXDump::DrawPS(Int_t nn, Double_t *xw, Double_t *yw)
509 {
510  Int_t n = TMath::Abs(nn);;
511  Float_t x, y;
512 
513  if( n <= 1) {
514  Error("DrawPS", "Two points are needed");
515  return;
516  }
517 
518  x = XtoTeX(xw[0]);
519  y = YtoTeX(yw[0]);
520 
521  Int_t fillis = fFillStyle/1000;
522  Int_t fillsi = fFillStyle%1000;
523 
524  if (nn>0) {
525  if (fLineWidth<=0) return;
526  SetColor(fLineColor);
527  PrintStr("@");
528  PrintStr("\\draw [c");
529  TString spec = gStyle->GetLineStyleString(fLineStyle);
530  TString tikzSpec;
531  TString stripped = TString{spec.Strip(TString::kBoth)};
532  if (stripped.Length()) {
533  tikzSpec.Append(",dash pattern=");
534  Ssiz_t i{0}, j{0};
535  bool on{true}, iterate{true};
536 
537  while (iterate){
538  j = stripped.Index(" ", 1, i, TString::kExact);
539  if (j == kNPOS){
540  iterate = false;
541  j = stripped.Length();
542  }
543 
544  if (on) {
545  tikzSpec.Append("on ");
546  on = false;
547  } else {
548  tikzSpec.Append("off ");
549  on = true;
550  }
551  int num = TString{stripped(i, j - i)}.Atoi();
552  float pt = 0.2*num;
553  tikzSpec.Append(TString::Format("%.2fpt ", pt));
554  i = j + 1;
555  }
556  PrintStr(tikzSpec.Data());
557  }
558  PrintStr(",line width=");
559  WriteReal(0.3*fLineScale*fLineWidth, kFALSE);
560  if (fCurrentAlpha != 1.) {
561  PrintStr(",opacity=");
562  WriteReal(fCurrentAlpha, kFALSE);
563  }
564  } else {
565  SetColor(fFillColor);
566  if (fillis==1) {
567  PrintStr("@");
568  PrintStr("\\draw [c, fill=c");
569  } else if (fillis==0) {
570  PrintStr("@");
571  PrintStr("\\draw [c");
572  } else {
573  PrintStr("\\draw [pattern=");
574  switch (fillsi) {
575  case 1 :
576  PrintStr("crosshatch dots");
577  break;
578  case 2 :
579  case 3 :
580  PrintStr("dots");
581  break;
582  case 4 :
583  PrintStr("north east lines");
584  break;
585  case 5 :
586  PrintStr("north west lines");
587  break;
588  case 6 :
589  PrintStr("vertical lines");
590  break;
591  case 7 :
592  PrintStr("horizontal lines");
593  break;
594  case 10 :
595  PrintStr("bricks");
596  break;
597  case 13 :
598  PrintStr("crosshatch");
599  break;
600  }
601  PrintStr(", draw=none, pattern color=c");
602  }
603  if (fCurrentAlpha != 1.) {
604  PrintStr(", fill opacity=");
605  WriteReal(fCurrentAlpha, kFALSE);
606  }
607  }
608  PrintStr("] (");
609  WriteReal(x, kFALSE);
610  PrintFast(1,",");
611  WriteReal(y, kFALSE);
612  PrintStr(") -- ");
613 
614  for (Int_t i=1;i<n;i++) {
615  x = XtoTeX(xw[i]);
616  y = YtoTeX(yw[i]);
617  PrintFast(1,"(");
618  WriteReal(x, kFALSE);
619  PrintFast(1,",");
620  WriteReal(y, kFALSE);
621  PrintFast(1,")");
622  if (i<n-1) PrintStr(" -- ");
623  else PrintStr(";@");
624  }
625 }
626 
627 ////////////////////////////////////////////////////////////////////////////////
628 /// Start the TeX page. This function starts the tikzpicture environment
629 
630 void TTeXDump::NewPage()
631 {
632  // Compute pad conversion coefficients
633  if (gPad) {
634  Double_t ww = gPad->GetWw();
635  Double_t wh = gPad->GetWh();
636  fYsize = fXsize*wh/ww;
637  } else {
638  fYsize = 27;
639  }
640 
641  if(!fBoundingBox) {
642  PrintStr("\\begin{tikzpicture}@");
643  DefineMarkers();
644  fBoundingBox = kTRUE;
645  }
646 }
647 
648 ////////////////////////////////////////////////////////////////////////////////
649 /// Set the range for the paper in centimetres
650 
651 void TTeXDump::Range(Float_t xsize, Float_t ysize)
652 {
653  fXsize = xsize;
654  fYsize = ysize;
655 
656  fRange = kTRUE;
657 }
658 
659 ////////////////////////////////////////////////////////////////////////////////
660 /// Set color index for fill areas
661 
662 void TTeXDump::SetFillColor( Color_t cindex )
663 {
664  fFillColor = cindex;
665  if (gStyle->GetFillColor() <= 0) cindex = 0;
666 }
667 
668 ////////////////////////////////////////////////////////////////////////////////
669 /// Set color index for lines
670 
671 void TTeXDump::SetLineColor( Color_t cindex )
672 {
673  fLineColor = cindex;
674 }
675 
676 ////////////////////////////////////////////////////////////////////////////////
677 /// Change the line style
678 ///
679 /// - linestyle = 2 dashed
680 /// - linestyle = 3 dotted
681 /// - linestyle = 4 dash-dotted
682 /// - linestyle = else solid (1 in is used most of the time)
683 
684 void TTeXDump::SetLineStyle(Style_t linestyle)
685 {
686  fLineStyle = linestyle;
687 }
688 
689 ////////////////////////////////////////////////////////////////////////////////
690 /// Set the lines width.
691 
692 void TTeXDump::SetLineWidth(Width_t linewidth)
693 {
694  fLineWidth = linewidth;
695 }
696 
697 ////////////////////////////////////////////////////////////////////////////////
698 /// Set size for markers.
699 
700 void TTeXDump::SetMarkerSize( Size_t msize)
701 {
702  fMarkerSize = msize;
703 }
704 
705 ////////////////////////////////////////////////////////////////////////////////
706 /// Set color index for markers.
707 
708 void TTeXDump::SetMarkerColor( Color_t cindex)
709 {
710  fMarkerColor = cindex;
711 }
712 
713 ////////////////////////////////////////////////////////////////////////////////
714 /// Set color with its color index
715 
716 void TTeXDump::SetColor(Int_t color)
717 {
718  if (color < 0) color = 0;
719  TColor *col = gROOT->GetColor(color);
720 
721  if (col) {
722  SetColor(col->GetRed(), col->GetGreen(), col->GetBlue());
723  fCurrentAlpha = col->GetAlpha();
724  } else {
725  SetColor(1., 1., 1.);
726  fCurrentAlpha = 1.;
727  }
728 }
729 
730 ////////////////////////////////////////////////////////////////////////////////
731 /// Set color with its R G B components
732 ///
733 /// - r: % of red in [0,1]
734 /// - g: % of green in [0,1]
735 /// - b: % of blue in [0,1]
736 
737 void TTeXDump::SetColor(Float_t r, Float_t g, Float_t b)
738 {
739  if (fCurrentRed == r && fCurrentGreen == g && fCurrentBlue == b) return;
740 
741  fCurrentRed = r;
742  fCurrentGreen = g;
743  fCurrentBlue = b;
744  PrintStr("@");
745  PrintStr("\\definecolor{c}{rgb}{");
746  WriteReal(r, kFALSE);
747  PrintFast(1,",");
748  WriteReal(g, kFALSE);
749  PrintFast(1,",");
750  WriteReal(b, kFALSE);
751  PrintFast(2,"};");
752 }
753 
754 ////////////////////////////////////////////////////////////////////////////////
755 /// Set color index for text
756 
757 void TTeXDump::SetTextColor( Color_t cindex )
758 {
759  fTextColor = cindex;
760 }
761 
762 ////////////////////////////////////////////////////////////////////////////////
763 /// Draw text
764 ///
765 /// - xx: x position of the text
766 /// - yy: y position of the text
767 /// - chars: text to be drawn
768 
769 void TTeXDump::Text(Double_t x, Double_t y, const char *chars)
770 {
771  Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
772  Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
773  Float_t tsize, ftsize;
774  if (wh < hh) {
775  tsize = fTextSize*wh;
776  Int_t sizeTTF = (Int_t)(tsize+0.5);
777  ftsize = (sizeTTF*fXsize*gPad->GetAbsWNDC())/wh;
778  } else {
779  tsize = fTextSize*hh;
780  Int_t sizeTTF = (Int_t)(tsize+0.5);
781  ftsize = (sizeTTF*fYsize*gPad->GetAbsHNDC())/hh;
782  }
783  ftsize *= 2.22097;
784  if (ftsize <= 0) return;
785 
786  TString t(chars);
787  if (t.Index("\\")>=0 || t.Index("^{")>=0 || t.Index("_{")>=0) {
788  t.Prepend("$");
789  t.Append("$");
790  } else {
791  t.ReplaceAll("<","$<$");
792  t.ReplaceAll(">","$>$");
793  t.ReplaceAll("_","\\_");
794  }
795  t.ReplaceAll("&","\\&");
796  t.ReplaceAll("#","\\#");
797  t.ReplaceAll("%","\\%");
798 
799  Int_t txalh = fTextAlign/10;
800  if (txalh <1) txalh = 1; else if (txalh > 3) txalh = 3;
801  Int_t txalv = fTextAlign%10;
802  if (txalv <1) txalv = 1; else if (txalv > 3) txalv = 3;
803  SetColor(fTextColor);
804  PrintStr("@");
805  PrintStr("\\draw");
806  if (txalh!=2 || txalv!=2) {
807  PrintStr(" [anchor=");
808  if (txalv==1) PrintStr("base");
809  if (txalv==3) PrintStr("north");
810  if (txalh==1) PrintStr(" west");
811  if (txalh==3) PrintStr(" east");
812  PrintFast(1,"]");
813  }
814  PrintFast(2," (");
815  WriteReal(XtoTeX(x), kFALSE);
816  PrintFast(1,",");
817  WriteReal(YtoTeX(y), kFALSE);
818  PrintStr(") node[scale=");
819  WriteReal(ftsize, kFALSE);
820  PrintStr(", color=c");
821  if (fCurrentAlpha != 1.) {
822  PrintStr(",opacity=");
823  WriteReal(fCurrentAlpha, kFALSE);
824  }
825  PrintStr(", rotate=");
826  WriteReal(fTextAngle, kFALSE);
827  PrintFast(2,"]{");
828  PrintStr(t.Data());
829  PrintFast(2,"};");
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 /// Write a string of characters in NDC
834 
835 void TTeXDump::TextNDC(Double_t u, Double_t v, const char *chars)
836 {
837  Double_t x = gPad->GetX1() + u*(gPad->GetX2() - gPad->GetX1());
838  Double_t y = gPad->GetY1() + v*(gPad->GetY2() - gPad->GetY1());
839  Text(x, y, chars);
840 }
841 
842 ////////////////////////////////////////////////////////////////////////////////
843 /// Convert U from NDC coordinate to TeX
844 
845 Float_t TTeXDump::UtoTeX(Double_t u)
846 {
847  Double_t cm = fXsize*(gPad->GetAbsXlowNDC() + u*gPad->GetAbsWNDC());
848  return cm;
849 }
850 
851 ////////////////////////////////////////////////////////////////////////////////
852 /// Convert V from NDC coordinate to TeX
853 
854 Float_t TTeXDump::VtoTeX(Double_t v)
855 {
856  Double_t cm = fYsize*(gPad->GetAbsYlowNDC() + v*gPad->GetAbsHNDC());
857  return cm;
858 }
859 
860 ////////////////////////////////////////////////////////////////////////////////
861 /// Convert X from world coordinate to TeX
862 
863 Float_t TTeXDump::XtoTeX(Double_t x)
864 {
865  Double_t u = (x - gPad->GetX1())/(gPad->GetX2() - gPad->GetX1());
866  return UtoTeX(u);
867 }
868 
869 ////////////////////////////////////////////////////////////////////////////////
870 /// Convert Y from world coordinate to TeX
871 
872 Float_t TTeXDump::YtoTeX(Double_t y)
873 {
874  Double_t v = (y - gPad->GetY1())/(gPad->GetY2() - gPad->GetY1());
875  return VtoTeX(v);
876 }
877 
878 ////////////////////////////////////////////////////////////////////////////////
879 /// Begin the Cell Array painting
880 
881 void TTeXDump::CellArrayBegin(Int_t, Int_t, Double_t, Double_t, Double_t,
882  Double_t)
883 {
884  Warning("CellArrayBegin", "not yet implemented");
885 }
886 
887 ////////////////////////////////////////////////////////////////////////////////
888 /// Paint the Cell Array
889 
890 void TTeXDump::CellArrayFill(Int_t, Int_t, Int_t)
891 {
892  Warning("CellArrayFill", "not yet implemented");
893 }
894 
895 ////////////////////////////////////////////////////////////////////////////////
896 /// End the Cell Array painting
897 
898 void TTeXDump::CellArrayEnd()
899 {
900  Warning("CellArrayEnd", "not yet implemented");
901 }
902 
903 ////////////////////////////////////////////////////////////////////////////////
904 /// Not needed in TeX case
905 
906 void TTeXDump::DrawPS(Int_t, Float_t *, Float_t *)
907 {
908  Warning("DrawPS", "not yet implemented");
909 }
910 
911 ////////////////////////////////////////////////////////////////////////////////
912 /// add additional pgfplotmarks
913 
914 void TTeXDump::DefineMarkers()
915 {
916  // open cross
917  PrintStr("\\pgfdeclareplotmark{cross} {@");
918  PrintStr("\\pgfpathmoveto{\\pgfpoint{-0.3\\pgfplotmarksize}{\\pgfplotmarksize}}@");
919  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{\\pgfplotmarksize}}@");
920  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
921  PrintStr("\\pgfpathlineto{\\pgfpoint{+1\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
922  PrintStr("\\pgfpathlineto{\\pgfpoint{+1\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
923  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
924  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{-1.\\pgfplotmarksize}}@");
925  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{-1.\\pgfplotmarksize}}@");
926  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
927  PrintStr("\\pgfpathlineto{\\pgfpoint{-1.\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
928  PrintStr("\\pgfpathlineto{\\pgfpoint{-1.\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
929  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
930  PrintStr("\\pgfpathclose@");
931  PrintStr("\\pgfusepathqstroke@");
932  PrintStr("}@");
933 
934  // filled cross
935  PrintStr("\\pgfdeclareplotmark{cross*} {@");
936  PrintStr("\\pgfpathmoveto{\\pgfpoint{-0.3\\pgfplotmarksize}{\\pgfplotmarksize}}@");
937  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{\\pgfplotmarksize}}@");
938  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
939  PrintStr("\\pgfpathlineto{\\pgfpoint{+1\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
940  PrintStr("\\pgfpathlineto{\\pgfpoint{+1\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
941  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
942  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{-1.\\pgfplotmarksize}}@");
943  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{-1.\\pgfplotmarksize}}@");
944  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
945  PrintStr("\\pgfpathlineto{\\pgfpoint{-1.\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
946  PrintStr("\\pgfpathlineto{\\pgfpoint{-1.\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
947  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
948  PrintStr("\\pgfpathclose@");
949  PrintStr("\\pgfusepathqfillstroke@");
950  PrintStr("}@");
951 
952  // open star
953  PrintStr("\\pgfdeclareplotmark{newstar} {@");
954  PrintStr("\\pgfpathmoveto{\\pgfqpoint{0pt}{\\pgfplotmarksize}}@");
955  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{44}{0.5\\pgfplotmarksize}}@");
956  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{18}{\\pgfplotmarksize}}@");
957  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-20}{0.5\\pgfplotmarksize}}@");
958  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-54}{\\pgfplotmarksize}}@");
959  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-90}{0.5\\pgfplotmarksize}}@");
960  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{234}{\\pgfplotmarksize}}@");
961  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{198}{0.5\\pgfplotmarksize}}@");
962  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{162}{\\pgfplotmarksize}}@");
963  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{134}{0.5\\pgfplotmarksize}}@");
964  PrintStr("\\pgfpathclose@");
965  PrintStr("\\pgfusepathqstroke@");
966  PrintStr("}@");
967 
968  // filled star
969  PrintStr("\\pgfdeclareplotmark{newstar*} {@");
970  PrintStr("\\pgfpathmoveto{\\pgfqpoint{0pt}{\\pgfplotmarksize}}@");
971  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{44}{0.5\\pgfplotmarksize}}@");
972  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{18}{\\pgfplotmarksize}}@");
973  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-20}{0.5\\pgfplotmarksize}}@");
974  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-54}{\\pgfplotmarksize}}@");
975  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-90}{0.5\\pgfplotmarksize}}@");
976  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{234}{\\pgfplotmarksize}}@");
977  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{198}{0.5\\pgfplotmarksize}}@");
978  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{162}{\\pgfplotmarksize}}@");
979  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{134}{0.5\\pgfplotmarksize}}@");
980  PrintStr("\\pgfpathclose@");
981  PrintStr("\\pgfusepathqfillstroke@");
982  PrintStr("}@");
983 }