ROOT  6.06/08
Reference Guide
TPostScript.cxx
Go to the documentation of this file.
1 // @(#)root/postscript:$Id$
2 // Author: Rene Brun, Olivier Couet, Pierre Juillot, Oleksandr Grebenyuk, Yue Shi Lai
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 /** \class TPostScript
13 \ingroup PS
14 
15 Interface to PostScript.
16 
17 To generate a Postscript (or encapsulated ps) file corresponding to
18 a single image in a canvas, you can:
19 
20  - Select the <B>Print PostScript</B> item in the canvas <B>File</B> menu.
21  By default, a Postscript file with the name of the canvas.ps is generated.
22  - Click in the canvas area, near the edges, with the right mouse button
23  and select the <B>Print</B> item. You can select the name of the Postscript
24  file. If the file name is xxx.ps, you will generate a Postscript file named
25  xxx.ps. If the file name is xxx.eps, you generate an encapsulated Postscript
26  file instead.
27  - In your program (or macro), you can type:
28 ~~~ {.cpp}
29  c1->Print("xxx.ps")</B> or <B>c1->Print("xxx.eps").
30 ~~~
31  This will generate a file corresponding to the picture in the canvas
32  pointed by `c1`.
33 ~~~ {.cpp}
34  pad1->Print("xxx.ps");
35 ~~~
36  prints only the picture in the pad pointed by `pad1`.
37 
38 The size of the Postscript picture, by default, is computed to keep the aspect
39 ratio of the picture on the screen, where the size along x is always 20cm. You
40 can set the size of the PostScript picture before generating the picture
41 with a command such as:
42 
43 ~~~ {.cpp}
44  TPostScript myps("myfile.ps",111)
45  myps.Range(xsize,ysize);
46  object->Draw();
47  myps.Close();
48 ~~~
49 You can set the default paper size with:
50  ~~~ {.cpp}
51  gStyle->SetPaperSize(xsize,ysize);
52  ~~~
53 You can resume writing again in this file with `myps.Open();`.
54 Note that you may have several Postscript files opened simultaneously.
55 
56  ## Output type
57 
58 The output type allows to define how the PostScript output will looks like.
59 It allows to define the page format (A4, Legal etc..), the orientation
60 (Portrait, Landscape) and the number of images (zones) per page.
61 The output type has the following form:
62 
63 ~~~ {.cpp}
64  [Format][Nx][Ny][Type]
65 ~~~
66 
67 Where:
68 
69  - Format : Is an integer between 0 and 99 defining the page format:
70 ~~~ {.cpp}
71  Format = 3 the paper is in the standard A3 format.
72  Format = n (1<n<98) is an An format.
73  Format = 4 and Format=0 are the same and define an A4 page.
74  The A0 format is selected by Format=99.
75  The US format Letter is selected by Format = 100.
76  The US format Legal is selected by Format = 200.
77  The US format Ledger is selected by Format = 300.
78 ~~~
79  - Nx, Ny : Specify respectively the number of zones on the x and y axis.
80  Nx and Ny are integers between 1 and 9.
81  - Type : Can be equal to:
82  - 1 : Portrait mode with a small margin at the bottom of the page.
83  - 2 : Landscape mode with a small margin at the bottom of the page.
84  - 4 : Portrait mode with a large margin at the bottom of the page.
85  - 5 : Landscape mode with a large margin at the bottom of the page.
86  The large margin is useful for some PostScript printers (very often
87  for the colour printers) as they need more space to grip the paper
88  for mechanical reasons. Note that some PostScript colour printers
89  can also use the so called special A4 format permitting the full
90  usage of the A4 area; in this case larger margins are not necessary
91  and Type=1 or 2 can be used.
92  - 3 : Encapsulated PostScript. This Type permits the generation of files
93  which can be included in other documents, for example in LaTeX files.
94 
95 ## Making several pictures in the same Postscript file: case 1
96 
97 The following macro is an example illustrating how to open a Postscript
98 file and draw several pictures. The generation of a new Postscript page
99 is automatic when `TCanvas::Clear` is called by `object->Draw()`.
100 
101  ~~~ {.cpp}
102  {
103  TFile f("hsimple.root");
104  TCanvas c1("c1","canvas",800,600);
105 
106  // select postscript output type
107  // type = 111 portrait ps
108  // type = 112 landscape ps
109  // type = 113 eps
110  Int_t type = 111;
111 
112  // create a postscript file and set the paper size
113  TPostScript ps("test.ps",type);
114  ps.Range(16,24); //set x,y of printed page
115 
116  // draw 3 histograms from file hsimple.root on separate pages
117  hpx->Draw();
118  c1.Update(); //force drawing in a macro
119  hprof->Draw();
120  c1.Update();
121  hpx->Draw("lego1");
122  c1.Update();
123  ps.Close();
124  }
125  ~~~
126 
127 ## Making several pictures in the same Postscript file: case 2
128 
129 This example shows 2 pages. The canvas is divided.
130 `TPostScript::NewPage` must be called before starting a new
131 picture.`object->Draw` does not clear the canvas in this case
132 because we clear only the pads and not the main canvas.
133 Note that `c1->Update` must be called at the end of the first picture.
134 
135  ~~~ {.cpp}
136  {
137  TFile *f1 = new TFile("hsimple.root");
138  TCanvas *c1 = new TCanvas("c1");
139  TPostScript *ps = new TPostScript("file.ps",112);
140  c1->Divide(2,1);
141  // picture 1
142  ps->NewPage();
143  c1->cd(1);
144  hpx->Draw();
145  c1->cd(2);
146  hprof->Draw();
147  c1->Update();
148 
149  // picture 2
150  ps->NewPage();
151  c1->cd(1);
152  hpxpy->Draw();
153  c1->cd(2);
154  ntuple->Draw("px");
155  c1->Update();
156  ps->Close();
157 
158  // invoke Postscript viewer
159  gSystem->Exec("gs file.ps");
160  }
161  ~~~
162 
163 ## Making several pictures in the same Postscript file: case 3
164 This is the recommended way. If the Postscript file name finishes with
165 "(", the file remains opened (it is not closed). If the Postscript file name
166 finishes with ")" and the file has been opened with "(", the file is closed.
167 
168 Example:
169  ~~~ {.cpp}
170  {
171  TCanvas c1("c1");
172  h1.Draw();
173  c1.Print("c1.ps("); // write canvas and keep the ps file open
174  h2.Draw();
175  c1.Print("c1.ps"); // canvas is added to "c1.ps"
176  h3.Draw();
177  c1.Print("c1.ps)"); // canvas is added to "c1.ps" and ps file is closed
178  }
179  ~~~
180 The `TCanvas::Print("file.ps(")` mechanism is very useful, but it can
181 be a little inconvenient to have the action of opening/closing a file being
182 atomic with printing a page. Particularly if pages are being generated in some
183 loop one needs to detect the special cases of first and last page and then
184 munge the argument to Print() accordingly.
185 The "[" and "]" can be used instead of "(" and ")" as shown below.
186 
187 Example:
188  ~~~ {.cpp}
189  c1.Print("file.ps["); // No actual print, just open file.ps
190 
191  for (int i=0; i<10; ++i) {
192  // fill canvas for context i
193  // ...
194 
195  c1.Print("file.ps"); // Actually print canvas to the file
196  }
197 
198  c1.Print("file.ps]"); // No actual print, just close the file
199  ~~~
200 
201  ## Color Model
202 
203 TPostScript support two color model RGB and CMYK. CMY and CMYK models are
204 subtractive color models unlike RGB which is an additive. They are mainly
205 used for printing purposes. CMY means Cyan Magenta Yellow to convert RGB
206 to CMY it is enough to do: C=1-R, M=1-G and Y=1-B. CMYK has one more
207 component K (black). The conversion from RGB to CMYK is:
208 
209  ~~~ {.cpp}
210  Double_t Black = TMath::Min(TMath::Min(1-Red,1-Green),1-Blue);
211  Double_t Cyan = (1-Red-Black)/(1-Black);
212  Double_t Magenta = (1-Green-Black)/(1-Black);
213  Double_t Yellow = (1-Blue-Black)/(1-Black);
214  ~~~
215 CMYK add the black component which allows to have a better quality for black
216 printing. PostScript support the CMYK model.
217 
218 To change the color model use gStyle->SetColorModelPS(c).
219 
220  - c = 0 means TPostScript will use RGB color model (default)
221  - c = 1 means TPostScript will use CMYK color model
222 */
223 
224 #ifdef WIN32
225 #pragma optimize("",off)
226 #endif
227 
228 #include <stdlib.h>
229 #include <string.h>
230 #include <ctype.h>
231 #include <wchar.h>
232 #include <fontconfig/fontconfig.h>
233 
234 #include "Riostream.h"
235 #include "Byteswap.h"
236 #include "TROOT.h"
237 #include "TColor.h"
238 #include "TVirtualPad.h"
239 #include "TPoints.h"
240 #include "TPostScript.h"
241 #include "TStyle.h"
242 #include "TMath.h"
243 #include "TText.h"
244 #include "TSystem.h"
245 #include "TEnv.h"
246 
247 #include "../../../graf2d/mathtext/inc/fontembed.h"
248 
249 // to scale fonts to the same size as the old TT version
250 const Float_t kScale = 0.93376068;
251 
252 // Array defining if a font must be embedded or not.
253 static Bool_t MustEmbed[32];
254 
256 
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 /// Default PostScript constructor
261 
263 {
264  fStream = 0;
265  fType = 0;
266  gVirtualPS = this;
267  fBlue = 0.;
268  fBoundingBox = kFALSE;
269  fClear = kFALSE;
270  fClip = 0;
271  fClipStatus = kFALSE;
272  fCurrentColor = 0;
273  fDXC = 0.;
274  fDYC = 0.;
275  fFX = 0.;
276  fFY = 0.;
277  fGreen = 0.;
278  fIXzone = 0;
279  fIYzone = 0;
280  fLastCellBlue = 0;
281  fLastCellGreen = 0;
282  fLastCellRed = 0;
283  fLineJoin = 0;
284  fLineScale = 0.;
285  fMarkerSizeCur = 0.;
286  fMaxLines = 0;
287  fMaxsize = 0;
288  fMode = 0;
289  fNBSameColorCell = 0;
290  fNXzone = 0;
291  fNYzone = 0;
292  fNbCellLine = 0;
293  fNbCellW = 0;
294  fNbinCT = 0;
295  fNpages = 0;
296  fRange = kFALSE;
297  fRed = 0.;
298  fSave = 0;
299  fX1v = 0.;
300  fX1w = 0.;
301  fX2v = 0.;
302  fX2w = 0.;
303  fXC = 0.;
304  fXVP1 = 0.;
305  fXVP2 = 0.;
306  fXVS1 = 0.;
307  fXVS2 = 0.;
308  fXsize = 0.;
309  fY1v = 0.;
310  fY1w = 0.;
311  fY2v = 0.;
312  fY2w = 0.;
313  fYC = 0.;
314  fYVP1 = 0.;
315  fYVP2 = 0.;
316  fYVS1 = 0.;
317  fYVS2 = 0.;
318  fYsize = 0.;
319  fZone = kFALSE;
320  fFileName = "";
321  fFontEmbed = kFALSE;
322  Int_t i;
323  for (i=0; i<32; i++) fPatterns[i] = 0;
324  for (i=0; i<32; i++) MustEmbed[i] = kFALSE;
325  SetTitle("PS");
326 }
327 
328 ////////////////////////////////////////////////////////////////////////////////
329 /// Initialize the PostScript interface
330 ///
331 /// - fname : PostScript file name
332 /// - wtype : PostScript workstation type
333 ///
334 ///
335 /// The possible workstation types are:
336 /// - 111 ps Portrait
337 /// - 112 ps Landscape
338 /// - 113 eps
339 
340 TPostScript::TPostScript(const char *fname, Int_t wtype)
341 :TVirtualPS(fname, wtype)
342 {
343  fStream = 0;
344  SetTitle("PS");
345  Open(fname, wtype);
346 }
347 
348 ////////////////////////////////////////////////////////////////////////////////
349 /// Open a PostScript file
350 
351 void TPostScript::Open(const char *fname, Int_t wtype)
352 {
353  if (fStream) {
354  Warning("Open", "postscript file already open");
355  return;
356  }
357 
358  fMarkerSizeCur = 0;
359  fCurrentColor = 0;
360  fRed = -1;
361  fGreen = -1;
362  fBlue = -1;
363  fLenBuffer = 0;
364  fClip = 0;
365  fType = abs(wtype);
366  fClear = kTRUE;
367  fZone = kFALSE;
368  fSave = 0;
369  fFontEmbed = kFALSE;
372  fMode = fType%10;
373  Float_t xrange, yrange;
374  if (gPad) {
375  Double_t ww = gPad->GetWw();
376  Double_t wh = gPad->GetWh();
377  if (fType == 113) {
378  ww *= gPad->GetWNDC();
379  wh *= gPad->GetHNDC();
380  }
381  Double_t ratio = wh/ww;
382  if (fType == 112) {
383  xrange = fYsize;
384  yrange = xrange*ratio;
385  if (yrange > fXsize) { yrange = fXsize; xrange = yrange/ratio;}
386  } else {
387  xrange = fXsize;
388  yrange = fXsize*ratio;
389  if (yrange > fYsize) { yrange = fYsize; xrange = yrange/ratio;}
390  }
391  fXsize = xrange; fYsize = yrange;
392  }
393 
394  // Open OS file
395  fFileName = fname;
396  fStream = new std::ofstream(fFileName.Data(),std::ios::out);
398  printf("ERROR in TPostScript::Open: Cannot open file:%s\n",fFileName.Data());
399  return;
400  }
401  gVirtualPS = this;
402 
403  for (Int_t i=0;i<fSizBuffer;i++) fBuffer[i] = ' ';
404  if( fType == 113) {
406  PrintStr("%!PS-Adobe-2.0 EPSF-2.0@");
407  } else {
409  PrintStr("%!PS-Adobe-2.0@");
410  Initialize();
411  }
412 
414  fRange = kFALSE;
415 
416  // Set a default range
417  Range(fXsize, fYsize);
418 
419  fPrinted = kFALSE;
420  if (fType == 113) NewPage();
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Default PostScript destructor
425 
427 {
428  Close();
429 }
430 
431 ////////////////////////////////////////////////////////////////////////////////
432 /// Close a PostScript file
433 
435 {
436  if (!gVirtualPS) return;
437  if (!fStream) return;
438  if (gPad) gPad->Update();
439  if( fMode != 3) {
440  SaveRestore(-1);
441  if( fPrinted ) { PrintStr("showpage@"); SaveRestore(-1);}
442  PrintStr("@");
443  PrintStr("%%Trailer@");
444  PrintStr("%%Pages: ");
446  PrintStr("@");
447  while (fSave > 0) { SaveRestore(-1); }
448  } else {
449  PrintStr("@");
450  while (fSave > 0) { SaveRestore(-1); }
451  PrintStr("showpage@");
452  PrintStr("end@");
453  }
454  PrintStr("@");
455  PrintStr("%%EOF@");
456 
457  // Embed the fonts previously used by TMathText
458  if (!fFontEmbed) {
459  // Close the file fFileName
460  if (fStream) {
461  PrintStr("@");
462  fStream->close(); delete fStream; fStream = 0;
463  }
464 
465  // Rename the file fFileName
466  TString tmpname = Form("%s_tmp_%d",fFileName.Data(),gSystem->GetPid());
467  if (gSystem->Rename( fFileName.Data() , tmpname.Data())) {
468  Error("Text", "Cannot open temporary file: %s\n", tmpname.Data());
469  return;
470  }
471 
472  // Reopen the file fFileName
473  fStream = new std::ofstream(fFileName.Data(),std::ios::out);
475  Error("Text", "Cannot open file: %s\n", fFileName.Data());
476  return;
477  }
478 
479  // Embed the fonts at the right place
480  FILE *sg = fopen(tmpname.Data(),"r");
481  if (sg == 0) {
482  Error("Text", "Cannot open file: %s\n", tmpname.Data());
483  return;
484  }
485  char line[255];
486  while (fgets(line,255,sg)) {
487  if (strstr(line,"EndComments")) PrintStr("%%DocumentNeededResources: ProcSet (FontSetInit)@");
488  fStream->write(line,strlen(line));
489  if (!fFontEmbed && strstr(line,"m5")) {
490  FontEmbed();
491  PrintStr("@");
492  }
493  }
494  fclose(sg);
495  if (gSystem->Unlink(tmpname.Data())) return;
496  }
497 
498  fFontEmbed = kFALSE;
499 
500  // Close file stream
501 
502  if (fStream) { fStream->close(); delete fStream; fStream = 0;}
503 
504  gVirtualPS = 0;
505 }
506 
507 ////////////////////////////////////////////////////////////////////////////////
508 /// Activate an already open PostScript file
509 
511 {
512  if (!fType) {
513  Error("On", "no postscript file open");
514  Off();
515  return;
516  }
517  gVirtualPS = this;
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// Deactivate an already open PostScript file
522 
524 {
525  gVirtualPS = 0;
526 }
527 
528 ////////////////////////////////////////////////////////////////////////////////
529 /// Draw a Cell Array
530 ///
531 /// Drawing a PostScript Cell Array is in fact done thanks to three
532 /// procedures: CellArrayBegin, CellArrayFill, and CellArrayEnd.
533 ///
534 /// - CellArrayBegin: Initiate the Cell Array by writing the necessary
535 /// PostScript procedures and the initial values of the
536 /// required parameters. The input parameters are:
537 /// - W: number of boxes along the width.
538 /// - H: number of boxes along the height
539 /// - x1,x2,y1,y2: First box coordinates.
540 /// - CellArrayFill: Is called for each box of the Cell Array. The first
541 /// box is the top left one and the last box is the
542 /// bottom right one. The input parameters are the Red,
543 /// Green, and Blue components of the box colour. These
544 /// Levels are between 0 and 255.
545 /// - CellArrayEnd: Finishes the Cell Array.
546 ///
547 /// PostScript cannot handle arrays larger than 65535. So the Cell Array
548 /// is drawn in several pieces.
549 
551  Double_t y1, Double_t y2)
552 {
553  Int_t ix1 = XtoPS(x1);
554  Int_t iy1 = YtoPS(y1);
555 
556  Float_t wt = (288/2.54)*gPad->GetAbsWNDC()*
557  fXsize*((x2 - x1)/(gPad->GetX2()-gPad->GetX1()));
558  Float_t ht = (288/2.54)*gPad->GetAbsHNDC()*
559  fYsize*((y2 - y1)/(gPad->GetY2()-gPad->GetY1()));
560 
561  fLastCellRed = 300;
562  fLastCellGreen = 300;
563  fLastCellBlue = 300;
564  fNBSameColorCell = 0;
565 
566  fNbinCT = 0;
567  fNbCellW = W;
568  fNbCellLine = 0;
569  fMaxLines = 40000/(3*fNbCellW);
570 
571  // Define some parameters
572  PrintStr("@/WT"); WriteReal(wt) ; PrintStr(" def"); // Cells width
573  PrintStr(" /HT"); WriteReal(ht) ; PrintStr(" def"); // Cells height
574  PrintStr(" /XS"); WriteInteger(ix1) ; PrintStr(" def"); // X start
575  PrintStr(" /YY"); WriteInteger(iy1) ; PrintStr(" def"); // Y start
576  PrintStr(" /NX"); WriteInteger(W) ; PrintStr(" def"); // Number of columns
577  PrintStr(" /NY"); WriteInteger(fMaxLines); PrintStr(" def"); // Number of lines
578 
579  // This PS procedure draws one cell.
580  PrintStr(" /DrawCell ");
581  PrintStr( "{WT HT XX YY bf");
582  PrintStr( " /NBBD NBBD 1 add def");
583  PrintStr( " NBBD NBB eq {exit} if");
584  PrintStr( " /XX WT XX add def");
585  PrintStr( " IX NX eq ");
586  PrintStr( "{/YY YY HT sub def");
587  PrintStr( " /XX XS def");
588  PrintStr( " /IX 0 def} if");
589  PrintStr( " /IX IX 1 add def} def");
590 
591  // This PS procedure draws fMaxLines line. It takes care of duplicated
592  // colors. Values "n" greater than 300 mean than the previous color
593  // should be duplicated n-300 times.
594  PrintStr(" /DrawCT ");
595  PrintStr( "{/NBB NX NY mul def");
596  PrintStr( " /XX XS def");
597  PrintStr( " /IX 1 def");
598  PrintStr( " /NBBD 0 def");
599  PrintStr( " /RC 0 def /GC 1 def /BC 2 def");
600  PrintStr( " 1 1 NBB ");
601  PrintStr( "{/NB CT RC get def");
602  PrintStr( " NB 301 ge ");
603  PrintStr( "{/NBL NB 300 sub def");
604  PrintStr( " 1 1 NBL ");
605  PrintStr( "{DrawCell}");
606  PrintStr( " for");
607  PrintStr( " /RC RC 1 add def");
608  PrintStr( " /GC RC 1 add def");
609  PrintStr( " /BC RC 2 add def}");
610  PrintStr( "{CT RC get 255 div CT GC get 255 div CT BC get 255 div setrgbcolor");
611  PrintStr( " DrawCell");
612  PrintStr( " /RC RC 3 add def");
613  PrintStr( " /GC GC 3 add def");
614  PrintStr( " /BC BC 3 add def} ifelse NBBD NBB eq {exit} if} for");
615  PrintStr( " /YY YY HT sub def clear} def");
616 
617  PrintStr(" /CT [");
618 }
619 
620 ////////////////////////////////////////////////////////////////////////////////
621 /// Paint the Cell Array
622 
624 {
625  if (fLastCellRed == r && fLastCellGreen == g && fLastCellBlue == b) {
627  } else {
628  if (fNBSameColorCell != 0 ) {
630  fNBSameColorCell = 0;
631  }
632  WriteInteger(r);
633  WriteInteger(g);
634  WriteInteger(b);
635  fLastCellRed = r;
636  fLastCellGreen = g;
637  fLastCellBlue = b;
638  }
639 
640  fNbinCT++;
641  if (fNbinCT == fNbCellW) {
642  fNbCellLine++;
643  fNbinCT = 0;
644  }
645 
646  if (fNbCellLine == fMaxLines) {
648  PrintStr("] def DrawCT /CT [");
649  fNbCellLine = 0;
650  fLastCellRed = 300;
651  fLastCellGreen = 300;
652  fLastCellBlue = 300;
653  fNBSameColorCell = 0;
654  fNbinCT = 0;
655  }
656 }
657 
658 ////////////////////////////////////////////////////////////////////////////////
659 /// End the Cell Array painting
660 
662 {
664  PrintStr("] def /NY");
666  PrintStr(" def DrawCT ");
667 }
668 
669 ////////////////////////////////////////////////////////////////////////////////
670 /// Define the markers
671 
673 {
674  PrintStr("/mp {newpath /y exch def /x exch def} def@");
675  PrintStr("/side {[w .77 mul w .23 mul] .385 w mul sd w 0 l currentpoint t -144 r} def@");
676  PrintStr("/mr {mp x y w2 0 360 arc} def /m24 {mr s} def /m20 {mr f} def@");
677  PrintStr("/mb {mp x y w2 add m w2 neg 0 d 0 w neg d w 0 d 0 w d cl} def@");
678  PrintStr("/mt {mp x y w2 add m w2 neg w neg d w 0 d cl} def@");
679  PrintStr("/m21 {mb f} def /m25 {mb s} def /m22 {mt f} def /m26{mt s} def@");
680  PrintStr("/m23 {mp x y w2 sub m w2 w d w neg 0 d cl f} def@");
681  PrintStr("/m27 {mp x y w2 add m w3 neg w2 neg d w3 w2 neg d w3 w2 d cl s} def@");
682  PrintStr("/m28 {mp x w2 sub y w2 sub w3 add m w3 0 d ");
683  PrintStr(" 0 w3 neg d w3 0 d 0 w3 d w3 0 d ");
684  PrintStr(" 0 w3 d w3 neg 0 d 0 w3 d w3 neg 0 d");
685  PrintStr(" 0 w3 neg d w3 neg 0 d cl s } def@");
686  PrintStr("/m29 {mp gsave x w2 sub y w2 add w3 sub m currentpoint t");
687  PrintStr(" 4 {side} repeat cl fill gr} def@");
688  PrintStr("/m30 {mp gsave x w2 sub y w2 add w3 sub m currentpoint t");
689  PrintStr(" 4 {side} repeat cl s gr} def@");
690  PrintStr("/m31 {mp x y w2 sub m 0 w d x w2 sub y m w 0 d");
691  PrintStr(" x w2 sub y w2 add m w w neg d x w2 sub y w2");
692  PrintStr(" sub m w w d s} def@");
693  PrintStr("/m32 {mp x y w2 sub m w2 w d w neg 0 d cl s} def@");
694  PrintStr("/m33 {mp x y w2 add m w3 neg w2 neg d w3 w2 neg d w3 w2 d cl f} def@");
695  PrintStr("/m34 {mp x w2 sub y w2 sub w3 add m w3 0 d ");
696  PrintStr(" 0 w3 neg d w3 0 d 0 w3 d w3 0 d ");
697  PrintStr(" 0 w3 d w3 neg 0 d 0 w3 d w3 neg 0 d");
698  PrintStr(" 0 w3 neg d w3 neg 0 d cl f } def@");
699  PrintStr("/m2 {mp x y w2 sub m 0 w d x w2 sub y m w 0 d s} def@");
700  PrintStr("/m5 {mp x w2 sub y w2 sub m w w d x w2 sub y w2 add m w w neg d s} def@");
701 }
702 
703 ////////////////////////////////////////////////////////////////////////////////
704 /// Draw a Box
705 
707 {
708  static Double_t x[4], y[4];
709  Int_t ix1 = XtoPS(x1);
710  Int_t ix2 = XtoPS(x2);
711  Int_t iy1 = YtoPS(y1);
712  Int_t iy2 = YtoPS(y2);
713  Int_t fillis = fFillStyle/1000;
714  Int_t fillsi = fFillStyle%1000;
715 
716  if (fillis == 3 || fillis == 2) {
717  if (fillsi > 99) {
718  x[0] = x1; y[0] = y1;
719  x[1] = x2; y[1] = y1;
720  x[2] = x2; y[2] = y2;
721  x[3] = x1; y[3] = y2;
722  return;
723  }
724  if (fillsi > 0 && fillsi < 26) {
725  x[0] = x1; y[0] = y1;
726  x[1] = x2; y[1] = y1;
727  x[2] = x2; y[2] = y2;
728  x[3] = x1; y[3] = y2;
729  DrawPS(-4, &x[0], &y[0]);
730  }
731  if (fillsi == -3) {
732  SetColor(5);
733  WriteInteger(ix2 - ix1);
734  WriteInteger(iy2 - iy1);
735  WriteInteger(ix1);
736  WriteInteger(iy1);
737  PrintFast(3," bf");
738  }
739  }
740  if (fillis == 1) {
742  WriteInteger(ix2 - ix1);
743  WriteInteger(iy2 - iy1);
744  WriteInteger(ix1);
745  WriteInteger(iy1);
746  PrintFast(3," bf");
747  }
748  if (fillis == 0) {
749  if (fLineWidth<=0) return;
751  WriteInteger(ix2 - ix1);
752  WriteInteger(iy2 - iy1);
753  WriteInteger(ix1);
754  WriteInteger(iy1);
755  PrintFast(3," bl");
756  }
757 }
758 
759 ////////////////////////////////////////////////////////////////////////////////
760 /// Draw a Frame around a box
761 ///
762 /// - mode = -1 box looks as it is behind the screen
763 /// - mode = 1 box looks as it is in front of the screen
764 /// - border is the border size in already precomputed PostScript units
765 /// - dark is the color for the dark part of the frame
766 /// - light is the color for the light part of the frame
767 
769  Int_t mode, Int_t border, Int_t dark, Int_t light)
770 {
771  static Int_t xps[7], yps[7];
772  Int_t i, ixd0, iyd0, idx, idy, ixdi, iydi, ix, iy;
773 
774  // Draw top&left part of the box
775  if (mode == -1) SetColor(dark);
776  else SetColor(light);
777  Int_t bordPS = 4*border;
778  xps[0] = XtoPS(xl); yps[0] = YtoPS(yl);
779  xps[1] = xps[0] + bordPS; yps[1] = yps[0] + bordPS;
780  xps[2] = xps[1]; yps[2] = YtoPS(yt) - bordPS;
781  xps[3] = XtoPS(xt) - bordPS; yps[3] = yps[2];
782  xps[4] = XtoPS(xt); yps[4] = YtoPS(yt);
783  xps[5] = xps[0]; yps[5] = yps[4];
784  xps[6] = xps[0]; yps[6] = yps[0];
785 
786  ixd0 = xps[0];
787  iyd0 = yps[0];
788  WriteInteger(ixd0);
789  WriteInteger(iyd0);
790 
791  PrintFast(2," m");
792  idx = 0;
793  idy = 0;
794  for (i=1;i<7;i++) {
795  ixdi = xps[i];
796  iydi = yps[i];
797  ix = ixdi - ixd0;
798  iy = iydi - iyd0;
799  ixd0 = ixdi;
800  iyd0 = iydi;
801  if( ix && iy) {
802  if( idx ) { MovePS(idx,0); idx = 0; }
803  if( idy ) { MovePS(0,idy); idy = 0; }
804  MovePS(ix,iy);
805  continue;
806  }
807  if ( ix ) {
808  if( idy ) { MovePS(0,idy); idy = 0; }
809  if( !idx ) { idx = ix; continue;}
810  if( ix*idx > 0 ) idx += ix;
811  else { MovePS(idx,0); idx = ix; }
812  continue;
813  }
814  if( iy ) {
815  if( idx ) { MovePS(idx,0); idx = 0; }
816  if( !idy) { idy = iy; continue;}
817  if( iy*idy > 0 ) idy += iy;
818  else { MovePS(0,idy); idy = iy; }
819  }
820  }
821  if( idx ) MovePS(idx,0);
822  if( idy ) MovePS(0,idy);
823  PrintFast(2," f");
824 
825  // Draw bottom&right part of the box
826  if (mode == -1) SetColor(light);
827  else SetColor(dark);
828  xps[0] = XtoPS(xl); yps[0] = YtoPS(yl);
829  xps[1] = xps[0] + bordPS; yps[1] = yps[0] + bordPS;
830  xps[2] = XtoPS(xt) - bordPS; yps[2] = yps[1];
831  xps[3] = xps[2]; yps[3] = YtoPS(yt) - bordPS;
832  xps[4] = XtoPS(xt); yps[4] = YtoPS(yt);
833  xps[5] = xps[4]; yps[5] = yps[0];
834  xps[6] = xps[0]; yps[6] = yps[0];
835 
836  ixd0 = xps[0];
837  iyd0 = yps[0];
838  WriteInteger(ixd0);
839  WriteInteger(iyd0);
840 
841  PrintFast(2," m");
842  idx = 0;
843  idy = 0;
844  for (i=1;i<7;i++) {
845  ixdi = xps[i];
846  iydi = yps[i];
847  ix = ixdi - ixd0;
848  iy = iydi - iyd0;
849  ixd0 = ixdi;
850  iyd0 = iydi;
851  if( ix && iy) {
852  if( idx ) { MovePS(idx,0); idx = 0; }
853  if( idy ) { MovePS(0,idy); idy = 0; }
854  MovePS(ix,iy);
855  continue;
856  }
857  if ( ix ) {
858  if( idy ) { MovePS(0,idy); idy = 0; }
859  if( !idx ) { idx = ix; continue;}
860  if( ix*idx > 0 ) idx += ix;
861  else { MovePS(idx,0); idx = ix; }
862  continue;
863  }
864  if( iy ) {
865  if( idx ) { MovePS(idx,0); idx = 0; }
866  if( !idy) { idy = iy; continue;}
867  if( iy*idy > 0 ) idy += iy;
868  else { MovePS(0,idy); idy = iy; }
869  }
870  }
871  if( idx ) MovePS(idx,0);
872  if( idy ) MovePS(0,idy);
873  PrintFast(2," f");
874 }
875 
876 ////////////////////////////////////////////////////////////////////////////////
877 /// Draw a PolyLine
878 ///
879 /// Draw a polyline through the points xy.
880 /// - If nn=1 moves only to point x,y.
881 /// - If nn=0 the x,y are written in the PostScript file
882 /// according to the current transformation.
883 /// - If nn>0 the line is clipped as a line.
884 /// - If nn<0 the line is clipped as a fill area.
885 
887 {
888  Int_t i, n, ixd0, iyd0, idx, idy, ixdi, iydi, ix, iy;
889  Style_t linestylesav = fLineStyle;
890  Width_t linewidthsav = fLineWidth;
891  if (nn > 0) {
892  if (fLineWidth<=0) return;
893  n = nn;
897  } else {
898  n = -nn;
899  SetLineStyle(1);
900  SetLineWidth(1);
902  }
903 
904  ixd0 = XtoPS(xy[0].GetX());
905  iyd0 = YtoPS(xy[0].GetY());
906  WriteInteger(ixd0);
907  WriteInteger(iyd0);
908  if( n <= 1) {
909  if( n == 0) goto END;
910  PrintFast(2," m");
911  goto END;
912  }
913 
914  PrintFast(2," m");
915  idx = 0;
916  idy = 0;
917  for (i=1;i<n;i++) {
918  ixdi = XtoPS(xy[i].GetX());
919  iydi = YtoPS(xy[i].GetY());
920  ix = ixdi - ixd0;
921  iy = iydi - iyd0;
922  ixd0 = ixdi;
923  iyd0 = iydi;
924  if( ix && iy) {
925  if( idx ) { MovePS(idx,0); idx = 0; }
926  if( idy ) { MovePS(0,idy); idy = 0; }
927  MovePS(ix,iy);
928  continue;
929  }
930  if ( ix ) {
931  if( idy ) { MovePS(0,idy); idy = 0; }
932  if( !idx ) { idx = ix; continue;}
933  if( ix*idx > 0 ) idx += ix;
934  else { MovePS(idx,0); idx = ix; }
935  continue;
936  }
937  if( iy ) {
938  if( idx ) { MovePS(idx,0); idx = 0; }
939  if( !idy) { idy = iy; continue;}
940  if( iy*idy > 0 ) idy += iy;
941  else { MovePS(0,idy); idy = iy; }
942  }
943  }
944  if( idx ) MovePS(idx,0);
945  if( idy ) MovePS(0,idy);
946 
947  if (nn > 0 ) {
948  if (xy[0].GetX() == xy[n-1].GetX() && xy[0].GetY() == xy[n-1].GetY()) PrintFast(3," cl");
949  PrintFast(2," s");
950  } else {
951  PrintFast(2," f");
952  }
953 END:
954  if (nn < 0) {
955  SetLineStyle(linestylesav);
956  SetLineWidth(linewidthsav);
957  }
958 }
959 
960 ////////////////////////////////////////////////////////////////////////////////
961 /// Draw a PolyLine in NDC space
962 ///
963 /// Draw a polyline through the points xy.
964 /// - If nn=1 moves only to point x,y.
965 /// - If nn=0 the x,y are written in the PostScript file
966 /// according to the current transformation.
967 /// - If nn>0 the line is clipped as a line.
968 /// - If nn<0 the line is clipped as a fill area.
969 
971 {
972  Int_t i, n, ixd0, iyd0, idx, idy, ixdi, iydi, ix, iy;
973  Style_t linestylesav = fLineStyle;
974  Width_t linewidthsav = fLineWidth;
975  if (nn > 0) {
976  if (fLineWidth<=0) return;
977  n = nn;
981  } else {
982  n = -nn;
983  SetLineStyle(1);
984  SetLineWidth(1);
986  }
987 
988  ixd0 = UtoPS(xy[0].GetX());
989  iyd0 = VtoPS(xy[0].GetY());
990  WriteInteger(ixd0);
991  WriteInteger(iyd0);
992  if( n <= 1) {
993  if( n == 0) goto END;
994  PrintFast(2," m");
995  goto END;
996  }
997 
998  PrintFast(2," m");
999  idx = 0;
1000  idy = 0;
1001  for (i=1;i<n;i++) {
1002  ixdi = UtoPS(xy[i].GetX());
1003  iydi = VtoPS(xy[i].GetY());
1004  ix = ixdi - ixd0;
1005  iy = iydi - iyd0;
1006  ixd0 = ixdi;
1007  iyd0 = iydi;
1008  if( ix && iy) {
1009  if( idx ) { MovePS(idx,0); idx = 0; }
1010  if( idy ) { MovePS(0,idy); idy = 0; }
1011  MovePS(ix,iy);
1012  continue;
1013  }
1014  if ( ix ) {
1015  if( idy ) { MovePS(0,idy); idy = 0; }
1016  if( !idx ) { idx = ix; continue;}
1017  if( ix*idx > 0 ) idx += ix;
1018  else { MovePS(idx,0); idx = ix; }
1019  continue;
1020  }
1021  if( iy ) {
1022  if( idx ) { MovePS(idx,0); idx = 0; }
1023  if( !idy) { idy = iy; continue;}
1024  if( iy*idy > 0 ) idy += iy;
1025  else { MovePS(0,idy); idy = iy; }
1026  }
1027  }
1028  if( idx ) MovePS(idx,0);
1029  if( idy ) MovePS(0,idy);
1030 
1031  if (nn > 0 ) {
1032  if (xy[0].GetX() == xy[n-1].GetX() && xy[0].GetY() == xy[n-1].GetY()) PrintFast(3," cl");
1033  PrintFast(2," s");
1034  } else {
1035  PrintFast(2," f");
1036  }
1037 END:
1038  if (nn < 0) {
1039  SetLineStyle(linestylesav);
1040  SetLineWidth(linewidthsav);
1041  }
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////
1045 /// Draw markers at the n WC points x, y
1046 
1048 {
1049  Int_t i, np, markerstyle;
1050  Float_t markersize;
1051  static char chtemp[10];
1052 
1053  if (!fMarkerSize) return;
1054  Style_t linestylesav = fLineStyle;
1055  Width_t linewidthsav = fLineWidth;
1056  SetLineStyle(1);
1057  SetLineWidth(1);
1059  markerstyle = abs(fMarkerStyle);
1060  if (markerstyle <= 0) strlcpy(chtemp, " m20",10);
1061  if (markerstyle == 1) strlcpy(chtemp, " m20",10);
1062  if (markerstyle == 2) strlcpy(chtemp, " m2",10);
1063  if (markerstyle == 3) strlcpy(chtemp, " m31",10);
1064  if (markerstyle == 4) strlcpy(chtemp, " m24",10);
1065  if (markerstyle == 5) strlcpy(chtemp, " m5",10);
1066  if (markerstyle >= 6 && markerstyle <= 19) strlcpy(chtemp, " m20",10);
1067  if (markerstyle >= 20 && markerstyle <= 34 ) snprintf(chtemp,10," m%d", markerstyle);
1068  if (markerstyle >= 35) strlcpy(chtemp, " m20",10);
1069 
1070  // Set the PostScript marker size
1071  if (markerstyle == 1) {
1072  markersize = 2.;
1073  } else if (markerstyle == 6) {
1074  markersize = 4.;
1075  } else if (markerstyle == 7) {
1076  markersize = 8.;
1077  } else {
1078  Float_t symbolsize = fMarkerSize;
1079  const Int_t kBASEMARKER = 8;
1080  Float_t sbase = symbolsize*kBASEMARKER;
1081  Float_t s2x = sbase / Float_t(gPad->GetWw() * gPad->GetAbsWNDC());
1082  markersize = this->UtoPS(s2x) - this->UtoPS(0);
1083  }
1084 
1085  if (fMarkerSizeCur != markersize) {
1086  fMarkerSizeCur = markersize;
1087  PrintFast(3," /w");
1088  WriteInteger(Int_t(markersize+0.5));
1089  PrintFast(40," def /w2 {w 2 div} def /w3 {w 3 div} def");
1090  }
1091 
1092  WriteInteger(XtoPS(x[0]));
1093  WriteInteger(YtoPS(y[0]));
1094  if (n == 1) {
1095  PrintStr(chtemp);
1096  SetLineStyle(linestylesav);
1097  SetLineWidth(linewidthsav);
1098  return;
1099  }
1100  np = 1;
1101  for (i=1;i<n;i++) {
1102  WriteInteger(XtoPS(x[i]));
1103  WriteInteger(YtoPS(y[i]));
1104  np++;
1105  if (np == 100 || i == n-1) {
1106  WriteInteger(np);
1107  PrintFast(2," {");
1108  PrintStr(chtemp);
1109  PrintFast(3,"} R");
1110  np = 0;
1111  }
1112  }
1113  SetLineStyle(linestylesav);
1114  SetLineWidth(linewidthsav);
1115 }
1116 
1117 ////////////////////////////////////////////////////////////////////////////////
1118 /// Draw markers at the n WC points x, y
1119 
1121 {
1122  Int_t i, np, markerstyle;
1123  Float_t markersize;
1124  static char chtemp[10];
1125 
1126  if (!fMarkerSize) return;
1127  Style_t linestylesav = fLineStyle;
1128  Width_t linewidthsav = fLineWidth;
1129  SetLineStyle(1);
1130  SetLineWidth(1);
1132  markerstyle = abs(fMarkerStyle);
1133  if (markerstyle <= 0) strlcpy(chtemp, " m20",10);
1134  if (markerstyle == 1) strlcpy(chtemp, " m20",10);
1135  if (markerstyle == 2) strlcpy(chtemp, " m2",10);
1136  if (markerstyle == 3) strlcpy(chtemp, " m31",10);
1137  if (markerstyle == 4) strlcpy(chtemp, " m24",10);
1138  if (markerstyle == 5) strlcpy(chtemp, " m5",10);
1139  if (markerstyle >= 6 && markerstyle <= 19) strlcpy(chtemp, " m20",10);
1140  if (markerstyle >= 20 && markerstyle <= 34 ) snprintf(chtemp,10," m%d", markerstyle);
1141  if (markerstyle >= 35) strlcpy(chtemp, " m20",10);
1142 
1143  // Set the PostScript marker size
1144  if (markerstyle == 1) {
1145  markersize = 2.;
1146  } else if (markerstyle == 6) {
1147  markersize = 4.;
1148  } else if (markerstyle == 7) {
1149  markersize = 8.;
1150  } else {
1151  Float_t symbolsize = fMarkerSize;
1152  const Int_t kBASEMARKER = 8;
1153  Float_t sbase = symbolsize*kBASEMARKER;
1154  Float_t s2x = sbase / Float_t(gPad->GetWw() * gPad->GetAbsWNDC());
1155  markersize = this->UtoPS(s2x) - this->UtoPS(0);
1156  }
1157 
1158  if (fMarkerSizeCur != markersize) {
1159  fMarkerSizeCur = markersize;
1160  PrintFast(3," /w");
1161  WriteInteger(Int_t(markersize+0.5));
1162  PrintFast(40," def /w2 {w 2 div} def /w3 {w 3 div} def");
1163  }
1164 
1165  WriteInteger(XtoPS(x[0]));
1166  WriteInteger(YtoPS(y[0]));
1167  if (n == 1) {
1168  PrintStr(chtemp);
1169  SetLineStyle(linestylesav);
1170  SetLineWidth(linewidthsav);
1171  return;
1172  }
1173  np = 1;
1174  for (i=1;i<n;i++) {
1175  WriteInteger(XtoPS(x[i]));
1176  WriteInteger(YtoPS(y[i]));
1177  np++;
1178  if (np == 100 || i == n-1) {
1179  WriteInteger(np);
1180  PrintFast(2," {");
1181  PrintStr(chtemp);
1182  PrintFast(3,"} R");
1183  np = 0;
1184  }
1185  }
1186  SetLineStyle(linestylesav);
1187  SetLineWidth(linewidthsav);
1188 }
1189 
1190 ////////////////////////////////////////////////////////////////////////////////
1191 /// Draw a PolyLine
1192 ///
1193 /// Draw a polyline through the points xw,yw.
1194 /// - If nn=1 moves only to point xw,yw.
1195 /// - If nn=0 the XW(1) and YW(1) are written in the PostScript file
1196 /// according to the current NT.
1197 /// - If nn>0 the line is clipped as a line.
1198 /// - If nn<0 the line is clipped as a fill area.
1199 
1201 {
1202  static Float_t dyhatch[24] = {.0075,.0075,.0075,.0075,.0075,.0075,.0075,.0075,
1203  .01 ,.01 ,.01 ,.01 ,.01 ,.01 ,.01 ,.01 ,
1204  .015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015};
1205  static Float_t anglehatch[24] = {180, 90,135, 45,150, 30,120, 60,
1206  180, 90,135, 45,150, 30,120, 60,
1207  180, 90,135, 45,150, 30,120, 60};
1208  Int_t i, n, ixd0, iyd0, idx, idy, ixdi, iydi, ix, iy, fais, fasi;
1209  fais = fasi = n = 0;
1210  Int_t jxd0 = XtoPS(xw[0]);
1211  Int_t jyd0 = YtoPS(yw[0]);
1212  Style_t linestylesav = fLineStyle;
1213  Width_t linewidthsav = fLineWidth;
1214 
1215  if (nn > 0) {
1216  if (fLineWidth<=0) return;
1217  n = nn;
1221  }
1222  if (nn < 0) {
1223  n = -nn;
1224  SetLineStyle(1);
1225  SetLineWidth(1);
1227  fais = fFillStyle/1000;
1228  fasi = fFillStyle%1000;
1229  if (fais == 3 || fais == 2) {
1230  if (fasi > 100 && fasi <125) {
1231  DrawHatch(dyhatch[fasi-101],anglehatch[fasi-101], n, xw, yw);
1232  goto END;
1233  }
1234  if (fasi > 0 && fasi < 26) {
1236  }
1237  }
1238  }
1239 
1240  ixd0 = jxd0;
1241  iyd0 = jyd0;
1242  WriteInteger(ixd0);
1243  WriteInteger(iyd0);
1244  if( n <= 1) {
1245  if( n == 0) goto END;
1246  PrintFast(2," m");
1247  goto END;
1248  }
1249 
1250  PrintFast(2," m");
1251  idx = idy = 0;
1252  for (i=1;i<n;i++) {
1253  ixdi = XtoPS(xw[i]);
1254  iydi = YtoPS(yw[i]);
1255  ix = ixdi - ixd0;
1256  iy = iydi - iyd0;
1257  ixd0 = ixdi;
1258  iyd0 = iydi;
1259  if( ix && iy) {
1260  if( idx ) { MovePS(idx,0); idx = 0; }
1261  if( idy ) { MovePS(0,idy); idy = 0; }
1262  MovePS(ix,iy);
1263  } else if ( ix ) {
1264  if( idy ) { MovePS(0,idy); idy = 0;}
1265  if( !idx ) { idx = ix;}
1266  else if( TMath::Sign(ix,idx) == ix ) idx += ix;
1267  else { MovePS(idx,0); idx = ix;}
1268  } else if( iy ) {
1269  if( idx ) { MovePS(idx,0); idx = 0;}
1270  if( !idy) { idy = iy;}
1271  else if( TMath::Sign(iy,idy) == iy) idy += iy;
1272  else { MovePS(0,idy); idy = iy;}
1273  }
1274  }
1275  if (idx) MovePS(idx,0);
1276  if (idy) MovePS(0,idy);
1277 
1278  if (nn > 0 ) {
1279  if (xw[0] == xw[n-1] && yw[0] == yw[n-1]) PrintFast(3," cl");
1280  PrintFast(2," s");
1281  } else {
1282  if (fais == 0) {PrintFast(5," cl s"); goto END;}
1283  if (fais == 3 || fais == 2) {
1284  if (fasi > 0 && fasi < 26) {
1285  PrintFast(3," FA");
1286  fRed = -1;
1287  fGreen = -1;
1288  fBlue = -1;
1289  }
1290  goto END;
1291  }
1292  PrintFast(2," f");
1293  }
1294 END:
1295  if (nn < 0) {
1296  SetLineStyle(linestylesav);
1297  SetLineWidth(linewidthsav);
1298  }
1299 }
1300 
1301 ////////////////////////////////////////////////////////////////////////////////
1302 /// Draw a PolyLine
1303 ///
1304 /// Draw a polyline through the points xw,yw.
1305 /// - If nn=1 moves only to point xw,yw.
1306 /// - If nn=0 the xw(1) and YW(1) are written in the PostScript file
1307 /// --- according to the current NT.
1308 /// - If nn>0 the line is clipped as a line.
1309 /// - If nn<0 the line is clipped as a fill area.
1310 
1312 {
1313  static Float_t dyhatch[24] = {.0075,.0075,.0075,.0075,.0075,.0075,.0075,.0075,
1314  .01 ,.01 ,.01 ,.01 ,.01 ,.01 ,.01 ,.01 ,
1315  .015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015 ,.015};
1316  static Float_t anglehatch[24] = {180, 90,135, 45,150, 30,120, 60,
1317  180, 90,135, 45,150, 30,120, 60,
1318  180, 90,135, 45,150, 30,120, 60};
1319  Int_t i, n, ixd0, iyd0, idx, idy, ixdi, iydi, ix, iy, fais, fasi;
1320  fais = fasi = n = 0;
1321  Int_t jxd0 = XtoPS(xw[0]);
1322  Int_t jyd0 = YtoPS(yw[0]);
1323  Style_t linestylesav = fLineStyle;
1324  Width_t linewidthsav = fLineWidth;
1325 
1326  if (nn > 0) {
1327  if (fLineWidth<=0) return;
1328  n = nn;
1332  }
1333  if (nn < 0) {
1334  n = -nn;
1335  SetLineStyle(1);
1336  SetLineWidth(1);
1338  fais = fFillStyle/1000;
1339  fasi = fFillStyle%1000;
1340  if (fais == 3 || fais == 2) {
1341  if (fasi > 100 && fasi <125) {
1342  DrawHatch(dyhatch[fasi-101],anglehatch[fasi-101], n, xw, yw);
1343  goto END;
1344  }
1345  if (fasi > 0 && fasi < 26) {
1347  }
1348  }
1349  }
1350 
1351  ixd0 = jxd0;
1352  iyd0 = jyd0;
1353  WriteInteger(ixd0);
1354  WriteInteger(iyd0);
1355  if( n <= 1) {
1356  if( n == 0) goto END;
1357  PrintFast(2," m");
1358  goto END;
1359  }
1360 
1361  PrintFast(2," m");
1362  idx = idy = 0;
1363  for (i=1;i<n;i++) {
1364  ixdi = XtoPS(xw[i]);
1365  iydi = YtoPS(yw[i]);
1366  ix = ixdi - ixd0;
1367  iy = iydi - iyd0;
1368  ixd0 = ixdi;
1369  iyd0 = iydi;
1370  if( ix && iy) {
1371  if( idx ) { MovePS(idx,0); idx = 0; }
1372  if( idy ) { MovePS(0,idy); idy = 0; }
1373  MovePS(ix,iy);
1374  } else if ( ix ) {
1375  if( idy ) { MovePS(0,idy); idy = 0;}
1376  if( !idx ) { idx = ix;}
1377  else if( TMath::Sign(ix,idx) == ix ) idx += ix;
1378  else { MovePS(idx,0); idx = ix;}
1379  } else if( iy ) {
1380  if( idx ) { MovePS(idx,0); idx = 0;}
1381  if( !idy) { idy = iy;}
1382  else if( TMath::Sign(iy,idy) == iy) idy += iy;
1383  else { MovePS(0,idy); idy = iy;}
1384  }
1385  }
1386  if (idx) MovePS(idx,0);
1387  if (idy) MovePS(0,idy);
1388 
1389  if (nn > 0 ) {
1390  if (xw[0] == xw[n-1] && yw[0] == yw[n-1]) PrintFast(3," cl");
1391  PrintFast(2," s");
1392  } else {
1393  if (fais == 0) {PrintFast(5," cl s"); goto END;}
1394  if (fais == 3 || fais == 2) {
1395  if (fasi > 0 && fasi < 26) {
1396  PrintFast(3," FA");
1397  fRed = -1;
1398  fGreen = -1;
1399  fBlue = -1;
1400  }
1401  goto END;
1402  }
1403  PrintFast(2," f");
1404  }
1405 END:
1406  if (nn < 0) {
1407  SetLineStyle(linestylesav);
1408  SetLineWidth(linewidthsav);
1409  }
1410 }
1411 
1412 ////////////////////////////////////////////////////////////////////////////////
1413 /// Draw Fill area with hatch styles
1414 
1416 {
1417  Warning("DrawHatch", "hatch fill style not yet implemented");
1418 }
1419 
1420 ////////////////////////////////////////////////////////////////////////////////
1421 /// Draw Fill area with hatch styles
1422 
1424 {
1425  Warning("DrawHatch", "hatch fill style not yet implemented");
1426 }
1427 
1428 ////////////////////////////////////////////////////////////////////////////////
1429 
1431 {
1432  std::ifstream font_file(filename, std::ios::binary);
1433 
1434  // We cannot read directly using iostream iterators due to
1435  // signedness
1436  font_file.seekg(0, std::ios::end);
1437 
1438  const size_t font_file_length = font_file.tellg();
1439 
1440  font_file.seekg(0, std::ios::beg);
1441 
1442  std::vector<unsigned char> font_data(font_file_length, '\0');
1443 
1444  font_file.read(reinterpret_cast<char *>(&font_data[0]),
1445  font_file_length);
1446 
1447  std::string font_name;
1448  std::string postscript_string =
1449  mathtext::font_embed_postscript_t::font_embed_type_1(
1450  font_name, font_data);
1451 
1452  if (!postscript_string.empty()) {
1453  PrintRaw(postscript_string.size(), postscript_string.data());
1454  PrintStr("@");
1455 
1456  return true;
1457  }
1458 
1459  return false;
1460 }
1461 
1462 ////////////////////////////////////////////////////////////////////////////////
1463 
1465 {
1466  std::ifstream font_file(filename, std::ios::binary);
1467 
1468  // We cannot read directly using iostream iterators due to
1469  // signedness
1470  font_file.seekg(0, std::ios::end);
1471 
1472  const size_t font_file_length = font_file.tellg();
1473 
1474  font_file.seekg(0, std::ios::beg);
1475 
1476  std::vector<unsigned char> font_data(font_file_length, '\0');
1477 
1478  font_file.read(reinterpret_cast<char *>(&font_data[0]), font_file_length);
1479 
1480  std::string font_name;
1481  std::string postscript_string =
1482  mathtext::font_embed_postscript_t::font_embed_type_2(font_name, font_data);
1483 
1484  if (!postscript_string.empty()) {
1485  PrintRaw(postscript_string.size(), postscript_string.data());
1486  PrintStr("@");
1487 
1488  return true;
1489  }
1490 
1491  return false;
1492 }
1493 
1494 ////////////////////////////////////////////////////////////////////////////////
1495 
1497 {
1498  std::ifstream font_file(filename, std::ios::binary);
1499 
1500  // We cannot read directly using iostream iterators due to signedness
1501 
1502  font_file.seekg(0, std::ios::end);
1503 
1504  const size_t font_file_length = font_file.tellg();
1505 
1506  font_file.seekg(0, std::ios::beg);
1507 
1508  std::vector<unsigned char> font_data(font_file_length, '\0');
1509 
1510  font_file.read(reinterpret_cast<char *>(&font_data[0]), font_file_length);
1511 
1512  std::string font_name;
1513  std::string postscript_string =
1514  mathtext::font_embed_postscript_t::font_embed_type_42(font_name, font_data);
1515 
1516  if (!postscript_string.empty()) {
1517  PrintRaw(postscript_string.size(), postscript_string.data());
1518  PrintStr("@");
1519 
1520  return true;
1521  }
1522  fprintf(stderr, "%s:%d:\n", __FILE__, __LINE__);
1523 
1524  return false;
1525 }
1526 
1527 ////////////////////////////////////////////////////////////////////////////////
1528 /// Embed font in PS file.
1529 
1531 {
1532  PrintStr("%%IncludeResource: ProcSet (FontSetInit)@");
1533 
1534  for (Int_t fontid = 1; fontid < 30; fontid++) {
1535  if (fontid != 15 && MustEmbed[fontid-1]) {
1536 
1537  char *ttfont = NULL;
1538 
1539  FcPattern *pat, *match;
1540  FcCharSet *set = NULL;
1541  FcResult result;
1542 
1543  pat = FcPatternCreate ();
1544 
1545  switch (fontid) {
1546  case 1:
1547  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freeserif");
1548  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1549  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
1550  break;
1551  case 2:
1552  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freeserif");
1553  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1554  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1555  break;
1556  case 3:
1557  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freeserif");
1558  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1559  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
1560  break;
1561  case 4:
1562  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freesans");
1563  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1564  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1565  break;
1566  case 5:
1567  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freesans");
1568  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1569  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
1570  break;
1571  case 6:
1572  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freesans");
1573  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1574  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1575  break;
1576  case 7:
1577  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freesans");
1578  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1579  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
1580  break;
1581  case 8:
1582  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freemono");
1583  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1584  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1585  break;
1586  case 9:
1587  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freemono");
1588  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1589  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
1590  break;
1591  case 10:
1592  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freemono");
1593  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1594  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1595  break;
1596  case 11:
1597  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freemono");
1598  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1599  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
1600  break;
1601  case 12:
1602  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"symbol");
1603  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1604  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1605  break;
1606  case 13:
1607  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"freeserif");
1608  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1609  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1610  break;
1611  case 14:
1612  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"dingbats");
1613  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1614  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1615  break;
1616  case 16:
1617  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixgeneral");
1618  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1619  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1620  break;
1621  case 17:
1622  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixgeneral");
1623  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1624  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
1625  break;
1626  case 18:
1627  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixgeneral");
1628  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1629  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1630  break;
1631  case 19:
1632  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixgeneral");
1633  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1634  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ITALIC);
1635  break;
1636  case 20:
1637  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize1");
1638  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1639  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1640  break;
1641  case 21:
1642  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize1");
1643  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1644  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1645  break;
1646  case 22:
1647  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize2");
1648  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1649  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1650  break;
1651  case 23:
1652  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize2");
1653  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1654  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1655  break;
1656  case 24:
1657  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize3");
1658  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1659  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1660  break;
1661  case 25:
1662  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize3");
1663  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1664  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1665  break;
1666  case 26:
1667  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize4");
1668  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1669  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1670  break;
1671  case 27:
1672  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize4");
1673  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_BOLD);
1674  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1675  break;
1676  case 28:
1677  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"stixsize5");
1678  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1679  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1680  break;
1681  case 29:
1682  FcPatternAddString (pat, FC_FAMILY, (const FcChar8*)"droidsansfallback");
1683  FcPatternAddInteger (pat, FC_WEIGHT, FC_WEIGHT_REGULAR);
1684  FcPatternAddInteger (pat, FC_SLANT, FC_SLANT_ROMAN);
1685  set = FcCharSetCreate ();
1686  FcCharSetAddChar (set, 0x0410); // Cyrillic
1687  FcCharSetAddChar (set, 0x4e00); // CJK
1688  FcPatternAddCharSet (pat, FC_CHARSET, set);
1689  break;
1690  }
1691 
1692  FcConfigSubstitute (NULL, pat, FcMatchPattern);
1693  FcDefaultSubstitute (pat);
1694  match = FcFontMatch (NULL, pat, &result);
1695  char *ttfnt;
1696  FcPatternGetString (match, FC_FILE, 0, (FcChar8**)&ttfnt);
1697  ttfont = StrDup(ttfnt);
1698  FcPatternDestroy (match);
1699  FcPatternDestroy (pat);
1700  if (set) FcCharSetDestroy (set);
1701 
1702  if (!ttfont) {
1703  Error("TPostScript::FontEmbed", "font %d not found in path",
1704  fontid);
1705  } else {
1706  if (FontEmbedType2(ttfont)) {
1707  // nothing
1708  } else if(FontEmbedType1(ttfont)) {
1709  // nothing
1710  } else if(FontEmbedType42(ttfont)) {
1711  // nothing
1712  } else {
1713  Error("TPostScript::FontEmbed", "failed to embed font %d)",
1714  fontid);
1715  }
1716  delete [] ttfont;
1717  }
1718  }
1719  }
1720  PrintStr("%%IncludeResource: font Times-Roman@");
1721  PrintStr("%%IncludeResource: font Times-Italic@");
1722  PrintStr("%%IncludeResource: font Times-Bold@");
1723  PrintStr("%%IncludeResource: font Times-BoldItalic@");
1724  PrintStr("%%IncludeResource: font Helvetica@");
1725  PrintStr("%%IncludeResource: font Helvetica-Oblique@");
1726  PrintStr("%%IncludeResource: font Helvetica-Bold@");
1727  PrintStr("%%IncludeResource: font Helvetica-BoldOblique@");
1728  PrintStr("%%IncludeResource: font Courier@");
1729  PrintStr("%%IncludeResource: font Courier-Oblique@");
1730  PrintStr("%%IncludeResource: font Courier-Bold@");
1731  PrintStr("%%IncludeResource: font Courier-BoldOblique@");
1732  PrintStr("%%IncludeResource: font Symbol@");
1733  PrintStr("%%IncludeResource: font ZapfDingbats@");
1734 
1735  fFontEmbed = kTRUE;
1736 }
1737 
1738 ////////////////////////////////////////////////////////////////////////////////
1739 /// Font Re-encoding
1740 
1742 {
1743  PrintStr("/reEncode ");
1744  PrintStr("{exch findfont");
1745  PrintStr(" dup length dict begin");
1746  PrintStr(" {1 index /FID eq ");
1747  PrintStr(" {pop pop}");
1748  PrintStr(" {def} ifelse");
1749  PrintStr(" } forall");
1750  PrintStr(" /Encoding exch def");
1751  PrintStr(" currentdict end");
1752  PrintStr(" dup /FontName get exch");
1753  PrintStr(" definefont pop");
1754  PrintStr(" } def");
1755  PrintStr(" [/Times-Bold /Times-Italic /Times-BoldItalic /Helvetica");
1756  PrintStr(" /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique");
1757  PrintStr(" /Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique");
1758  PrintStr(" /Times-Roman /AvantGarde-Book /AvantGarde-BookOblique");
1759  PrintStr(" /AvantGarde-Demi /AvantGarde-DemiOblique /Bookman-Demi");
1760  PrintStr(" /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic");
1761  PrintStr(" /Helvetica-Narrow /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique");
1762  PrintStr(" /Helvetica-Narrow-Oblique /NewCenturySchlbk-Roman /NewCenturySchlbk-Bold");
1763  PrintStr(" /NewCenturySchlbk-BoldItalic /NewCenturySchlbk-Italic");
1764  PrintStr(" /Palatino-Bold /Palatino-BoldItalic /Palatino-Italic /Palatino-Roman");
1765  PrintStr(" ] {ISOLatin1Encoding reEncode } forall");
1766 }
1767 
1768 ////////////////////////////////////////////////////////////////////////////////
1769 /// PostScript Initialisation
1770 ///
1771 /// This method initialize the following PostScript procedures:
1772 ///
1773 /// | Macro Name | Input parameters | Explanation |
1774 /// |------------|------------------|-----------------------------------|
1775 /// | l | x y | Draw a line to the x y position |
1776 /// | m | x y | Move to the position x y |
1777 /// | box | dx dy x y | Define a box |
1778 /// | bl | dx dy x y | Draw a line box |
1779 /// | bf | dx dy x y | Draw a filled box |
1780 /// | t | x y | Translate |
1781 /// | r | angle | Rotate |
1782 /// | rl | i j | Roll the stack |
1783 /// | d | x y | Draw a relative line to x y |
1784 /// | X | x | Draw a relative line to x (y=0) |
1785 /// | Y | y | Draw a relative line to y (x=0) |
1786 /// | rm | x y | Move relatively to x y |
1787 /// | gr | | Restore the graphic context |
1788 /// | lw | lwidth | Set line width to lwidth |
1789 /// | sd | [] 0 | Set dash line define by [] |
1790 /// | s | | Stroke mode |
1791 /// | c | r g b | Set rgb color to r g b |
1792 /// | cl | | Close path |
1793 /// | f | | Fill the last describe path |
1794 /// | mXX | x y | Draw the marker type XX at (x,y) |
1795 /// | Zone | ix iy | Define the current zone |
1796 /// | black | | The color is black |
1797 /// | C | dx dy x y | Clipping on |
1798 /// | NC | | Clipping off |
1799 /// | R | | repeat |
1800 /// | ita | | Used to make the symbols italic |
1801 /// | K | | kshow |
1802 
1804 {
1805  Double_t rpxmin, rpymin, width, heigth;
1806  rpxmin = rpymin = width = heigth = 0;
1807  Int_t format;
1808  fNpages=1;
1809  for (Int_t i=0;i<32;i++) fPatterns[i]=0;
1810 
1811  // Mode is last digit of PostScript Workstation type
1812  // mode=1,2 for portrait/landscape black and white
1813  // mode=3 for Encapsulated PostScript File
1814  // mode=4 for portrait colour
1815  // mode=5 for lanscape colour
1816  Int_t atype = abs(fType);
1817  fMode = atype%10;
1818  if( fMode <= 0 || fMode > 5) {
1819  Error("Initialize", "invalid file type %d", fMode);
1820  return;
1821  }
1822 
1823  // fNXzone (fNYzone) is the total number of windows in x (y)
1824  fNXzone = (atype%1000)/100;
1825  fNYzone = (atype%100)/10;
1826  if( fNXzone <= 0 ) fNXzone = 1;
1827  if( fNYzone <= 0 ) fNYzone = 1;
1828  fIXzone = 1;
1829  fIYzone = 1;
1830 
1831  // format = 0-99 is the European page format (A4,A3 ...)
1832  // format = 100 is the US format 8.5x11.0 inch
1833  // format = 200 is the US format 8.5x14.0 inch
1834  // format = 300 is the US format 11.0x17.0 inch
1835  format = atype/1000;
1836  if( format == 0 ) format = 4;
1837  if( format == 99 ) format = 0;
1838 
1839  PrintStr("%%Title: ");
1840  const char *pstitle = gStyle->GetTitlePS();
1841  if (gPad && !pstitle[0]) pstitle = gPad->GetMother()->GetTitle();
1842  if (strlen(GetName())<=80) PrintStr(GetName());
1843  if(!pstitle[0] && fMode != 3) {;
1844  PrintFast(2," (");
1845  if ( format <= 99 ) {;
1846  PrintFast(2," A");
1847  WriteInteger(format);
1848  PrintFast(1,")");
1849  }
1850  else {
1851  if ( format == 100 ) PrintFast(8," Letter)");
1852  if ( format == 200 ) PrintFast(7," Legal)");
1853  if ( format == 300 ) PrintFast(8," Ledger)");
1854  }
1855  PrintStr("@");
1856  PrintStr("%%Pages: (atend)@");
1857  }
1858  else {
1859  if (!strchr(pstitle,'\n')) {
1860  PrintFast(2,": ");
1861  PrintStr(pstitle);
1862  }
1863  PrintStr("@");
1864  }
1865 
1866  PrintFast(24,"%%Creator: ROOT Version ");
1867  PrintStr(gROOT->GetVersion());
1868  PrintStr("@");
1869  PrintFast(16,"%%CreationDate: ");
1870  TDatime t;
1871  PrintStr(t.AsString());
1872  PrintStr("@");
1873 
1874  if ( fMode == 1 || fMode == 4) PrintStr("%%Orientation: Portrait@");
1875  if ( fMode == 2 || fMode == 5) PrintStr("%%Orientation: Landscape@");
1876 
1877  PrintStr("%%EndComments@");
1878  PrintStr("%%BeginProlog@");
1879 
1880  if( fMode == 3)PrintStr("80 dict begin@");
1881 
1882  // Initialisation of PostScript procedures
1883  PrintStr("/s {stroke} def /l {lineto} def /m {moveto} def /t {translate} def@");
1884  PrintStr("/r {rotate} def /rl {roll} def /R {repeat} def@");
1885  PrintStr("/d {rlineto} def /rm {rmoveto} def /gr {grestore} def /f {eofill} def@");
1886  if (gStyle->GetColorModelPS()) {
1887  PrintStr("/c {setcmykcolor} def /black {0 0 0 1 setcmykcolor} def /sd {setdash} def@");
1888  } else {
1889  PrintStr("/c {setrgbcolor} def /black {0 setgray} def /sd {setdash} def@");
1890  }
1891  PrintStr("/cl {closepath} def /sf {scalefont setfont} def /lw {setlinewidth} def@");
1892  PrintStr("/box {m dup 0 exch d exch 0 d 0 exch neg d cl} def@");
1893  PrintStr("/NC{systemdict begin initclip end}def/C{NC box clip newpath}def@");
1894  PrintStr("/bl {box s} def /bf {gsave box gsave f grestore 1 lw [] 0 sd s grestore} def /Y { 0 exch d} def /X { 0 d} def @");
1895  PrintStr("/K {{pop pop 0 moveto} exch kshow} bind def@");
1896  PrintStr("/ita {/ang 15 def gsave [1 0 ang dup sin exch cos div 1 0 0] concat} def @");
1897 
1898  DefineMarkers();
1899 
1900  FontEncode();
1901 
1902  // mode=1 for portrait black/white
1903  if (fMode == 1) {
1904  rpxmin = 0.7;
1905  rpymin = TMath::Sqrt(2.)*rpxmin;
1906  switch (format) {
1907  case 100 :
1908  width = (8.5*2.54)-2.*rpxmin;
1909  heigth = (11.*2.54)-2.*rpymin;
1910  break;
1911  case 200 :
1912  width = (8.5*2.54)-2.*rpxmin;
1913  heigth = (14.*2.54)-2.*rpymin;
1914  break;
1915  case 300 :
1916  width = (11.*2.54)-2.*rpxmin;
1917  heigth = (17.*2.54)-2.*rpymin;
1918  break;
1919  default :
1920  width = 21.0-2.*rpxmin;
1921  heigth = 29.7-2.*rpymin;
1922  };
1923  }
1924 
1925  // mode=2 for landscape black/white
1926  if (fMode == 2) {
1927  rpymin = 0.7;
1928  rpxmin = TMath::Sqrt(2.)*rpymin;
1929  switch (format) {
1930  case 100 :
1931  width = (11.*2.54)-2.*rpxmin;
1932  heigth = (8.5*2.54)-2.*rpymin;
1933  case 200 :
1934  width = (14.*2.54)-2.*rpxmin;
1935  heigth = (8.5*2.54)-2.*rpymin;
1936  case 300 :
1937  width = (17.*2.54)-2.*rpxmin;
1938  heigth = (11.*2.54)-2.*rpymin;
1939  default :
1940  width = 29.7-2.*rpxmin;
1941  heigth = 21-2.*rpymin;
1942  };
1943  }
1944 
1945  // mode=3 encapsulated PostScript
1946  if (fMode == 3) {
1947  width = 20;
1948  heigth = 20;
1949  format = 4;
1950  fNXzone = 1;
1951  fNYzone = 1;
1952  }
1953 
1954  // mode=4 for portrait colour
1955  if (fMode == 4) {
1956  rpxmin = 0.7;
1957  rpymin = 3.4;
1958  switch (format) {
1959  case 100 :
1960  width = (8.5*2.54)-2.*rpxmin;
1961  heigth = (11.*2.54)-2.*rpymin;
1962  case 200 :
1963  width = (8.5*2.54)-2.*rpxmin;
1964  heigth = (14.*2.54)-2.*rpymin;
1965  case 300 :
1966  width = (11.*2.54)-2.*rpxmin;
1967  heigth = (17.*2.54)-2.*rpymin;
1968  default :
1969  width = (21.0-2*rpxmin);
1970  heigth = (29.7-2.*rpymin);
1971  };
1972  }
1973 
1974  // mode=5 for lanscape colour
1975  if (fMode == 5) {
1976  rpxmin = 3.4;
1977  rpymin = 0.7;
1978  switch (format) {
1979  case 100 :
1980  width = (11.*2.54)-2.*rpxmin;
1981  heigth = (8.5*2.54)-2.*rpymin;
1982  case 200 :
1983  width = (14.*2.54)-2.*rpxmin;
1984  heigth = (8.5*2.54)-2.*rpymin;
1985  case 300 :
1986  width = (17.*2.54)-2.*rpxmin;
1987  heigth = (11.*2.54)-2.*rpymin;
1988  default :
1989  width = (29.7-2*rpxmin);
1990  heigth = (21-2.*rpymin);
1991  };
1992  }
1993 
1994  Double_t value = 0;
1995  if (format < 100) value = 21*TMath::Power(TMath::Sqrt(2.), 4-format);
1996  else if (format == 100) value = 8.5*2.54;
1997  else if (format == 200) value = 8.5*2.54;
1998  else if (format == 300) value = 11.*2.54;
1999  if (format >= 100) format = 4;
2000 
2001  // Compute size (in points) of the window for each picture = f(fNXzone,fNYzone)
2002  Double_t sizex = width/Double_t(fNXzone)*TMath::Power(TMath::Sqrt(2.), 4-format);
2003  Double_t sizey = heigth/Double_t(fNYzone)*TMath::Power(TMath::Sqrt(2.), 4-format);
2004  Int_t npx = 4*CMtoPS(sizex);
2005  Int_t npy = 4*CMtoPS(sizey);
2006  if (sizex > sizey) fMaxsize = CMtoPS(sizex);
2007  else fMaxsize = CMtoPS(sizey);
2008 
2009  // Procedure Zone
2010  if (fMode != 3) {
2011  PrintFast(33,"/Zone {/iy exch def /ix exch def ");
2012  PrintFast(10," ix 1 sub ");
2013  WriteInteger(npx);
2014  PrintFast(5," mul ");
2016  PrintFast(8," iy sub ");
2017  WriteInteger(npy);
2018  PrintStr(" mul t} def@");
2019  } else {
2020  PrintStr("@");
2021  }
2022 
2023  PrintStr("%%EndProlog@");
2024  PrintStr("%%BeginSetup@");
2025  PrintStr("%%EndSetup@");
2026  PrintFast(8,"newpath ");
2027  SaveRestore(1);
2028  if (fMode == 1 || fMode == 4) {
2029  WriteInteger(CMtoPS(rpxmin));
2030  WriteInteger(CMtoPS(rpymin));
2031  PrintFast(2," t");
2032  }
2033  if (fMode == 2 || fMode == 5) {
2034  PrintFast(7," 90 r 0");
2035  WriteInteger(CMtoPS(-value));
2036  PrintFast(3," t ");
2037  WriteInteger(CMtoPS(rpxmin));
2038  WriteInteger(CMtoPS(rpymin));
2039  PrintFast(2," t");
2040  }
2041 
2042  PrintFast(15," .25 .25 scale ");
2043  if (fMode != 3) {
2044  SaveRestore(1);
2045  PrintStr("@");
2046  PrintStr("%%Page: 1 1@");
2047  SaveRestore(1);
2048  }
2049 
2050  //Check is user has defined a special header in the current style
2051  Int_t nh = strlen(gStyle->GetHeaderPS());
2052  if (nh) {
2053  PrintFast(nh,gStyle->GetHeaderPS());
2054  if (fMode != 3) SaveRestore(1);
2055  }
2056 }
2057 
2058 ////////////////////////////////////////////////////////////////////////////////
2059 /// Move to a new position
2060 
2062 {
2063  if (ix != 0 && iy != 0) {
2064  WriteInteger(ix);
2065  WriteInteger(iy);
2066  PrintFast(2," d");
2067  } else if (ix != 0) {
2068  WriteInteger(ix);
2069  PrintFast(2," X");
2070  } else if (iy != 0) {
2071  WriteInteger(iy);
2072  PrintFast(2," Y");
2073  }
2074 }
2075 
2076 ////////////////////////////////////////////////////////////////////////////////
2077 /// Move to a new PostScript page
2078 
2080 {
2081  // Compute pad conversion coefficients
2082  if (gPad) {
2083  // if (!gPad->GetPadPaint()) gPad->Update();
2084  Double_t ww = gPad->GetWw();
2085  Double_t wh = gPad->GetWh();
2086  fYsize = fXsize*wh/ww;
2087  } else fYsize = 27;
2088 
2089  if(fType == 113 && !fBoundingBox) {
2090  Bool_t psave = fPrinted;
2091  PrintStr("@%%BoundingBox: ");
2092  Double_t xlow=0, ylow=0, xup=1, yup=1;
2093  if (gPad) {
2094  xlow = gPad->GetAbsXlowNDC();
2095  xup = xlow + gPad->GetAbsWNDC();
2096  ylow = gPad->GetAbsYlowNDC();
2097  yup = ylow + gPad->GetAbsHNDC();
2098  }
2099  WriteInteger(CMtoPS(fXsize*xlow));
2100  WriteInteger(CMtoPS(fYsize*ylow));
2101  WriteInteger(CMtoPS(fXsize*xup));
2102  WriteInteger(CMtoPS(fYsize*yup));
2103  PrintStr("@");
2104  Initialize();
2105  fBoundingBox = kTRUE;
2106  fPrinted = psave;
2107  }
2108  if (fPrinted) {
2109  if (fSave) SaveRestore(-1);
2110  fClear = kTRUE;
2111  fPrinted = kFALSE;
2112  }
2113  Zone();
2114 }
2115 
2116 ////////////////////////////////////////////////////////////////////////////////
2117 /// Set the range for the paper in centimeters
2118 
2120 {
2121  Float_t xps=0, yps=0, xncm=0, yncm=0, dxwn=0, dywn=0, xwkwn=0, ywkwn=0, xymax=0;
2122 
2123  fXsize = xsize;
2124  fYsize = ysize;
2125  if( fType != 113) { xps = fXsize; yps = fYsize; }
2126  else { xps = xsize; yps = ysize; }
2127 
2128  if( xsize <= xps && ysize < yps) {
2129  if ( xps > yps ) xymax = xps;
2130  else xymax = yps;
2131  xncm = xsize/xymax;
2132  yncm = ysize/xymax;
2133  dxwn = ((xps/xymax)-xncm)/2;
2134  dywn = ((yps/xymax)-yncm)/2;
2135  } else {
2136  if (xps/yps < 1) xwkwn = xps/yps;
2137  else xwkwn = 1;
2138  if (yps/xps < 1) ywkwn = yps/xps;
2139  else ywkwn = 1;
2140 
2141  if (xsize < ysize) {
2142  xncm = ywkwn*xsize/ysize;
2143  yncm = ywkwn;
2144  dxwn = (xwkwn-xncm)/2;
2145  dywn = 0;
2146  if( dxwn < 0) {
2147  xncm = xwkwn;
2148  dxwn = 0;
2149  yncm = xwkwn*ysize/xsize;
2150  dywn = (ywkwn-yncm)/2;
2151  }
2152  } else {
2153  xncm = xwkwn;
2154  yncm = xwkwn*ysize/xsize;
2155  dxwn = 0;
2156  dywn = (ywkwn-yncm)/2;
2157  if( dywn < 0) {
2158  yncm = ywkwn;
2159  dywn = 0;
2160  xncm = ywkwn*xsize/ysize;
2161  dxwn = (xwkwn-xncm)/2;
2162  }
2163  }
2164  }
2165  fXVP1 = dxwn;
2166  fXVP2 = xncm+dxwn;
2167  fYVP1 = dywn;
2168  fYVP2 = yncm+dywn;
2169  fRange = kTRUE;
2170 }
2171 
2172 ////////////////////////////////////////////////////////////////////////////////
2173 /// Compute number of gsaves for restore
2174 /// This allows to write the correct number of grestore at the
2175 /// end of the PS file.
2176 
2178 {
2179  if (flag == 1) { PrintFast(7," gsave "); fSave++; }
2180  else { PrintFast(4," gr "); fSave--; }
2181 }
2182 
2183 ////////////////////////////////////////////////////////////////////////////////
2184 /// Set color index for fill areas
2185 
2187 {
2188  fFillColor = cindex;
2189  if (gStyle->GetFillColor() <= 0) cindex = 0;
2190  SetColor(Int_t(cindex));
2191 }
2192 
2193 ////////////////////////////////////////////////////////////////////////////////
2194 /// Patterns definition
2195 ///
2196 /// Define the pattern ipat in the current PS file. ipat can vary from
2197 /// 1 to 25. Together with the pattern, the color (color) in which the
2198 /// pattern has to be drawn is also required. A pattern is defined in the
2199 /// current PS file only the first time it is used. Some level 2
2200 /// Postscript functions are used, so on level 1 printers, patterns will
2201 /// not work. This is not a big problem because patterns are
2202 /// defined only if they are used, so if they are not used a PS level 1
2203 /// file will not be polluted by level 2 features, and in any case the old
2204 /// patterns used a lot of memory which made them almost unusable on old
2205 /// level 1 printers. Finally we should say that level 1 devices are
2206 /// becoming very rare. The official PostScript is now level 3 !
2207 
2209 {
2210  char cdef[28];
2211  char cpat[5];
2212  snprintf(cpat,5," P%2.2d", ipat);
2213 
2214  // fPatterns is used as an array of chars. If fPatterns[ipat] != 0 the
2215  // pattern number ipat as already be defined is this file and it
2216  // is not necessary to redefine it. fPatterns is set to zero in Initialize.
2217  // The pattern number 26 allows to know if the macro "cs" has already
2218  // been defined in the current file (see label 200).
2219  if (fPatterns[ipat] == 0) {
2220 
2221  // Define the Patterns. Line width must be 1
2222  // Setting fLineWidth to -1 will force the line width definition next time
2223  // TPostScript::SetLineWidth will be called.
2224  fLineWidth = -1;
2225  PrintFast(5," 1 lw");
2226  PrintStr(" << /PatternType 1 /PaintType 2 /TilingType 1");
2227  switch (ipat) {
2228  case 1 :
2229  PrintStr(" /BBox [ 0 0 98 4 ]");
2230  PrintStr(" /XStep 98 /YStep 4");
2231  PrintStr(" /PaintProc { begin gsave");
2232  PrintStr(" [1] 0 sd 2 4 m 99 4 l s 1 3 m 98 3 l s");
2233  PrintStr(" 2 2 m 99 2 l s 1 1 m 98 1 l s");
2234  PrintStr(" gr end } >> [ 4.0 0 0 4.0 0 0 ]");
2235  break;
2236  case 2 :
2237  PrintStr(" /BBox [ 0 0 96 4 ]");
2238  PrintStr(" /XStep 96 /YStep 4");
2239  PrintStr(" /PaintProc { begin gsave");
2240  PrintStr(" [1 3] 0 sd 2 4 m 98 4 l s 0 3 m 96 3 l s");
2241  PrintStr(" 2 2 m 98 2 l s 0 1 m 96 1 l s");
2242  PrintStr(" gr end } >> [ 3.0 0 0 3.0 0 0 ]");
2243  break;
2244  case 3 :
2245  PrintStr(" /BBox [ 0 0 96 16 ]");
2246  PrintStr(" /XStep 96 /YStep 16");
2247  PrintStr(" /PaintProc { begin gsave");
2248  PrintStr(" [1 3] 0 sd 2 13 m 98 13 l s 0 9 m 96 9 l s");
2249  PrintStr(" 2 5 m 98 5 l s 0 1 m 96 1 l s");
2250  PrintStr(" gr end } >> [ 2.0 0 0 2.0 0 0 ]");
2251  break;
2252  case 4 :
2253  PrintStr(" /BBox [ 0 0 100 100 ]");
2254  PrintStr(" /XStep 100 /YStep 100");
2255  PrintStr(" /PaintProc { begin gsave");
2256  PrintStr(" 0 0 m 100 100 l s");
2257  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2258  break;
2259  case 5 :
2260  PrintStr(" /BBox [ 0 0 100 100 ]");
2261  PrintStr(" /XStep 100 /YStep 100");
2262  PrintStr(" /PaintProc { begin gsave");
2263  PrintStr(" 0 100 m 100 0 l s");
2264  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2265  break;
2266  case 6 :
2267  PrintStr(" /BBox [ 0 0 100 100 ]");
2268  PrintStr(" /XStep 100 /YStep 100");
2269  PrintStr(" /PaintProc { begin gsave");
2270  PrintStr(" 50 0 m 50 100 l s");
2271  PrintStr(" gr end } >> [ 0.12 0 0 0.12 0 0 ]");
2272  break;
2273  case 7 :
2274  PrintStr(" /BBox [ 0 0 100 100 ]");
2275  PrintStr(" /XStep 100 /YStep 100");
2276  PrintStr(" /PaintProc { begin gsave");
2277  PrintStr(" 0 50 m 100 50 l s");
2278  PrintStr(" gr end } >> [ 0.12 0 0 0.12 0 0 ]");
2279  break;
2280  case 8 :
2281  PrintStr(" /BBox [ 0 0 101 101 ]");
2282  PrintStr(" /XStep 100 /YStep 100");
2283  PrintStr(" /PaintProc { begin gsave");
2284  PrintStr(" 0 0 m 0 30 l 30 0 l f 0 70 m 0 100 l 30 100 l f");
2285  PrintStr(" 70 100 m 100 100 l 100 70 l f 70 0 m 100 0 l");
2286  PrintStr(" 100 30 l f 50 20 m 20 50 l 50 80 l 80 50 l f");
2287  PrintStr(" 50 80 m 30 100 l s 20 50 m 0 30 l s 50 20 m");
2288  PrintStr(" 70 0 l s 80 50 m 100 70 l s");
2289  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2290  break;
2291  case 9 :
2292  PrintStr(" /BBox [ 0 0 100 100 ]");
2293  PrintStr(" /XStep 100 /YStep 100");
2294  PrintStr(" /PaintProc { begin gsave");
2295  PrintStr(" 0 50 m 50 50 50 180 360 arc");
2296  PrintStr(" 0 50 m 0 100 50 270 360 arc");
2297  PrintStr(" 50 100 m 100 100 50 180 270 arc s");
2298  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2299  break;
2300  case 10 :
2301  PrintStr(" /BBox [ 0 0 100 100 ]");
2302  PrintStr(" /XStep 100 /YStep 100");
2303  PrintStr(" /PaintProc { begin gsave");
2304  PrintStr(" 0 50 m 100 50 l 1 1 m 100 1 l");
2305  PrintStr(" 0 0 m 0 50 l 100 0 m 100 50 l");
2306  PrintStr(" 50 50 m 50 100 l s");
2307  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2308  break;
2309  case 11 :
2310  PrintStr(" /BBox [ 0 0 100 100 ]");
2311  PrintStr(" /XStep 100 /YStep 100");
2312  PrintStr(" /PaintProc { begin gsave");
2313  PrintStr(" 0 0 m 0 20 l 50 0 m 50 20 l");
2314  PrintStr(" 100 0 m 100 20 l 0 80 m 0 100 l");
2315  PrintStr(" 50 80 m 50 100 l 100 80 m 100 100 l");
2316  PrintStr(" 25 30 m 25 70 l 75 30 m 75 70 l");
2317  PrintStr(" 0 100 m 20 85 l 50 100 m 30 85 l");
2318  PrintStr(" 50 100 m 70 85 l 100 100 m 80 85 l");
2319  PrintStr(" 0 0 m 20 15 l 50 0 m 30 15 l");
2320  PrintStr(" 50 0 m 70 15 l 100 0 m 80 15 l");
2321  PrintStr(" 5 35 m 45 65 l 5 65 m 45 35 l");
2322  PrintStr(" 55 35 m 95 65 l 55 65 m 95 35 l s");
2323  PrintStr(" gr end } >> [ 0.5 0 0 0.5 0 0 ]");
2324  break;
2325  case 12 :
2326  PrintStr(" /BBox [ 0 0 100 100 ]");
2327  PrintStr(" /XStep 100 /YStep 100");
2328  PrintStr(" /PaintProc { begin gsave");
2329  PrintStr(" 0 80 m 0 100 20 270 360 arc");
2330  PrintStr(" 30 100 m 50 100 20 180 360 arc");
2331  PrintStr(" 80 100 m 100 100 20 180 270 arc");
2332  PrintStr(" 20 0 m 0 0 20 0 90 arc");
2333  PrintStr(" 70 0 m 50 0 20 0 180 arc");
2334  PrintStr(" 100 20 m 100 0 20 90 180 arc");
2335  PrintStr(" 45 50 m 25 50 20 0 360 arc");
2336  PrintStr(" 95 50 m 75 50 20 0 360 arc s");
2337  PrintStr(" gr end } >> [ 0.5 0 0 0.5 0 0 ]");
2338  break;
2339  case 13 :
2340  PrintStr(" /BBox [ 0 0 100 100 ]");
2341  PrintStr(" /XStep 100 /YStep 100");
2342  PrintStr(" /PaintProc { begin gsave");
2343  PrintStr(" 0 0 m 100 100 l 0 100 m 100 0 l s");
2344  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2345  break;
2346  case 14 :
2347  PrintStr(" /BBox [ 0 0 100 100 ]");
2348  PrintStr(" /XStep 80 /YStep 80");
2349  PrintStr(" /PaintProc { begin gsave");
2350  PrintStr(" 0 20 m 100 20 l 20 0 m 20 100 l");
2351  PrintStr(" 0 80 m 100 80 l 80 0 m 80 100 l");
2352  PrintStr(" 20 40 m 60 40 l 60 20 m 60 60 l");
2353  PrintStr(" 40 40 m 40 80 l 40 60 m 80 60 l s");
2354  PrintStr(" gr end } >> [ 0.60 0 0 0.60 0 0 ]");
2355  break;
2356  case 15 :
2357  PrintStr(" /BBox [ 0 0 60 60 ]");
2358  PrintStr(" /XStep 60 /YStep 60");
2359  PrintStr(" /PaintProc { begin gsave");
2360  PrintStr(" 0 55 m 0 60 5 270 360 arc");
2361  PrintStr(" 25 60 m 30 60 5 180 360 arc");
2362  PrintStr(" 55 60 m 60 60 5 180 270 arc");
2363  PrintStr(" 20 30 m 15 30 5 0 360 arc");
2364  PrintStr(" 50 30 m 45 30 5 0 360");
2365  PrintStr(" arc 5 0 m 0 0 5 0 90 arc");
2366  PrintStr(" 35 0 m 30 0 5 0 180 arc");
2367  PrintStr(" 60 5 m 60 0 5 90 180 arc s");
2368  PrintStr(" gr end } >> [ 0.41 0 0 0.41 0 0 ]");
2369  break;
2370  case 16 :
2371  PrintStr(" /BBox [ 0 0 100 100 ]");
2372  PrintStr(" /XStep 100 /YStep 100");
2373  PrintStr(" /PaintProc { begin gsave");
2374  PrintStr(" 50 50 m 25 50 25 0 180 arc s");
2375  PrintStr(" 50 50 m 75 50 25 180 360 arc s");
2376  PrintStr(" gr end } >> [ 0.4 0 0 0.2 0 0 ]");
2377  break;
2378  case 17 :
2379  PrintStr(" /BBox [ 0 0 100 100 ]");
2380  PrintStr(" /XStep 100 /YStep 100");
2381  PrintStr(" /PaintProc { begin gsave");
2382  PrintStr(" [24] 0 setdash 0 0 m 100 100 l s");
2383  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2384  break;
2385  case 18 :
2386  PrintStr(" /BBox [ 0 0 100 100 ]");
2387  PrintStr(" /XStep 100 /YStep 100");
2388  PrintStr(" /PaintProc { begin gsave");
2389  PrintStr(" [24] 0 setdash 0 100 m 100 0 l s");
2390  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2391  break;
2392  case 19 :
2393  PrintStr(" /BBox [ 0 0 100 100 ]");
2394  PrintStr(" /XStep 100 /YStep 100");
2395  PrintStr(" /PaintProc { begin gsave");
2396  PrintStr(" 90 50 m 50 50 40 0 360 arc");
2397  PrintStr(" 0 50 m 0 100 50 270 360 arc");
2398  PrintStr(" 50 0 m 0 0 50 0 90 arc");
2399  PrintStr(" 100 50 m 100 0 50 90 180 arc");
2400  PrintStr(" 50 100 m 100 100 50 180 270 arc s");
2401  PrintStr(" gr end } >> [ 0.47 0 0 0.47 0 0 ]");
2402  break;
2403  case 20 :
2404  PrintStr(" /BBox [ 0 0 100 100 ]");
2405  PrintStr(" /XStep 100 /YStep 100");
2406  PrintStr(" /PaintProc { begin gsave");
2407  PrintStr(" 50 50 m 50 75 25 270 450 arc s");
2408  PrintStr(" 50 50 m 50 25 25 90 270 arc s");
2409  PrintStr(" gr end } >> [ 0.2 0 0 0.4 0 0 ]");
2410  break;
2411  case 21 :
2412  PrintStr(" /BBox [ 0 0 101 101 ]");
2413  PrintStr(" /XStep 100 /YStep 100");
2414  PrintStr(" /PaintProc { begin gsave");
2415  PrintStr(" 1 1 m 25 1 l 25 25 l 50 25 l 50 50 l");
2416  PrintStr(" 75 50 l 75 75 l 100 75 l 100 100 l");
2417  PrintStr(" 50 1 m 75 1 l 75 25 l 100 25 l 100 50 l");
2418  PrintStr(" 0 50 m 25 50 l 25 75 l 50 75 l 50 100 l s");
2419  PrintStr(" gr end } >> [ 0.5 0 0 0.5 0 0 ]");
2420  break;
2421  case 22 :
2422  PrintStr(" /BBox [ 0 0 101 101 ]");
2423  PrintStr(" /XStep 100 /YStep 100");
2424  PrintStr(" /PaintProc { begin gsave");
2425  PrintStr(" 1 100 m 25 100 l 25 75 l 50 75 l 50 50 l");
2426  PrintStr(" 75 50 l 75 25 l 100 25 l 100 1 l");
2427  PrintStr(" 50 100 m 75 100 l 75 75 l 100 75 l 100 50 l");
2428  PrintStr(" 0 50 m 25 50 l 25 25 l 50 25 l 50 1 l s");
2429  PrintStr(" gr end } >> [ 0.5 0 0 0.5 0 0 ]");
2430  break;
2431  case 23 :
2432  PrintStr(" /BBox [ 0 0 100 100 ]");
2433  PrintStr(" /XStep 100 /YStep 100");
2434  PrintStr(" /PaintProc { begin gsave");
2435  PrintStr(" [1 7] 0 sd 0 8 50 { dup dup m 2 mul 0 l s } for");
2436  PrintStr(" 0 8 50 { dup dup 2 mul 100 m 50 add exch 50");
2437  PrintStr(" add l s } for 100 0 m 100 100 l 50 50 l f");
2438  PrintStr(" gr end } >> [ 0.24 0 0 0.24 0 0 ]");
2439  break;
2440  case 24 :
2441  PrintStr(" /BBox [ 0 0 100 100 ]");
2442  PrintStr(" /XStep 100 /YStep 100");
2443  PrintStr(" /PaintProc { begin gsave");
2444  PrintStr(" 100 100 m 100 36 l 88 36 l 88 88 l f");
2445  PrintStr(" 100 0 m 100 12 l 56 12 l 50 0 l f");
2446  PrintStr(" 0 0 m 48 0 l 48 48 l 50 48 l 56 60 l");
2447  PrintStr(" 36 60 l 36 12 l 0 12 l f [1 7] 0 sd");
2448  PrintStr(" 61 8 87 { dup dup dup 12 exch m 88 exch l s");
2449  PrintStr(" 16 exch 4 sub m 88 exch 4 sub l s } for");
2450  PrintStr(" 13 8 35 { dup dup dup 0 exch m 36 exch l s");
2451  PrintStr(" 4 exch 4 sub m 36 exch 4 sub l s } for");
2452  PrintStr(" 37 8 59 { dup dup dup 12 exch m 36 exch l s");
2453  PrintStr(" 16 exch 4 sub m 36 exch 4 sub l s } for");
2454  PrintStr(" 13 8 60 { dup dup dup 56 exch m 100 exch l s");
2455  PrintStr(" 60 exch 4 sub m 100 exch 4 sub l s } for");
2456  PrintStr(" gr end } >> [ 0.5 0 0 0.5 0 0 ]");
2457  break;
2458  case 25 :
2459  PrintStr(" /BBox [ 0 0 101 101 ]");
2460  PrintStr(" /XStep 100 /YStep 100");
2461  PrintStr(" /PaintProc { begin gsave");
2462  PrintStr(" 0 0 m 30 30 l 70 30 l 70 70 l 100 100 l 100 0 l");
2463  PrintStr(" f 30 30 m 30 70 l 70 70 l f");
2464  PrintStr(" gr end } >> [ 0.5 0 0 0.5 0 0 ]");
2465  };
2466  snprintf(cdef,28," makepattern /%s exch def",&cpat[1]);
2467  PrintStr(cdef);
2468  fPatterns[ipat] = 1;
2469  }
2470 
2471  // Define the macro cs and FA if they are not yet defined.
2472  if (fPatterns[26] == 0) {
2473  if (gStyle->GetColorModelPS()) {
2474  PrintStr(" /cs {[/Pattern /DeviceCMYK] setcolorspace} def");
2475  PrintStr(" /FA {f [/DeviceCMYK] setcolorspace} def");
2476  } else {
2477  PrintStr(" /cs {[/Pattern /DeviceRGB] setcolorspace} def");
2478  PrintStr(" /FA {f [/DeviceRGB] setcolorspace} def");
2479  }
2480  fPatterns[26] = 1;
2481  }
2482 
2483  // Activate the pattern.
2484  PrintFast(3," cs");
2485  TColor *col = gROOT->GetColor(color);
2486  if (col) {
2487  Double_t colRed = col->GetRed();
2488  Double_t colGreen = col->GetGreen();
2489  Double_t colBlue = col->GetBlue();
2490  if (gStyle->GetColorModelPS()) {
2491  Double_t colBlack = TMath::Min(TMath::Min(1-colRed,1-colGreen),1-colBlue);
2492  if (colBlack==1) {
2493  WriteReal(0);
2494  WriteReal(0);
2495  WriteReal(0);
2496  WriteReal(colBlack);
2497  } else {
2498  Double_t colCyan = (1-colRed-colBlack)/(1-colBlack);
2499  Double_t colMagenta = (1-colGreen-colBlack)/(1-colBlack);
2500  Double_t colYellow = (1-colBlue-colBlack)/(1-colBlack);
2501  WriteReal(colCyan);
2502  WriteReal(colMagenta);
2503  WriteReal(colYellow);
2504  WriteReal(colBlack);
2505  }
2506  } else {
2507  WriteReal(colRed);
2508  WriteReal(colGreen);
2509  WriteReal(colBlue);
2510  }
2511  }
2512  PrintFast(4,cpat);
2513  PrintFast(9," setcolor");
2514 }
2515 
2516 ////////////////////////////////////////////////////////////////////////////////
2517 /// Set color index for lines
2518 
2520 {
2521  fLineColor = cindex;
2522  SetColor(Int_t(cindex));
2523 }
2524 
2525 ////////////////////////////////////////////////////////////////////////////////
2526 /// Set the value of the global parameter TPostScript::fgLineJoin.
2527 /// This parameter determines the appearance of joining lines in a PostScript
2528 /// output.
2529 /// It takes one argument which may be:
2530 /// - 0 (miter join)
2531 /// - 1 (round join)
2532 /// - 2 (bevel join)
2533 /// The default value is 0 (miter join).
2534 ///
2535 /// \image html postscript_1.png
2536 ///
2537 /// To change the line join behaviour just do:
2538 /// ~~~ {cpp}
2539 /// TPostScript::SetLineJoin(2); // Set the PS line join to bevel.
2540 /// ~~~
2541 
2543 {
2544  fgLineJoin = linejoin;
2545 }
2546 
2547 ////////////////////////////////////////////////////////////////////////////////
2548 /// Change the line style
2549 ///
2550 /// - linestyle = 2 dashed
2551 /// - linestyle = 3 dotted
2552 /// - linestyle = 4 dash-dotted
2553 /// - linestyle = else = solid
2554 ///
2555 /// See TStyle::SetLineStyleString for style definition
2556 
2558 {
2559  if ( linestyle == fLineStyle) return;
2560  fLineStyle = linestyle;
2561  const char *st = gStyle->GetLineStyleString(linestyle);
2562  PrintFast(1,"[");
2563  Int_t nch = strlen(st);
2564  PrintFast(nch,st);
2565  PrintFast(6,"] 0 sd");
2566 }
2567 
2568 ////////////////////////////////////////////////////////////////////////////////
2569 /// Change the line width
2570 
2572 {
2573  if ( linewidth == fLineWidth) return;
2574  fLineWidth = linewidth;
2575  if (fLineWidth!=0) {
2577  PrintFast(3," lw");
2578  }
2579 }
2580 
2581 ////////////////////////////////////////////////////////////////////////////////
2582 /// Set color index for markers
2583 
2585 {
2586  fMarkerColor = cindex;
2587  SetColor(Int_t(cindex));
2588 }
2589 
2590 ////////////////////////////////////////////////////////////////////////////////
2591 /// Set the current color.
2592 
2594 {
2595  if (color < 0) color = 0;
2596  fCurrentColor = color;
2597  TColor *col = gROOT->GetColor(color);
2598  if (col)
2599  SetColor(col->GetRed(), col->GetGreen(), col->GetBlue());
2600  else
2601  SetColor(1., 1., 1.);
2602 }
2603 
2604 ////////////////////////////////////////////////////////////////////////////////
2605 /// Set directly current color (don't go via TColor).
2606 
2608 {
2609  if (r == fRed && g == fGreen && b == fBlue) return;
2610 
2611  fRed = r;
2612  fGreen = g;
2613  fBlue = b;
2614 
2615  if (fRed <= 0 && fGreen <= 0 && fBlue <= 0 ) {
2616  PrintFast(6," black");
2617  } else {
2618  if (gStyle->GetColorModelPS()) {
2619  Double_t colBlack = TMath::Min(TMath::Min(1-fRed,1-fGreen),1-fBlue);
2620  Double_t colCyan = (1-fRed-colBlack)/(1-colBlack);
2621  Double_t colMagenta = (1-fGreen-colBlack)/(1-colBlack);
2622  Double_t colYellow = (1-fBlue-colBlack)/(1-colBlack);
2623  WriteReal(colCyan);
2624  WriteReal(colMagenta);
2625  WriteReal(colYellow);
2626  WriteReal(colBlack);
2627  } else {
2628  WriteReal(fRed);
2629  WriteReal(fGreen);
2630  WriteReal(fBlue);
2631  }
2632  PrintFast(2," c");
2633  }
2634 }
2635 
2636 ////////////////////////////////////////////////////////////////////////////////
2637 /// Set color index for text
2638 
2640 {
2641  fTextColor = cindex;
2642 
2643  SetColor( Int_t(cindex) );
2644 }
2645 
2646 ////////////////////////////////////////////////////////////////////////////////
2647 /// Write a string of characters
2648 ///
2649 /// This method writes the string chars into a PostScript file
2650 /// at position xx,yy in world coordinates.
2651 
2652 void TPostScript::Text(Double_t xx, Double_t yy, const char *chars)
2653 {
2654  static const char *psfont[31][2] = {
2655  { "Root.PSFont.1", "/Times-Italic" },
2656  { "Root.PSFont.2", "/Times-Bold" },
2657  { "Root.PSFont.3", "/Times-BoldItalic" },
2658  { "Root.PSFont.4", "/Helvetica" },
2659  { "Root.PSFont.5", "/Helvetica-Oblique" },
2660  { "Root.PSFont.6", "/Helvetica-Bold" },
2661  { "Root.PSFont.7", "/Helvetica-BoldOblique" },
2662  { "Root.PSFont.8", "/Courier" },
2663  { "Root.PSFont.9", "/Courier-Oblique" },
2664  { "Root.PSFont.10", "/Courier-Bold" },
2665  { "Root.PSFont.11", "/Courier-BoldOblique" },
2666  { "Root.PSFont.12", "/Symbol" },
2667  { "Root.PSFont.13", "/Times-Roman" },
2668  { "Root.PSFont.14", "/ZapfDingbats" },
2669  { "Root.PSFont.15", "/Symbol" },
2670  { "Root.PSFont.STIXGen", "/STIXGeneral" },
2671  { "Root.PSFont.STIXGenIt", "/STIXGeneral-Italic" },
2672  { "Root.PSFont.STIXGenBd", "/STIXGeneral-Bold" },
2673  { "Root.PSFont.STIXGenBdIt", "/STIXGeneral-BoldItalic" },
2674  { "Root.PSFont.STIXSiz1Sym", "/STIXSize1Symbols" },
2675  { "Root.PSFont.STIXSiz1SymBd", "/STIXSize1Symbols-Bold" },
2676  { "Root.PSFont.STIXSiz2Sym", "/STIXSize2Symbols" },
2677  { "Root.PSFont.STIXSiz2SymBd", "/STIXSize2Symbols-Bold" },
2678  { "Root.PSFont.STIXSiz3Sym", "/STIXSize3Symbols" },
2679  { "Root.PSFont.STIXSiz3SymBd", "/STIXSize3Symbols-Bold" },
2680  { "Root.PSFont.STIXSiz4Sym", "/STIXSize4Symbols" },
2681  { "Root.PSFont.STIXSiz4SymBd", "/STIXSize4Symbols-Bold" },
2682  { "Root.PSFont.STIXSiz5Sym", "/STIXSize5Symbols" },
2683  { "Root.PSFont.ME", "/DroidSansFallback" },
2684  { "Root.PSFont.CJKMing", "/DroidSansFallback" },
2685  { "Root.PSFont.CJKGothic", "/DroidSansFallback" }
2686  };
2687 
2688  const Double_t kDEGRAD = TMath::Pi()/180.;
2689  Double_t x = xx;
2690  Double_t y = yy;
2691  if (!gPad) return;
2692 
2693  // Compute the font size. Exit if it is 0
2694  // The font size is computed from the TTF size to get exactly the same
2695  // size on the screen and in the PostScript file.
2696  Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
2697  Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
2698  Float_t tsize, ftsize;
2699 
2700  if (wh < hh) {
2701  tsize = fTextSize*wh;
2702  Int_t sizeTTF = (Int_t)(tsize*kScale+0.5); // TTF size
2703  ftsize = (sizeTTF*fXsize*gPad->GetAbsWNDC())/wh;
2704  } else {
2705  tsize = fTextSize*hh;
2706  Int_t sizeTTF = (Int_t)(tsize*kScale+0.5); // TTF size
2707  ftsize = (sizeTTF*fYsize*gPad->GetAbsHNDC())/hh;
2708  }
2709  Double_t fontsize = 4*(72*(ftsize)/2.54);
2710  if( fontsize <= 0) return;
2711 
2712  Float_t tsizex = gPad->AbsPixeltoX(Int_t(tsize))-gPad->AbsPixeltoX(0);
2713  Float_t tsizey = gPad->AbsPixeltoY(0)-gPad->AbsPixeltoY(Int_t(tsize));
2714 
2715  Int_t font = abs(fTextFont)/10;
2716  if( font > 31 || font < 1) font = 1;
2717 
2718  // Text color.
2720 
2721  // Text alignment.
2722  Int_t txalh = fTextAlign/10;
2723  if (txalh <1) txalh = 1; else if (txalh > 3) txalh = 3;
2724  Int_t txalv = fTextAlign%10;
2725  if (txalv <1) txalv = 1; else if (txalv > 3) txalv = 3;
2726  if (txalv == 3) {
2727  y -= 0.8*tsizey*TMath::Cos(kDEGRAD*fTextAngle);
2728  x += 0.8*tsizex*TMath::Sin(kDEGRAD*fTextAngle);
2729  } else if (txalv == 2) {
2730  y -= 0.4*tsizey*TMath::Cos(kDEGRAD*fTextAngle);
2731  x += 0.4*tsizex*TMath::Sin(kDEGRAD*fTextAngle);
2732  }
2733 
2734  UInt_t w = 0, w0 = 0;
2735  Bool_t kerning;
2736  // In order to measure the precise character positions we need to trick
2737  // FreeType into rendering high-resolution characters otherwise it will
2738  // stick to the screen pixel grid, which is far worse than we can achieve
2739  // on print.
2740  const Float_t scale = 16.0;
2741  // Save current text attributes.
2742  TText saveAttText;
2743  saveAttText.TAttText::operator=(*this);
2744  const Int_t len=strlen(chars);
2745  Int_t *charWidthsCumul = 0;
2746  TText t;
2747  t.SetTextSize(fTextSize * scale);
2749  t.GetTextAdvance(w, chars);
2750  t.GetTextAdvance(w0, chars, kFALSE);
2751  t.TAttText::Modify();
2752  if (w0-w != 0) kerning = kTRUE;
2753  else kerning = kFALSE;
2754  if (kerning) {
2755  // Calculate the individual character placements.
2756  charWidthsCumul = new Int_t[len];
2757  for (Int_t i = len - 1;i >= 0;i--) {
2758  UInt_t ww = 0;
2759  t.GetTextAdvance(ww, chars + i);
2760  Double_t wwl = (gPad->AbsPixeltoX(ww)-gPad->AbsPixeltoX(0));
2761  charWidthsCumul[i] = (Int_t)((XtoPS(wwl) - XtoPS(0)) / scale);
2762  }
2763  }
2764  // Restore text attributes.
2765  saveAttText.TAttText::Modify();
2766 
2767  Double_t charsLength = gPad->AbsPixeltoX(w)-gPad->AbsPixeltoX(0);
2768  Int_t psCharsLength = (Int_t)((XtoPS(charsLength)-XtoPS(0)) / scale);
2769 
2770  // Text angle.
2771  Int_t psangle = Int_t(0.5 + fTextAngle);
2772 
2773  // Save context.
2774  PrintStr("@");
2775  SaveRestore(1);
2776 
2777  // Clipping
2778  Int_t xc1 = XtoPS(gPad->GetX1());
2779  Int_t xc2 = XtoPS(gPad->GetX2());
2780  Int_t yc1 = YtoPS(gPad->GetY1());
2781  Int_t yc2 = YtoPS(gPad->GetY2());
2782  WriteInteger(xc2 - xc1);
2783  WriteInteger(yc2 - yc1);
2784  WriteInteger(xc1);
2785  WriteInteger(yc1);
2786  PrintStr(" C");
2787 
2788  // Output text position and angle. The text position is computed
2789  // using Double_t to avoid precision problems.
2790  Double_t vx = (x - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1());
2791  Double_t cmx = fXsize*(gPad->GetAbsXlowNDC()+vx*gPad->GetAbsWNDC());
2792  WriteReal((288.*cmx)/2.54);
2793  Double_t vy = (y - gPad->GetY1())/(gPad->GetY2()-gPad->GetY1());
2794  Double_t cmy = fYsize*(gPad->GetAbsYlowNDC()+vy*gPad->GetAbsHNDC());
2795  WriteReal((288.*cmy)/2.54);
2796  PrintStr(Form(" t %d r ", psangle));
2797  if(txalh == 2) PrintStr(Form(" %d 0 t ", -psCharsLength/2));
2798  if(txalh == 3) PrintStr(Form(" %d 0 t ", -psCharsLength));
2799  PrintStr(gEnv->GetValue(psfont[font-1][0], psfont[font-1][1]));
2800  if (font != 15) {
2801  PrintStr(Form(" findfont %g sf 0 0 m ",fontsize));
2802  } else {
2803  PrintStr(Form(" findfont %g sf 0 0 m ita ",fontsize));
2804  }
2805 
2806  if (kerning) {
2807  PrintStr("@");
2808  // Output individual character placements
2809  for (Int_t i = len-1; i >= 1; i--) {
2810  WriteInteger(charWidthsCumul[0] - charWidthsCumul[i]);
2811  }
2812  delete [] charWidthsCumul;
2813  PrintStr("@");
2814  }
2815 
2816  // Output text.
2817  PrintStr("(");
2818 
2819  // Inside a PostScript string, the new line (if needed to break up long lines) must be escaped by a backslash.
2820  const char *crsave = fImplicitCREsc;
2821  fImplicitCREsc = "\\";
2822 
2823  char str[8];
2824  for (Int_t i=0; i<len;i++) {
2825  if (chars[i]!='\n') {
2826  if (chars[i]=='(' || chars[i]==')' || chars[i]=='\\') {
2827  snprintf(str,8,"\\%c",chars[i]);
2828  PrintStr(str);
2829  } else if ((chars[i]=='-') && (font != 12)) {
2830  PrintStr("\\255");
2831  } else {
2832  snprintf(str,8,"%c",chars[i]);
2833  PrintFast(1,str);
2834  }
2835  }
2836  }
2837  PrintStr(")");
2838  fImplicitCREsc = crsave;
2839 
2840  if (kerning) {
2841  if (font != 15) PrintStr(" K NC");
2842  else PrintStr(" K gr NC");
2843  } else {
2844  if (font != 15) PrintStr(" show NC");
2845  else PrintStr(" show gr NC");
2846  }
2847 
2848  SaveRestore(-1);
2849 }
2850 
2851 ////////////////////////////////////////////////////////////////////////////////
2852 /// Write a string of characters
2853 ///
2854 /// This method writes the string chars into a PostScript file
2855 /// at position xx,yy in world coordinates.
2856 
2857 void TPostScript::Text(Double_t xx, Double_t yy, const wchar_t *chars)
2858 {
2859  static const char *psfont[31][2] = {
2860  { "Root.PSFont.1", "/FreeSerifItalic" },
2861  { "Root.PSFont.2", "/FreeSerifBold" },
2862  { "Root.PSFont.3", "/FreeSerifBoldItalic" },
2863  { "Root.PSFont.4", "/FreeSans" },
2864  { "Root.PSFont.5", "/FreeSansOblique" },
2865  { "Root.PSFont.6", "/FreeSansBold" },
2866  { "Root.PSFont.7", "/FreeSansBoldOblique" },
2867  { "Root.PSFont.8", "/FreeMono" },
2868  { "Root.PSFont.9", "/FreeMonoOblique" },
2869  { "Root.PSFont.10", "/FreeMonoBold" },
2870  { "Root.PSFont.11", "/FreeMonoBoldOblique" },
2871  { "Root.PSFont.12", "/StandardSymbolsL" },
2872  { "Root.PSFont.13", "/FreeSerif" },
2873  { "Root.PSFont.14", "/Dingbats" },
2874  { "Root.PSFont.15", "/StandardSymbolsL" },
2875  { "Root.PSFont.STIXGen", "/STIXGeneral" },
2876  { "Root.PSFont.STIXGenIt", "/STIXGeneral-Italic" },
2877  { "Root.PSFont.STIXGenBd", "/STIXGeneral-Bold" },
2878  { "Root.PSFont.STIXGenBdIt", "/STIXGeneral-BoldItalic" },
2879  { "Root.PSFont.STIXSiz1Sym", "/STIXSize1Symbols" },
2880  { "Root.PSFont.STIXSiz1SymBd", "/STIXSize1Symbols-Bold" },
2881  { "Root.PSFont.STIXSiz2Sym", "/STIXSize2Symbols" },
2882  { "Root.PSFont.STIXSiz2SymBd", "/STIXSize2Symbols-Bold" },
2883  { "Root.PSFont.STIXSiz3Sym", "/STIXSize3Symbols" },
2884  { "Root.PSFont.STIXSiz3SymBd", "/STIXSize3Symbols-Bold" },
2885  { "Root.PSFont.STIXSiz4Sym", "/STIXSize4Symbols" },
2886  { "Root.PSFont.STIXSiz4SymBd", "/STIXSize4Symbols-Bold" },
2887  { "Root.PSFont.STIXSiz5Sym", "/STIXSize5Symbols" },
2888  { "Root.PSFont.ME", "/DroidSansFallback" },
2889  { "Root.PSFont.CJKMing", "/DroidSansFallback" },
2890  { "Root.PSFont.CJKGothic", "/DroidSansFallback" }
2891  };
2892 
2893  Int_t len = wcslen(chars);
2894  if (len<=0) return;
2895 
2896  const Double_t kDEGRAD = TMath::Pi()/180.;
2897  Double_t x = xx;
2898  Double_t y = yy;
2899  if (!gPad) return;
2900 
2901  // Compute the font size. Exit if it is 0
2902  // The font size is computed from the TTF size to get exactly the same
2903  // size on the screen and in the PostScript file.
2904  Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
2905  Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
2906  Float_t tsize, ftsize;
2907 
2908  if (wh < hh) {
2909  tsize = fTextSize*wh;
2910  Int_t sizeTTF = (Int_t)(tsize*kScale+0.5); // TTF size
2911  ftsize = (sizeTTF*fXsize*gPad->GetAbsWNDC())/wh;
2912  } else {
2913  tsize = fTextSize*hh;
2914  Int_t sizeTTF = (Int_t)(tsize*kScale+0.5); // TTF size
2915  ftsize = (sizeTTF*fYsize*gPad->GetAbsHNDC())/hh;
2916  }
2917  Double_t fontsize = 4*(72*(ftsize)/2.54);
2918  if( fontsize <= 0) return;
2919 
2920  Float_t tsizex = gPad->AbsPixeltoX(Int_t(tsize))-gPad->AbsPixeltoX(0);
2921  Float_t tsizey = gPad->AbsPixeltoY(0)-gPad->AbsPixeltoY(Int_t(tsize));
2922 
2923  Int_t font = abs(fTextFont)/10;
2924  if( font > 29 || font < 1) font = 1;
2925 
2926  // Text color.
2928 
2929  // Text alignment.
2930  Int_t txalh = fTextAlign/10;
2931  if (txalh <1) txalh = 1; else if (txalh > 3) txalh = 3;
2932  Int_t txalv = fTextAlign%10;
2933  if (txalv <1) txalv = 1; else if (txalv > 3) txalv = 3;
2934  if (txalv == 3) {
2935  y -= 0.8*tsizey*TMath::Cos(kDEGRAD*fTextAngle);
2936  x += 0.8*tsizex*TMath::Sin(kDEGRAD*fTextAngle);
2937  } else if (txalv == 2) {
2938  y -= 0.4*tsizey*TMath::Cos(kDEGRAD*fTextAngle);
2939  x += 0.4*tsizex*TMath::Sin(kDEGRAD*fTextAngle);
2940  }
2941  UInt_t w = 0, h = 0;
2942 
2943  TText t;
2946  t.GetTextExtent(w, h, chars);
2947  Double_t charsLength = gPad->AbsPixeltoX(w)-gPad->AbsPixeltoX(0);
2948  Int_t psCharsLength = XtoPS(charsLength)-XtoPS(0);
2949 
2950  // Text angle.
2951  Int_t psangle = Int_t(0.5 + fTextAngle);
2952 
2953  // Save context.
2954  PrintStr("@");
2955  SaveRestore(1);
2956 
2957  // Clipping
2958  Int_t xc1 = XtoPS(gPad->GetX1());
2959  Int_t xc2 = XtoPS(gPad->GetX2());
2960  Int_t yc1 = YtoPS(gPad->GetY1());
2961  Int_t yc2 = YtoPS(gPad->GetY2());
2962  WriteInteger(xc2 - xc1);
2963  WriteInteger(yc2 - yc1);
2964  WriteInteger(xc1);
2965  WriteInteger(yc1);
2966  PrintStr(" C");
2967 
2968  // Output text position and angle.
2969  WriteInteger(XtoPS(x));
2970  WriteInteger(YtoPS(y));
2971  PrintStr(Form(" t %d r ", psangle));
2972  if(txalh == 2) PrintStr(Form(" %d 0 t ", -psCharsLength/2));
2973  if(txalh == 3) PrintStr(Form(" %d 0 t ", -psCharsLength));
2974  MustEmbed[font-1] = kTRUE; // This font will be embedded in the file at EOF time.
2975  PrintStr(gEnv->GetValue(psfont[font-1][0], psfont[font-1][1]));
2976  PrintStr(Form(" findfont %g sf 0 0 m ",fontsize));
2977 
2978  // Output text.
2979  if (len > 1) PrintStr(Form("%d ", len));
2980  for(Int_t i = 0; i < len; i++) {
2981  // Adobe Glyph Naming Convention
2982  // http://www.adobe.com/devnet/opentype/archives/glyph.html
2983 #include "AdobeGlyphList.h"
2984  const wchar_t *lower = std::lower_bound(
2986  chars[i]);
2987  if(lower < adobe_glyph_ucs + nadobe_glyph &&
2988  *lower == chars[i]) {
2989  // Named glyph from AGL 1.2
2990  const unsigned long index =
2991  lower - adobe_glyph_ucs;
2992  PrintStr(Form("/%s ", adobe_glyph_name[index]));
2993  }
2994  else if((unsigned int)chars[i] < 0xffff) {
2995  // Unicode BMP
2996  PrintStr(Form("/uni%04X ",
2997  (unsigned int)chars[i]));
2998  }
2999  else {
3000  // Unicode supplemental planes
3001  PrintStr(Form("/u%04X ",
3002  (unsigned int)chars[i]));
3003  }
3004  }
3005  if(len > 1) {
3006  PrintStr("{glyphshow} repeat ");
3007  }
3008  else {
3009  PrintStr("glyphshow ");
3010  }
3011 
3012  PrintStr("NC");
3013 
3014  SaveRestore(-1);
3015 }
3016 
3017 ////////////////////////////////////////////////////////////////////////////////
3018 /// Write a string of characters in NDC
3019 
3020 void TPostScript::TextNDC(Double_t u, Double_t v, const char *chars)
3021 {
3022  Double_t x = gPad->GetX1() + u*(gPad->GetX2() - gPad->GetX1());
3023  Double_t y = gPad->GetY1() + v*(gPad->GetY2() - gPad->GetY1());
3024  Text(x, y, chars);
3025 }
3026 
3027 ////////////////////////////////////////////////////////////////////////////////
3028 /// Write a string of characters in NDC
3029 
3030 void TPostScript::TextNDC(Double_t u, Double_t v, const wchar_t *chars)
3031 {
3032  Double_t x = gPad->GetX1() + u*(gPad->GetX2() - gPad->GetX1());
3033  Double_t y = gPad->GetY1() + v*(gPad->GetY2() - gPad->GetY1());
3034  Text(x, y, chars);
3035 }
3036 
3037 ////////////////////////////////////////////////////////////////////////////////
3038 /// Convert U from NDC coordinate to PostScript
3039 
3041 {
3042  Double_t cm = fXsize*(gPad->GetAbsXlowNDC() + u*gPad->GetAbsWNDC());
3043  return Int_t(0.5 + 288*cm/2.54);
3044 }
3045 
3046 ////////////////////////////////////////////////////////////////////////////////
3047 /// Convert V from NDC coordinate to PostScript
3048 
3050 {
3051  Double_t cm = fYsize*(gPad->GetAbsYlowNDC() + v*gPad->GetAbsHNDC());
3052  return Int_t(0.5 + 288*cm/2.54);
3053 }
3054 
3055 ////////////////////////////////////////////////////////////////////////////////
3056 /// Convert X from world coordinate to PostScript
3057 
3059 {
3060  Double_t u = (x - gPad->GetX1())/(gPad->GetX2() - gPad->GetX1());
3061  return UtoPS(u);
3062 }
3063 
3064 ////////////////////////////////////////////////////////////////////////////////
3065 /// Convert Y from world coordinate to PostScript
3066 
3068 {
3069  Double_t v = (y - gPad->GetY1())/(gPad->GetY2() - gPad->GetY1());
3070  return VtoPS(v);
3071 }
3072 
3073 ////////////////////////////////////////////////////////////////////////////////
3074 /// Initialize the PostScript page in zones
3075 
3077 {
3078  if( !fClear )return;
3079  fClear = kFALSE;
3080 
3081  // When Zone has been called, fZone is TRUE
3082  fZone = kTRUE;
3083 
3084  if( fIYzone > fNYzone) {
3085  fIYzone=1;
3086  if( fMode != 3) {
3087  PrintStr("@showpage");
3088  SaveRestore(-1);
3089  fNpages++;
3090  PrintStr("@%%Page:");
3093  PrintStr("@");
3094  } else {
3095  PrintFast(9," showpage");
3096  SaveRestore(-1);
3097  }
3098  }
3099 
3100  // No grestore the first time
3101  if( fMode != 3) {
3102  if( fIXzone != 1 || fIYzone != 1) SaveRestore(-1);
3103  SaveRestore(1);
3104  PrintStr("@");
3107  PrintFast(5," Zone");
3108  PrintStr("@");
3109  fIXzone++;
3110  if( fIXzone > fNXzone) { fIXzone=1; fIYzone++; }
3111  }
3112 
3113  // Picture Initialisation
3114  SaveRestore(1);
3115  if (fgLineJoin) {
3117  PrintFast(12," setlinejoin");
3118  }
3119  PrintFast(6," 0 0 t");
3120  fRed = -1;
3121  fGreen = -1;
3122  fBlue = -1;
3123  fPrinted = kFALSE;
3124  fLineColor = -1;
3125  fLineStyle = -1;
3126  fLineWidth = -1;
3127  fFillColor = -1;
3128  fFillStyle = -1;
3129  fMarkerSizeCur = -1;
3130 }
Interface to PostScript.
Definition: TPostScript.h:31
virtual ~TPostScript()
Default PostScript destructor.
Int_t GetColorModelPS() const
Definition: TStyle.h:206
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
void DrawPolyLine(Int_t n, TPoints *xy)
Draw a PolyLine.
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1264
static Bool_t MustEmbed[32]
Float_t GetLineScalePS() const
Definition: TStyle.h:295
Int_t fNBSameColorCell
Definition: TPostScript.h:88
char * fBuffer
Definition: TVirtualPS.h:52
void Text(Double_t x, Double_t y, const char *string)
Write a string of characters.
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:711
Float_t fXsize
Definition: TPostScript.h:56
Float_t GetRed() const
Definition: TColor.h:60
Float_t fYVP2
Definition: TPostScript.h:51
T1 Sign(T1 a, T2 b)
Definition: TMathBase.h:155
short Style_t
Definition: RtypesCore.h:76
Bool_t fClear
Definition: TPostScript.h:76
TLine * line
void On()
Activate an already open PostScript file.
float Float_t
Definition: RtypesCore.h:53
void DrawPolyLineNDC(Int_t n, TPoints *uv)
Draw a PolyLine in NDC space.
const char Option_t
Definition: RtypesCore.h:62
Int_t CMtoPS(Double_t u)
Definition: TPostScript.h:104
void DefineMarkers()
Define the markers.
R__EXTERN TStyle * gStyle
Definition: TStyle.h:423
void CellArrayFill(Int_t r, Int_t g, Int_t b)
Paint the Cell Array.
Float_t fYsize
Definition: TPostScript.h:57
TH1 * h
Definition: legend2.C:5
Float_t fXVP2
Definition: TPostScript.h:49
void GetPaperSize(Float_t &xsize, Float_t &ysize) const
Set paper size for PostScript output.
Definition: TStyle.cxx:805
const char * fImplicitCREsc
Definition: TVirtualPS.h:53
Size_t fMarkerSize
Definition: TAttMarker.h:37
Bool_t fBoundingBox
Definition: TPostScript.h:75
static const char * filename()
Int_t fCurrentColor
Definition: TPostScript.h:70
#define gROOT
Definition: TROOT.h:352
Basic string class.
Definition: TString.h:137
virtual void WriteInteger(Int_t i, Bool_t space=kTRUE)
Write one Integer to the file.
Definition: TVirtualPS.cxx:167
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
static const unsigned long nadobe_glyph
Definition: AdobeGlyphList.h:1
Int_t fLastCellRed
Definition: TPostScript.h:85
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Float_t fMarkerSizeCur
Definition: TPostScript.h:69
const Bool_t kFALSE
Definition: Rtypes.h:92
void DrawPS(Int_t n, Float_t *xw, Float_t *yw)
Draw a PolyLine.
Int_t fNXzone
Definition: TPostScript.h:65
char fPatterns[32]
Definition: TPostScript.h:80
Bool_t fFontEmbed
Definition: TPostScript.h:90
void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Draw a Box.
void FontEmbed()
Embed font in PS file.
bool FontEmbedType42(const char *filename)
static std::string format(double x, double y, int digits, int width)
Float_t GetBlue() const
Definition: TColor.h:62
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:501
virtual void WriteReal(Float_t r, Bool_t space=kTRUE)
Write a Real number to the file.
Definition: TVirtualPS.cxx:182
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition: TSystem.cxx:1318
Int_t fType
Definition: TPostScript.h:72
void SetLineStyle(Style_t linestyle=1)
Change the line style.
virtual void SetTextFont(Font_t tfont=62)
Definition: TAttText.h:59
virtual void GetTextAdvance(UInt_t &a, const char *text, const Bool_t kern=kTRUE) const
Return text advance for string text if kern is true (default) kerning is taken into account...
Definition: TText.cxx:611
Int_t fSave
Definition: TPostScript.h:64
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1345
static const double x2[5]
Float_t fMaxsize
Definition: TPostScript.h:58
Int_t fNpages
Definition: TPostScript.h:71
Double_t x[n]
Definition: legend1.C:17
TPostScript()
Default PostScript constructor.
void SetLineWidth(Width_t linewidth=1)
Change the line width.
void Open(const char *filename, Int_t type=-111)
Open a PostScript file.
static Int_t fgLineJoin
Definition: TPostScript.h:92
virtual void PrintStr(const char *string="")
Output the string str in the output buffer.
Definition: TVirtualPS.cxx:69
TString fFileName
Definition: TPostScript.h:89
Int_t fNYzone
Definition: TPostScript.h:66
Float_t GetGreen() const
Definition: TColor.h:61
bool FontEmbedType2(const char *filename)
Int_t fNbCellW
Definition: TPostScript.h:82
Bool_t fClipStatus
Definition: TPostScript.h:77
static Vc_ALWAYS_INLINE Vector< T > abs(const Vector< T > &x)
Definition: vector.h:450
Base class for several text objects.
Definition: TText.h:42
Int_t fIYzone
Definition: TPostScript.h:68
Int_t fNbCellLine
Definition: TPostScript.h:83
short Color_t
Definition: RtypesCore.h:79
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)
Draw a Frame around a box.
Style_t fMarkerStyle
Definition: TAttMarker.h:36
TCanvas * kerning()
Definition: kerning.C:1
void CellArrayEnd()
End the Cell Array painting.
void MovePS(Int_t x, Int_t y)
Move to a new position.
Int_t UtoPS(Double_t u)
Convert U from NDC coordinate to PostScript.
Float_t fTextAngle
Definition: TAttText.h:35
Style_t fLineStyle
Definition: TAttLine.h:36
ROOT::R::TRInterface & r
Definition: Object.C:4
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
void Range(Float_t xrange, Float_t yrange)
Set the range for the paper in centimeters.
SVector< double, 2 > v
Definition: Dict.h:5
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
Int_t fSizBuffer
Definition: TVirtualPS.h:49
const char * GetLineStyleString(Int_t i=1) const
Return line style string (used by PostScript).
Definition: TStyle.cxx:787
Color_t fLineColor
Definition: TAttLine.h:35
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:480
void DrawPolyMarker(Int_t n, Float_t *x, Float_t *y)
Draw markers at the n WC points x, y.
const char * GetTitlePS() const
Definition: TStyle.h:293
void TextNDC(Double_t u, Double_t v, const char *string)
Write a string of characters in NDC.
unsigned int UInt_t
Definition: RtypesCore.h:42
Width_t fLineWidth
Definition: TAttLine.h:37
Float_t fXVP1
Definition: TPostScript.h:48
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
char * Form(const char *fmt,...)
Int_t fLastCellBlue
Definition: TPostScript.h:87
void DrawHatch(Float_t dy, Float_t angle, Int_t n, Float_t *x, Float_t *y)
Draw Fill area with hatch styles.
void SetMarkerColor(Color_t cindex=1)
Set color index for markers.
Bool_t fPrinted
Definition: TVirtualPS.h:50
void SetLineJoin(Int_t linejoin=0)
Set the value of the global parameter TPostScript::fgLineJoin.
std::ofstream * fStream
Definition: TVirtualPS.h:51
const Float_t kScale
void FontEncode()
Font Re-encoding.
Float_t fRed
Definition: TPostScript.h:59
Font_t fTextFont
Definition: TAttText.h:39
const char * GetHeaderPS() const
Definition: TStyle.h:292
Bool_t fRange
Definition: TPostScript.h:78
Double_t Cos(Double_t)
Definition: TMath.h:424
short Width_t
Definition: RtypesCore.h:78
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2513
void CellArrayBegin(Int_t W, Int_t H, Double_t x1, Double_t x2, Double_t y1, Double_t y2)
Draw a Cell Array.
PyObject * fType
Double_t Pi()
Definition: TMath.h:44
2-D graphics point (world coordinates).
Definition: TPoints.h:29
void SaveRestore(Int_t flag)
Compute number of gsaves for restore This allows to write the correct number of grestore at the end o...
Int_t YtoPS(Double_t y)
Convert Y from world coordinate to PostScript.
virtual void PrintRaw(Int_t len, const char *str)
Print a raw.
Definition: TVirtualPS.cxx:197
Int_t fNbinCT
Definition: TPostScript.h:81
static const double x1[5]
void Off()
Deactivate an already open PostScript file.
#define ClassImp(name)
Definition: Rtypes.h:279
void SetFillPatterns(Int_t ipat, Int_t color)
Patterns definition.
double Double_t
Definition: RtypesCore.h:55
virtual void PrintFast(Int_t nch, const char *string="")
Fast version of Print.
Definition: TVirtualPS.cxx:100
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
Bool_t fZone
Definition: TPostScript.h:79
bool FontEmbedType1(const char *filename)
Double_t y[n]
Definition: legend1.C:17
virtual Color_t GetFillColor() const
Definition: TAttFill.h:43
Int_t fIXzone
Definition: TPostScript.h:67
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:99
The color creation and management class.
Definition: TColor.h:23
Float_t fTextSize
Definition: TAttText.h:36
void Zone()
Initialize the PostScript page in zones.
void SetColor(Int_t color=1)
Set the current color.
virtual void GetTextExtent(UInt_t &w, UInt_t &h, const char *text) const
Return text extent for string text.
Definition: TText.cxx:583
Int_t fLenBuffer
Definition: TVirtualPS.h:48
static const char * adobe_glyph_name[nadobe_glyph]
void SetLineScale(Float_t scale=3)
Definition: TPostScript.h:136
Int_t VtoPS(Double_t v)
Convert V from NDC coordinate to PostScript.
void Close(Option_t *opt="")
Close a PostScript file.
void SetFillColor(Color_t cindex=1)
Set color index for fill areas.
Color_t fFillColor
Definition: TAttFill.h:35
Double_t Sin(Double_t)
Definition: TMath.h:421
Int_t fClip
Definition: TPostScript.h:74
void Initialize()
PostScript Initialisation.
#define NULL
Definition: Rtypes.h:82
R__EXTERN TVirtualPS * gVirtualPS
Definition: TVirtualPS.h:91
#define gPad
Definition: TVirtualPad.h:288
Int_t fMode
Definition: TPostScript.h:73
Int_t fLastCellGreen
Definition: TPostScript.h:86
void NewPage()
Move to a new PostScript page.
Float_t fLineScale
Definition: TPostScript.h:62
double result[121]
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition: TVirtualPS.h:40
Double_t Sqrt(Double_t x)
Definition: TMath.h:464
virtual void SetTextSize(Float_t tsize=1)
Definition: TAttText.h:60
Int_t XtoPS(Double_t x)
Convert X from world coordinate to PostScript.
const Bool_t kTRUE
Definition: Rtypes.h:91
Color_t fMarkerColor
Definition: TAttMarker.h:35
virtual void SetTitle(const char *title="")
Change (i.e. set) the title of the TNamed.
Definition: TNamed.cxx:152
float value
Definition: math.cpp:443
Color_t fTextColor
Definition: TAttText.h:38
void SetTextColor(Color_t cindex=1)
Set color index for text.
const Int_t n
Definition: legend1.C:16
void SetLineColor(Color_t cindex=1)
Set color index for lines.
Float_t fGreen
Definition: TPostScript.h:60
Float_t fYVP1
Definition: TPostScript.h:50
static const float lower
Definition: main.cpp:48
Int_t fMaxLines
Definition: TPostScript.h:84
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904
Float_t fBlue
Definition: TPostScript.h:61
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:39
Style_t fFillStyle
Definition: TAttFill.h:36
Short_t fTextAlign
Definition: TAttText.h:37
const char * Data() const
Definition: TString.h:349
static const wchar_t adobe_glyph_ucs[nadobe_glyph]
Definition: AdobeGlyphList.h:2