ROOT  6.06/09
Reference Guide
TSVG.cxx
Go to the documentation of this file.
1 // @(#)root/postscript:$Id$
2 // Author: Olivier Couet
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #ifdef WIN32
13 #pragma optimize("",off)
14 #endif
15 
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 
20 #include "Riostream.h"
21 #include "TROOT.h"
22 #include "TColor.h"
23 #include "TVirtualPad.h"
24 #include "TPoints.h"
25 #include "TSVG.h"
26 #include "TStyle.h"
27 #include "TMath.h"
28 #include "TObjString.h"
29 #include "TObjArray.h"
30 #include "TClass.h"
31 
33 
34 /** \class TSVG
35 \ingroup PS
36 
37 Interface to SVG
38 
39 [SVG](http://www.w3.org/Graphics/SVG/Overview.htm8)
40 (Scalable Vector Graphics) is a language for describing
41 two-dimensional graphics in XML. SVG allows high quality vector graphics in
42 HTML pages.
43 
44 To print a ROOT canvas "c1" into an SVG file simply do:
45 ~~~ {.cpp}
46  c1->Print("c1.svg");
47 ~~~
48 The result is the ASCII file `c1.svg`.
49 
50 It can be open directly using a web browser or included in a html document
51 the following way:
52 ~~~ {.cpp}
53 <embed width="95%" height="500" src="c1.svg">
54 ~~~
55 It is best viewed with Internet Explorer and you need the
56 [Adobe SVG Viewer](http://www.adobe.com/svg/viewer/install/main.html)
57 
58 To zoom using the Adobe SVG Viewer, position the mouse over
59 the area you want to zoom and click the right button.
60 
61 To define the zoom area,
62 use Control+drag to mark the boundaries of the zoom area.
63 
64 To pan, use Alt+drag.
65 By clicking with the right mouse button on the SVG graphics you will get
66 a pop-up menu giving other ways to interact with the image.
67 
68 SVG files can be used directly in compressed mode to minimize the time
69 transfer over the network. Compressed SVG files should be created using
70 `gzip` on a normal ASCII SVG file and should then be renamed
71 using the file extension `.svgz`.
72 */
73 
74 ////////////////////////////////////////////////////////////////////////////////
75 /// Default SVG constructor
76 
77 TSVG::TSVG() : TVirtualPS()
78 {
79  fStream = 0;
80  fType = 0;
81  gVirtualPS = this;
82  fBoundingBox = kFALSE;
83  fRange = kFALSE;
84  fXsize = 0.;
85  fYsize = 0.;
86  fYsizeSVG = 0;
87  SetTitle("SVG");
88 }
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Initialize the SVG interface
92 ///
93 /// - fname : SVG file name
94 /// - wtype : SVG workstation type. Not used in the SVG driver. But as TSVG
95 /// inherits from TVirtualPS it should be kept. Anyway it is not
96 /// necessary to specify this parameter at creation time because it
97 /// has a default value (which is ignore in the SVG case).
98 
99 TSVG::TSVG(const char *fname, Int_t wtype) : TVirtualPS(fname, wtype)
100 {
101  fStream = 0;
102  SetTitle("SVG");
103  Open(fname, wtype);
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// Open a SVG file
108 
109 void TSVG::Open(const char *fname, Int_t wtype)
110 {
111  if (fStream) {
112  Warning("Open", "SVG file already open");
113  return;
114  }
115 
116  fLenBuffer = 0;
117  fType = abs(wtype);
120  Float_t xrange, yrange;
121  if (gPad) {
122  Double_t ww = gPad->GetWw();
123  Double_t wh = gPad->GetWh();
124  ww *= gPad->GetWNDC();
125  wh *= gPad->GetHNDC();
126  Double_t ratio = wh/ww;
127  xrange = fXsize;
128  yrange = fXsize*ratio;
129  if (yrange > fYsize) { yrange = fYsize; xrange = yrange/ratio;}
130  fXsize = xrange; fYsize = yrange;
131  }
132 
133  // Open OS file
134  fStream = new std::ofstream(fname,std::ios::out);
135  if (fStream == 0 || !fStream->good()) {
136  printf("ERROR in TSVG::Open: Cannot open file:%s\n",fname);
137  if (fStream == 0) return;
138  }
139 
140  gVirtualPS = this;
141 
142  for (Int_t i=0;i<fSizBuffer;i++) fBuffer[i] = ' ';
143 
145 
146  fRange = kFALSE;
147 
148  // Set a default range
149  Range(fXsize, fYsize);
150 
151  NewPage();
152 }
153 
154 ////////////////////////////////////////////////////////////////////////////////
155 /// Default SVG destructor
156 
158 {
159  Close();
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Close a SVG file
164 
166 {
167  if (!gVirtualPS) return;
168  if (!fStream) return;
169  if (gPad) gPad->Update();
170  PrintStr("</svg>@");
171 
172  // Close file stream
173  if (fStream) { fStream->close(); delete fStream; fStream = 0;}
174 
175  gVirtualPS = 0;
176 }
177 
178 ////////////////////////////////////////////////////////////////////////////////
179 /// Activate an already open SVG file
180 
181 void TSVG::On()
182 {
183  // fType is used to know if the SVG file is open. Unlike TPostScript, TSVG
184  // has no "workstation type". In fact there is only one SVG type.
185 
186  if (!fType) {
187  Error("On", "no SVG file open");
188  Off();
189  return;
190  }
191  gVirtualPS = this;
192 }
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 /// Deactivate an already open SVG file
196 
197 void TSVG::Off()
198 {
199  gVirtualPS = 0;
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 /// Draw a Box
204 
206 {
207  static Double_t x[4], y[4];
208  Double_t ix1 = XtoSVG(x1);
209  Double_t ix2 = XtoSVG(x2);
210  Double_t iy1 = YtoSVG(y1);
211  Double_t iy2 = YtoSVG(y2);
212  Int_t fillis = fFillStyle/1000;
213  Int_t fillsi = fFillStyle%1000;
214 
215  if (fillis == 3 || fillis == 2) {
216  if (fillsi > 99) {
217  x[0] = x1; y[0] = y1;
218  x[1] = x2; y[1] = y1;
219  x[2] = x2; y[2] = y2;
220  x[3] = x1; y[3] = y2;
221  return;
222  }
223  if (fillsi > 0 && fillsi < 26) {
224  x[0] = x1; y[0] = y1;
225  x[1] = x2; y[1] = y1;
226  x[2] = x2; y[2] = y2;
227  x[3] = x1; y[3] = y2;
228  DrawPS(-4, &x[0], &y[0]);
229  }
230  if (fillsi == -3) {
231  PrintStr("@");
232  PrintFast(9,"<rect x=\"");
233  WriteReal(ix1, kFALSE);
234  PrintFast(5,"\" y=\"");
235  WriteReal(iy2, kFALSE);
236  PrintFast(9,"\" width=\"");
237  WriteReal(ix2-ix1, kFALSE);
238  PrintFast(10,"\" height=\"");
239  WriteReal(iy1-iy2, kFALSE);
240  PrintFast(7,"\" fill=");
241  SetColor(5);
242  PrintFast(2,"/>");
243  }
244  }
245  if (fillis == 1) {
246  PrintStr("@");
247  PrintFast(9,"<rect x=\"");
248  WriteReal(ix1, kFALSE);
249  PrintFast(5,"\" y=\"");
250  WriteReal(iy2, kFALSE);
251  PrintFast(9,"\" width=\"");
252  WriteReal(ix2-ix1, kFALSE);
253  PrintFast(10,"\" height=\"");
254  WriteReal(iy1-iy2, kFALSE);
255  PrintFast(7,"\" fill=");
257  PrintFast(2,"/>");
258  }
259  if (fillis == 0) {
260  if (fLineWidth<=0) return;
261  PrintStr("@");
262  PrintFast(9,"<rect x=\"");
263  WriteReal(ix1, kFALSE);
264  PrintFast(5,"\" y=\"");
265  WriteReal(iy2, kFALSE);
266  PrintFast(9,"\" width=\"");
267  WriteReal(ix2-ix1, kFALSE);
268  PrintFast(10,"\" height=\"");
269  WriteReal(iy1-iy2, kFALSE);
270  PrintFast(21,"\" fill=\"none\" stroke=");
272  PrintFast(2,"/>");
273  }
274 }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Draw a Frame around a box
278 ///
279 /// - mode = -1 the box looks as it is behind the screen
280 /// - mode = 1 the box looks as it is in front of the screen
281 /// - border is the border size in already pre-computed SVG units dark is the
282 /// color for the dark part of the frame light is the color for the light
283 /// part of the frame
284 
286  Int_t mode, Int_t border, Int_t dark, Int_t light)
287 {
288  static Double_t xps[7], yps[7];
289  Int_t i;
290  Double_t ixd0, iyd0, ixdi, iydi, ix, iy;
291  Int_t idx, idy;
292 
293  //- Draw top&left part of the box
294 
295  xps[0] = XtoSVG(xl); yps[0] = YtoSVG(yl);
296  xps[1] = xps[0] + border; yps[1] = yps[0] - border;
297  xps[2] = xps[1]; yps[2] = YtoSVG(yt) + border;
298  xps[3] = XtoSVG(xt) - border; yps[3] = yps[2];
299  xps[4] = XtoSVG(xt); yps[4] = YtoSVG(yt);
300  xps[5] = xps[0]; yps[5] = yps[4];
301  xps[6] = xps[0]; yps[6] = yps[0];
302 
303  ixd0 = xps[0];
304  iyd0 = yps[0];
305  PrintStr("@");
306  PrintFast(10,"<path d=\"M");
307  WriteReal(ixd0, kFALSE);
308  PrintFast(1,",");
309  WriteReal(iyd0, kFALSE);
310 
311  idx = 0;
312  idy = 0;
313  for (i=1; i<7; i++) {
314  ixdi = xps[i];
315  iydi = yps[i];
316  ix = ixdi - ixd0;
317  iy = iydi - iyd0;
318  ixd0 = ixdi;
319  iyd0 = iydi;
320  if( ix && iy) {
321  if( idx ) { MovePS(idx,0); idx = 0; }
322  if( idy ) { MovePS(0,idy); idy = 0; }
323  MovePS(ix,iy);
324  continue;
325  }
326  if ( ix ) {
327  if( idy ) { MovePS(0,idy); idy = 0; }
328  if( !idx ) { idx = ix; continue;}
329  if( ix*idx > 0 ) {
330  idx += ix;
331  } else {
332  MovePS(idx,0);
333  idx = ix;
334  }
335  continue;
336  }
337  if( iy ) {
338  if( idx ) { MovePS(idx,0); idx = 0; }
339  if( !idy) { idy = iy; continue;}
340  if( iy*idy > 0 ) {
341  idy += iy;
342  } else {
343  MovePS(0,idy);
344  idy = iy;
345  }
346  }
347  }
348  if( idx ) MovePS(idx,0);
349  if( idy ) MovePS(0,idy);
350  PrintFast(8,"z\" fill=");
351  if (mode == -1) {
352  SetColor(dark);
353  } else {
354  SetColor(light);
355  }
356  PrintFast(2,"/>");
357 
358  //- Draw bottom&right part of the box
359  xps[0] = XtoSVG(xl); yps[0] = YtoSVG(yl);
360  xps[1] = xps[0] + border; yps[1] = yps[0] - border;
361  xps[2] = XtoSVG(xt) - border; yps[2] = yps[1];
362  xps[3] = xps[2]; yps[3] = YtoSVG(yt) + border;
363  xps[4] = XtoSVG(xt); yps[4] = YtoSVG(yt);
364  xps[5] = xps[4]; yps[5] = yps[0];
365  xps[6] = xps[0]; yps[6] = yps[0];
366 
367  ixd0 = xps[0];
368  iyd0 = yps[0];
369  PrintStr("@");
370  PrintFast(10,"<path d=\"M");
371  WriteReal(ixd0, kFALSE);
372  PrintFast(1,",");
373  WriteReal(iyd0, kFALSE);
374 
375  idx = 0;
376  idy = 0;
377  for (i=1;i<7;i++) {
378  ixdi = xps[i];
379  iydi = yps[i];
380  ix = ixdi - ixd0;
381  iy = iydi - iyd0;
382  ixd0 = ixdi;
383  iyd0 = iydi;
384  if( ix && iy) {
385  if( idx ) { MovePS(idx,0); idx = 0; }
386  if( idy ) { MovePS(0,idy); idy = 0; }
387  MovePS(ix,iy);
388  continue;
389  }
390  if ( ix ) {
391  if( idy ) { MovePS(0,idy); idy = 0; }
392  if( !idx ) { idx = ix; continue;}
393  if( ix*idx > 0 ) {
394  idx += ix;
395  } else {
396  MovePS(idx,0);
397  idx = ix;
398  }
399  continue;
400  }
401  if( iy ) {
402  if( idx ) { MovePS(idx,0); idx = 0; }
403  if( !idy) { idy = iy; continue;}
404  if( iy*idy > 0 ) {
405  idy += iy;
406  } else {
407  MovePS(0,idy);
408  idy = iy;
409  }
410  }
411  }
412  if( idx ) MovePS(idx,0);
413  if( idy ) MovePS(0,idy);
414  PrintFast(8,"z\" fill=");
415  if (mode == -1) {
416  SetColor(light);
417  } else {
418  SetColor(dark);
419  }
420  PrintFast(2,"/>");
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Draw a PolyLine
425 ///
426 /// Draw a polyline through the points xy.
427 /// - If NN=1 moves only to point x,y.
428 /// - If NN=0 the x,y are written in the SVG file
429 /// according to the current transformation.
430 /// - If NN>0 the line is clipped as a line.
431 /// - If NN<0 the line is clipped as a fill area.
432 
434 {
435  Int_t n, idx, idy;
436  Double_t ixd0, iyd0, ixdi, iydi, ix, iy;
437 
438  if (nn > 0) {
439  n = nn;
440  } else {
441  n = -nn;
442  }
443 
444  ixd0 = XtoSVG(xy[0].GetX());
445  iyd0 = YtoSVG(xy[0].GetY());
446  if( n <= 1) return;
447 
448  PrintFast(2," m");
449  idx = 0;
450  idy = 0;
451  for (Int_t i=1;i<n;i++) {
452  ixdi = XtoSVG(xy[i].GetX());
453  iydi = YtoSVG(xy[i].GetY());
454  ix = ixdi - ixd0;
455  iy = iydi - iyd0;
456  ixd0 = ixdi;
457  iyd0 = iydi;
458  if( ix && iy) {
459  if( idx ) { MovePS(idx,0); idx = 0; }
460  if( idy ) { MovePS(0,idy); idy = 0; }
461  MovePS(ix,iy);
462  continue;
463  }
464  if ( ix ) {
465  if( idy ) { MovePS(0,idy); idy = 0; }
466  if( !idx ) { idx = ix; continue;}
467  if( ix*idx > 0 ) {
468  idx += ix;
469  } else {
470  MovePS(idx,0);
471  idx = ix;
472  }
473  continue;
474  }
475  if( iy ) {
476  if( idx ) { MovePS(idx,0); idx = 0; }
477  if( !idy) { idy = iy; continue;}
478  if( iy*idy > 0 ) {
479  idy += iy;
480  } else {
481  MovePS(0,idy);
482  idy = iy;
483  }
484  }
485  }
486  if( idx ) MovePS(idx,0);
487  if( idy ) MovePS(0,idy);
488 
489  if (nn > 0 ) {
490  } else {
491  }
492 }
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 /// Draw a PolyLine in NDC space
496 ///
497 /// Draw a polyline through the points xy.
498 /// --If NN=1 moves only to point x,y.
499 /// --If NN=0 the x,y are written in the SVG file
500 /// according to the current transformation.
501 /// --If NN>0 the line is clipped as a line.
502 /// - If NN<0 the line is clipped as a fill area.
503 
505 {
506  Int_t n, idx, idy;
507  Double_t ixd0, iyd0, ixdi, iydi, ix, iy;
508 
509  if (nn > 0) {
510  n = nn;
511  } else {
512  n = -nn;
513  }
514 
515  ixd0 = UtoSVG(xy[0].GetX());
516  iyd0 = VtoSVG(xy[0].GetY());
517  if( n <= 1) return;
518 
519  idx = 0;
520  idy = 0;
521  for (Int_t i=1;i<n;i++) {
522  ixdi = UtoSVG(xy[i].GetX());
523  iydi = VtoSVG(xy[i].GetY());
524  ix = ixdi - ixd0;
525  iy = iydi - iyd0;
526  ixd0 = ixdi;
527  iyd0 = iydi;
528  if( ix && iy) {
529  if( idx ) { MovePS(idx,0); idx = 0; }
530  if( idy ) { MovePS(0,idy); idy = 0; }
531  MovePS(ix,iy);
532  continue;
533  }
534  if ( ix ) {
535  if( idy ) { MovePS(0,idy); idy = 0; }
536  if( !idx ) { idx = ix; continue;}
537  if( ix*idx > 0 ) {
538  idx += ix;
539  } else {
540  MovePS(idx,0);
541  idx = ix;
542  }
543  continue;
544  }
545  if( iy ) {
546  if( idx ) { MovePS(idx,0); idx = 0; }
547  if( !idy) { idy = iy; continue;}
548  if( iy*idy > 0 ) {
549  idy += iy;
550  } else {
551  MovePS(0,idy);
552  idy = iy;
553  }
554  }
555  }
556  if( idx ) MovePS(idx,0);
557  if( idy ) MovePS(0,idy);
558 
559  if (nn > 0 ) {
560  if (xy[0].GetX() == xy[n-1].GetX() && xy[0].GetY() == xy[n-1].GetY()) PrintFast(3," cl");
561  } else {
562  }
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 /// Paint PolyMarker
567 
569 {
570  Int_t ms = abs(fMarkerStyle);
571 
572  if (ms >= 6 && ms <= 19) ms = 20;
573  if (ms == 4) ms = 24;
574 
575  // Define the marker size
576  Float_t msize = fMarkerSize;
577  if (fMarkerStyle == 1) msize = 0.01;
578  if (fMarkerStyle == 6) msize = 0.02;
579  if (fMarkerStyle == 7) msize = 0.04;
580 
581  const Int_t kBASEMARKER = 8;
582  Float_t sbase = msize*kBASEMARKER;
583  Float_t s2x = sbase / Float_t(gPad->GetWw() * gPad->GetAbsWNDC());
584  msize = this->UtoSVG(s2x) - this->UtoSVG(0);
585 
586  Double_t m = msize;
587  Double_t m2 = m/2;
588  Double_t m3 = m/3;
589  Double_t m6 = m/6;
590 
591  // Draw the marker according to the type
592  PrintStr("@");
593  if ((ms > 19 && ms < 24) || ms == 29 || ms == 33 || ms == 34) {
594  PrintStr("<g stroke=");
596  PrintStr(" stroke-width=\"");
598  PrintStr("\" fill=");
600  PrintStr(">");
601  } else {
602  PrintStr("<g stroke=");
604  PrintStr(" stroke-width=\"");
606  PrintStr("\" fill=\"none\"");
607  PrintStr(">");
608  }
609  Double_t ix,iy;
610  for (Int_t i=0;i<n;i++) {
611  ix = XtoSVG(xw[i]);
612  iy = YtoSVG(yw[i]);
613  PrintStr("@");
614  // Dot (.)
615  if (ms == 1) {
616  PrintStr("<line x1=\"");
617  WriteReal(ix-1, kFALSE);
618  PrintStr("\" y1=\"");
619  WriteReal(iy, kFALSE);
620  PrintStr("\" x2=\"");
621  WriteReal(ix, kFALSE);
622  PrintStr("\" y2=\"");
623  WriteReal(iy, kFALSE);
624  PrintStr("\"/>");
625  // Plus (+)
626  } else if (ms == 2) {
627  PrintStr("<line x1=\"");
628  WriteReal(ix-m2, kFALSE);
629  PrintStr("\" y1=\"");
630  WriteReal(iy, kFALSE);
631  PrintStr("\" x2=\"");
632  WriteReal(ix+m2, kFALSE);
633  PrintStr("\" y2=\"");
634  WriteReal(iy, kFALSE);
635  PrintStr("\"/>");
636 
637  PrintStr("<line x1=\"");
638  WriteReal(ix, kFALSE);
639  PrintStr("\" y1=\"");
640  WriteReal(iy-m2, kFALSE);
641  PrintStr("\" x2=\"");
642  WriteReal(ix, kFALSE);
643  PrintStr("\" y2=\"");
644  WriteReal(iy+m2, kFALSE);
645  PrintStr("\"/>");
646  // X shape (X)
647  } else if (ms == 5) {
648  PrintStr("<line x1=\"");
649  WriteReal(ix-m2, kFALSE);
650  PrintStr("\" y1=\"");
651  WriteReal(iy-m2, kFALSE);
652  PrintStr("\" x2=\"");
653  WriteReal(ix+m2, kFALSE);
654  PrintStr("\" y2=\"");
655  WriteReal(iy+m2, kFALSE);
656  PrintStr("\"/>");
657 
658  PrintStr("<line x1=\"");
659  WriteReal(ix-m2, kFALSE);
660  PrintStr("\" y1=\"");
661  WriteReal(iy+m2, kFALSE);
662  PrintStr("\" x2=\"");
663  WriteReal(ix+m2, kFALSE);
664  PrintStr("\" y2=\"");
665  WriteReal(iy-m2, kFALSE);
666  PrintStr("\"/>");
667  // Asterisk shape (*)
668  } else if (ms == 3 || ms == 31) {
669  PrintStr("<line x1=\"");
670  WriteReal(ix-m2, kFALSE);
671  PrintStr("\" y1=\"");
672  WriteReal(iy, kFALSE);
673  PrintStr("\" x2=\"");
674  WriteReal(ix+m2, kFALSE);
675  PrintStr("\" y2=\"");
676  WriteReal(iy, kFALSE);
677  PrintStr("\"/>");
678 
679  PrintStr("<line x1=\"");
680  WriteReal(ix, kFALSE);
681  PrintStr("\" y1=\"");
682  WriteReal(iy-m2, kFALSE);
683  PrintStr("\" x2=\"");
684  WriteReal(ix, kFALSE);
685  PrintStr("\" y2=\"");
686  WriteReal(iy+m2, kFALSE);
687  PrintStr("\"/>");
688 
689  PrintStr("<line x1=\"");
690  WriteReal(ix-m2, kFALSE);
691  PrintStr("\" y1=\"");
692  WriteReal(iy-m2, kFALSE);
693  PrintStr("\" x2=\"");
694  WriteReal(ix+m2, kFALSE);
695  PrintStr("\" y2=\"");
696  WriteReal(iy+m2, kFALSE);
697  PrintStr("\"/>");
698 
699  PrintStr("<line x1=\"");
700  WriteReal(ix-m2, kFALSE);
701  PrintStr("\" y1=\"");
702  WriteReal(iy+m2, kFALSE);
703  PrintStr("\" x2=\"");
704  WriteReal(ix+m2, kFALSE);
705  PrintStr("\" y2=\"");
706  WriteReal(iy-m2, kFALSE);
707  PrintStr("\"/>");
708  // Circle
709  } else if (ms == 24 || ms == 20) {
710  PrintStr("<circle cx=\"");
711  WriteReal(ix, kFALSE);
712  PrintStr("\" cy=\"");
713  WriteReal(iy, kFALSE);
714  PrintStr("\" r=\"");
715  if (m2<=0) m2=1;
716  WriteReal(m2, kFALSE);
717  PrintStr("\" fill=\"none\"");
718  PrintStr("/>");
719  // Square
720  } else if (ms == 25 || ms == 21) {
721  PrintStr("<rect x=\"");
722  WriteReal(ix-m2, kFALSE);
723  PrintStr("\" y=\"");
724  WriteReal(iy-m2, kFALSE);
725  PrintStr("\" width=\"");
726  WriteReal(m, kFALSE);
727  PrintStr("\" height=\"");
728  WriteReal(m, kFALSE);
729  PrintStr("\" fill=\"none\"");
730  PrintStr("/>");
731  // Down triangle
732  } else if (ms == 26 || ms == 22) {
733  PrintStr("<polygon points=\"");
734  WriteReal(ix); PrintStr(","); WriteReal(iy-m2);
735  WriteReal(ix+m2); PrintStr(","); WriteReal(iy+m2);
736  WriteReal(ix-m2); PrintStr(","); WriteReal(iy+m2);
737  PrintStr("\"/>");
738  // Up triangle
739  } else if (ms == 23 || ms == 32) {
740  PrintStr("<polygon points=\"");
741  WriteReal(ix-m2); PrintStr(","); WriteReal(iy-m2);
742  WriteReal(ix+m2); PrintStr(","); WriteReal(iy-m2);
743  WriteReal(ix); PrintStr(","); WriteReal(iy+m2);
744  PrintStr("\"/>");
745  // Diamond
746  } else if (ms == 27 || ms == 33) {
747  PrintStr("<polygon points=\"");
748  WriteReal(ix); PrintStr(","); WriteReal(iy-m2);
749  WriteReal(ix+m3); PrintStr(","); WriteReal(iy);
750  WriteReal(ix); PrintStr(","); WriteReal(iy+m2);
751  WriteReal(ix-m3); PrintStr(","); WriteReal(iy);
752  PrintStr("\"/>");
753  // Cross
754  } else if (ms == 28 || ms == 34) {
755  PrintStr("<polygon points=\"");
756  WriteReal(ix-m6); PrintStr(","); WriteReal(iy-m6);
757  WriteReal(ix-m6); PrintStr(","); WriteReal(iy-m2);
758  WriteReal(ix+m6); PrintStr(","); WriteReal(iy-m2);
759  WriteReal(ix+m6); PrintStr(","); WriteReal(iy-m6);
760  WriteReal(ix+m2); PrintStr(","); WriteReal(iy-m6);
761  WriteReal(ix+m2); PrintStr(","); WriteReal(iy+m6);
762  WriteReal(ix+m6); PrintStr(","); WriteReal(iy+m6);
763  WriteReal(ix+m6); PrintStr(","); WriteReal(iy+m2);
764  WriteReal(ix-m6); PrintStr(","); WriteReal(iy+m2);
765  WriteReal(ix-m6); PrintStr(","); WriteReal(iy+m6);
766  WriteReal(ix-m2); PrintStr(","); WriteReal(iy+m6);
767  WriteReal(ix-m2); PrintStr(","); WriteReal(iy-m6);
768  PrintStr("\"/>");
769  } else if (ms == 29 || ms == 30) {
770  PrintStr("<polygon points=\"");
771  WriteReal(ix); PrintStr(","); WriteReal(iy+m2);
772  WriteReal(ix+0.112255*m); PrintStr(","); WriteReal(iy+0.15451*m);
773  WriteReal(ix+0.47552*m); PrintStr(","); WriteReal(iy+0.15451*m);
774  WriteReal(ix+0.181635*m); PrintStr(","); WriteReal(iy-0.05902*m);
775  WriteReal(ix+0.29389*m); PrintStr(","); WriteReal(iy-0.40451*m);
776  WriteReal(ix); PrintStr(","); WriteReal(iy-0.19098*m);
777  WriteReal(ix-0.29389*m); PrintStr(","); WriteReal(iy-0.40451*m);
778  WriteReal(ix-0.181635*m); PrintStr(","); WriteReal(iy-0.05902*m);
779  WriteReal(ix-0.47552*m); PrintStr(","); WriteReal(iy+0.15451*m);
780  WriteReal(ix-0.112255*m); PrintStr(","); WriteReal(iy+0.15451*m);
781  PrintStr("\"/>");
782  } else {
783  PrintStr("<line x1=\"");
784  WriteReal(ix-1, kFALSE);
785  PrintStr("\" y1=\"");
786  WriteReal(iy, kFALSE);
787  PrintStr("\" x2=\"");
788  WriteReal(ix, kFALSE);
789  PrintStr("\" y2=\"");
790  WriteReal(iy, kFALSE);
791  PrintStr("\"/>");
792  }
793  }
794  PrintStr("@");
795  PrintStr("</g>");
796 }
797 
798 ////////////////////////////////////////////////////////////////////////////////
799 /// Paint PolyMarker
800 
802 {
803  Int_t ms = abs(fMarkerStyle);
804 
805  if (ms >= 6 && ms <= 19) ms = 20;
806  if (ms == 4) ms = 24;
807 
808  // Define the marker size
809  Float_t msize = fMarkerSize;
810  if (fMarkerStyle == 1) msize = 0.01;
811  if (fMarkerStyle == 6) msize = 0.02;
812  if (fMarkerStyle == 7) msize = 0.04;
813 
814  const Int_t kBASEMARKER = 8;
815  Float_t sbase = msize*kBASEMARKER;
816  Float_t s2x = sbase / Float_t(gPad->GetWw() * gPad->GetAbsWNDC());
817  msize = this->UtoSVG(s2x) - this->UtoSVG(0);
818 
819  Double_t m = msize;
820  Double_t m2 = m/2;
821  Double_t m3 = m/3;
822  Double_t m6 = m/6;
823 
824  // Draw the marker according to the type
825  PrintStr("@");
826  if ((ms > 19 && ms < 24) || ms == 29 || ms == 33 || ms == 34) {
827  PrintStr("<g stroke=");
829  PrintStr(" stroke-width=\"");
831  PrintStr("\" fill=");
833  PrintStr(">");
834  } else {
835  PrintStr("<g stroke=");
837  PrintStr(" stroke-width=\"");
839  PrintStr("\" fill=\"none\"");
840  PrintStr(">");
841  }
842  Double_t ix,iy;
843  for (Int_t i=0;i<n;i++) {
844  ix = XtoSVG(xw[i]);
845  iy = YtoSVG(yw[i]);
846  PrintStr("@");
847  // Dot (.)
848  if (ms == 1) {
849  PrintStr("<line x1=\"");
850  WriteReal(ix-1, kFALSE);
851  PrintStr("\" y1=\"");
852  WriteReal(iy, kFALSE);
853  PrintStr("\" x2=\"");
854  WriteReal(ix, kFALSE);
855  PrintStr("\" y2=\"");
856  WriteReal(iy, kFALSE);
857  PrintStr("\"/>");
858  // Plus (+)
859  } else if (ms == 2) {
860  PrintStr("<line x1=\"");
861  WriteReal(ix-m2, kFALSE);
862  PrintStr("\" y1=\"");
863  WriteReal(iy, kFALSE);
864  PrintStr("\" x2=\"");
865  WriteReal(ix+m2, kFALSE);
866  PrintStr("\" y2=\"");
867  WriteReal(iy, kFALSE);
868  PrintStr("\"/>");
869 
870  PrintStr("<line x1=\"");
871  WriteReal(ix, kFALSE);
872  PrintStr("\" y1=\"");
873  WriteReal(iy-m2, kFALSE);
874  PrintStr("\" x2=\"");
875  WriteReal(ix, kFALSE);
876  PrintStr("\" y2=\"");
877  WriteReal(iy+m2, kFALSE);
878  PrintStr("\"/>");
879  // X shape (X)
880  } else if (ms == 5) {
881  PrintStr("<line x1=\"");
882  WriteReal(ix-m2, kFALSE);
883  PrintStr("\" y1=\"");
884  WriteReal(iy-m2, kFALSE);
885  PrintStr("\" x2=\"");
886  WriteReal(ix+m2, kFALSE);
887  PrintStr("\" y2=\"");
888  WriteReal(iy+m2, kFALSE);
889  PrintStr("\"/>");
890 
891  PrintStr("<line x1=\"");
892  WriteReal(ix-m2, kFALSE);
893  PrintStr("\" y1=\"");
894  WriteReal(iy+m2, kFALSE);
895  PrintStr("\" x2=\"");
896  WriteReal(ix+m2, kFALSE);
897  PrintStr("\" y2=\"");
898  WriteReal(iy-m2, kFALSE);
899  PrintStr("\"/>");
900  // Asterisk shape (*)
901  } else if (ms == 3 || ms == 31) {
902  PrintStr("<line x1=\"");
903  WriteReal(ix-m2, kFALSE);
904  PrintStr("\" y1=\"");
905  WriteReal(iy, kFALSE);
906  PrintStr("\" x2=\"");
907  WriteReal(ix+m2, kFALSE);
908  PrintStr("\" y2=\"");
909  WriteReal(iy, kFALSE);
910  PrintStr("\"/>");
911 
912  PrintStr("<line x1=\"");
913  WriteReal(ix, kFALSE);
914  PrintStr("\" y1=\"");
915  WriteReal(iy-m2, kFALSE);
916  PrintStr("\" x2=\"");
917  WriteReal(ix, kFALSE);
918  PrintStr("\" y2=\"");
919  WriteReal(iy+m2, kFALSE);
920  PrintStr("\"/>");
921 
922  PrintStr("<line x1=\"");
923  WriteReal(ix-m2, kFALSE);
924  PrintStr("\" y1=\"");
925  WriteReal(iy-m2, kFALSE);
926  PrintStr("\" x2=\"");
927  WriteReal(ix+m2, kFALSE);
928  PrintStr("\" y2=\"");
929  WriteReal(iy+m2, kFALSE);
930  PrintStr("\"/>");
931 
932  PrintStr("<line x1=\"");
933  WriteReal(ix-m2, kFALSE);
934  PrintStr("\" y1=\"");
935  WriteReal(iy+m2, kFALSE);
936  PrintStr("\" x2=\"");
937  WriteReal(ix+m2, kFALSE);
938  PrintStr("\" y2=\"");
939  WriteReal(iy-m2, kFALSE);
940  PrintStr("\"/>");
941  // Circle
942  } else if (ms == 24 || ms == 20) {
943  PrintStr("<circle cx=\"");
944  WriteReal(ix, kFALSE);
945  PrintStr("\" cy=\"");
946  WriteReal(iy, kFALSE);
947  PrintStr("\" r=\"");
948  if (m2<=0) m2=1;
949  WriteReal(m2, kFALSE);
950  PrintStr("\"/>");
951  // Square
952  } else if (ms == 25 || ms == 21) {
953  PrintStr("<rect x=\"");
954  WriteReal(ix-m2, kFALSE);
955  PrintStr("\" y=\"");
956  WriteReal(iy-m2, kFALSE);
957  PrintStr("\" width=\"");
958  WriteReal(m, kFALSE);
959  PrintStr("\" height=\"");
960  WriteReal(m, kFALSE);
961  PrintStr("\"/>");
962  // Down triangle
963  } else if (ms == 26 || ms == 22) {
964  PrintStr("<polygon points=\"");
965  WriteReal(ix); PrintStr(","); WriteReal(iy-m2);
966  WriteReal(ix+m2); PrintStr(","); WriteReal(iy+m2);
967  WriteReal(ix-m2); PrintStr(","); WriteReal(iy+m2);
968  PrintStr("\"/>");
969  // Up triangle
970  } else if (ms == 23 || ms == 32) {
971  PrintStr("<polygon points=\"");
972  WriteReal(ix-m2); PrintStr(","); WriteReal(iy-m2);
973  WriteReal(ix+m2); PrintStr(","); WriteReal(iy-m2);
974  WriteReal(ix); PrintStr(","); WriteReal(iy+m2);
975  PrintStr("\"/>");
976  // Diamond
977  } else if (ms == 27 || ms == 33) {
978  PrintStr("<polygon points=\"");
979  WriteReal(ix); PrintStr(","); WriteReal(iy-m2);
980  WriteReal(ix+m3); PrintStr(","); WriteReal(iy);
981  WriteReal(ix); PrintStr(","); WriteReal(iy+m2);
982  WriteReal(ix-m3); PrintStr(","); WriteReal(iy);
983  PrintStr("\"/>");
984  // Cross
985  } else if (ms == 28 || ms == 34) {
986  PrintStr("<polygon points=\"");
987  WriteReal(ix-m6); PrintStr(","); WriteReal(iy-m6);
988  WriteReal(ix-m6); PrintStr(","); WriteReal(iy-m2);
989  WriteReal(ix+m6); PrintStr(","); WriteReal(iy-m2);
990  WriteReal(ix+m6); PrintStr(","); WriteReal(iy-m6);
991  WriteReal(ix+m2); PrintStr(","); WriteReal(iy-m6);
992  WriteReal(ix+m2); PrintStr(","); WriteReal(iy+m6);
993  WriteReal(ix+m6); PrintStr(","); WriteReal(iy+m6);
994  WriteReal(ix+m6); PrintStr(","); WriteReal(iy+m2);
995  WriteReal(ix-m6); PrintStr(","); WriteReal(iy+m2);
996  WriteReal(ix-m6); PrintStr(","); WriteReal(iy+m6);
997  WriteReal(ix-m2); PrintStr(","); WriteReal(iy+m6);
998  WriteReal(ix-m2); PrintStr(","); WriteReal(iy-m6);
999  PrintStr("\"/>");
1000  } else if (ms == 29 || ms == 30) {
1001  PrintStr("<polygon points=\"");
1002  WriteReal(ix); PrintStr(","); WriteReal(iy+m2);
1003  WriteReal(ix+0.112255*m); PrintStr(","); WriteReal(iy+0.15451*m);
1004  WriteReal(ix+0.47552*m); PrintStr(","); WriteReal(iy+0.15451*m);
1005  WriteReal(ix+0.181635*m); PrintStr(","); WriteReal(iy-0.05902*m);
1006  WriteReal(ix+0.29389*m); PrintStr(","); WriteReal(iy-0.40451*m);
1007  WriteReal(ix); PrintStr(","); WriteReal(iy-0.19098*m);
1008  WriteReal(ix-0.29389*m); PrintStr(","); WriteReal(iy-0.40451*m);
1009  WriteReal(ix-0.181635*m); PrintStr(","); WriteReal(iy-0.05902*m);
1010  WriteReal(ix-0.47552*m); PrintStr(","); WriteReal(iy+0.15451*m);
1011  WriteReal(ix-0.112255*m); PrintStr(","); WriteReal(iy+0.15451*m);
1012  PrintStr("\"/>");
1013  } else {
1014  PrintStr("<line x1=\"");
1015  WriteReal(ix-1, kFALSE);
1016  PrintStr("\" y1=\"");
1017  WriteReal(iy, kFALSE);
1018  PrintStr("\" x2=\"");
1019  WriteReal(ix, kFALSE);
1020  PrintStr("\" y2=\"");
1021  WriteReal(iy, kFALSE);
1022  PrintStr("\"/>");
1023  }
1024  }
1025  PrintStr("@");
1026  PrintStr("</g>");
1027 }
1028 
1029 ////////////////////////////////////////////////////////////////////////////////
1030 /// This function defines a path with xw and yw and draw it according the
1031 /// value of nn:
1032 ///
1033 /// - If nn>0 a line is drawn.
1034 /// - If nn<0 a closed polygon is drawn.
1035 
1037 {
1038  Int_t n, fais, fasi;
1039  Double_t ixd0, iyd0, idx, idy, ixdi, iydi, ix, iy;
1040  fais = fasi = 0;
1041 
1042  if (nn > 0) {
1043  if (fLineWidth<=0) return;
1044  n = nn;
1045  } else {
1046  n = -nn;
1047  fais = fFillStyle/1000;
1048  fasi = fFillStyle%1000;
1049  if (fais == 3 || fais == 2) {
1050  if (fasi > 100 && fasi <125) {
1051  return;
1052  }
1053  if (fasi > 0 && fasi < 26) {
1054  }
1055  }
1056  }
1057 
1058  if( n <= 1) {
1059  Error("DrawPS", "Two points are needed");
1060  return;
1061  }
1062 
1063  ixd0 = XtoSVG(xw[0]);
1064  iyd0 = YtoSVG(yw[0]);
1065 
1066  PrintStr("@");
1067  PrintFast(10,"<path d=\"M");
1068  WriteReal(ixd0, kFALSE);
1069  PrintFast(1,",");
1070  WriteReal(iyd0, kFALSE);
1071 
1072  idx = idy = 0;
1073  for (Int_t i=1;i<n;i++) {
1074  ixdi = XtoSVG(xw[i]);
1075  iydi = YtoSVG(yw[i]);
1076  ix = ixdi - ixd0;
1077  iy = iydi - iyd0;
1078  ixd0 = ixdi;
1079  iyd0 = iydi;
1080  if( ix && iy) {
1081  if( idx ) { MovePS(idx,0); idx = 0; }
1082  if( idy ) { MovePS(0,idy); idy = 0; }
1083  MovePS(ix,iy);
1084  } else if ( ix ) {
1085  if( idy ) { MovePS(0,idy); idy = 0;}
1086  if( !idx ) { idx = ix;}
1087  else if( TMath::Sign(ix,idx) == ix ) idx += ix;
1088  else { MovePS(idx,0); idx = ix;}
1089  } else if( iy ) {
1090  if( idx ) { MovePS(idx,0); idx = 0;}
1091  if( !idy) { idy = iy;}
1092  else if( TMath::Sign(iy,idy) == iy) idy += iy;
1093  else { MovePS(0,idy); idy = iy;}
1094  }
1095  }
1096  if (idx) MovePS(idx,0);
1097  if (idy) MovePS(0,idy);
1098 
1099  if (nn > 0 ) {
1100  if (xw[0] == xw[n-1] && yw[0] == yw[n-1]) PrintFast(1,"z");
1101  PrintFast(21,"\" fill=\"none\" stroke=");
1103  if(fLineWidth > 1.) {
1104  PrintFast(15," stroke-width=\"");
1106  PrintFast(1,"\"");
1107  }
1108  if (fLineStyle > 1) {
1109  PrintFast(19," stroke-dasharray=\"");
1111  TObjArray *tokens = st.Tokenize(" ");
1112  for (Int_t j = 0; j<tokens->GetEntries(); j++) {
1113  Int_t it;
1114  sscanf(((TObjString*)tokens->At(j))->GetName(), "%d", &it);
1115  if (j>0) PrintFast(1,",");
1116  WriteReal(it/4);
1117  }
1118  delete tokens;
1119  PrintFast(1,"\"");
1120  }
1121  PrintFast(2,"/>");
1122  } else {
1123  PrintFast(8,"z\" fill=");
1124  if (fais == 0) {
1125  PrintFast(14,"\"none\" stroke=");
1127  } else {
1129  }
1130  PrintFast(2,"/>");
1131  }
1132 }
1133 
1134 ////////////////////////////////////////////////////////////////////////////////
1135 /// Initialize the SVG file. The main task of the function is to output the
1136 /// SVG header file which consist in <title>, <desc> and <defs>. The
1137 /// HeaderPS provided by the user program is written in the <defs> part.
1138 
1140 {
1141  // Title
1142  PrintStr("<title>@");
1143  PrintStr(GetName());
1144  PrintStr("@");
1145  PrintStr("</title>@");
1146 
1147  // Description
1148  PrintStr("<desc>@");
1149  PrintFast(22,"Creator: ROOT Version ");
1150  PrintStr(gROOT->GetVersion());
1151  PrintStr("@");
1152  PrintFast(14,"CreationDate: ");
1153  TDatime t;
1154  PrintStr(t.AsString());
1155  //Check a special header is defined in the current style
1156  Int_t nh = strlen(gStyle->GetHeaderPS());
1157  if (nh) {
1158  PrintFast(nh,gStyle->GetHeaderPS());
1159  }
1160  PrintStr("</desc>@");
1161 
1162  // Definitions
1163  PrintStr("<defs>@");
1164  PrintStr("</defs>@");
1165 
1166 }
1167 
1168 ////////////////////////////////////////////////////////////////////////////////
1169 /// Move to a new position (ix, iy). The move is done in relative coordinates
1170 /// which allows to have short numbers which decrease the size of the file.
1171 /// This function use the full power of the SVG's paths by using the
1172 /// horizontal and vertical move whenever it is possible.
1173 
1175 {
1176  if (ix != 0 && iy != 0) {
1177  PrintFast(1,"l");
1178  WriteReal(ix);
1179  PrintFast(1,",");
1180  WriteReal(iy);
1181  } else if (ix != 0) {
1182  PrintFast(1,"h");
1183  WriteReal(ix);
1184  } else if (iy != 0) {
1185  PrintFast(1,"v");
1186  WriteReal(iy);
1187  }
1188 }
1189 
1190 ////////////////////////////////////////////////////////////////////////////////
1191 /// Start the SVG page. This function initialize the pad conversion
1192 /// coefficients and output the <svg> directive which is close later in the
1193 /// the function Close.
1194 
1196 {
1197  // Compute pad conversion coefficients
1198  if (gPad) {
1199  Double_t ww = gPad->GetWw();
1200  Double_t wh = gPad->GetWh();
1201  fYsize = fXsize*wh/ww;
1202  } else {
1203  fYsize = 27;
1204  }
1205 
1206  // <svg> directive. It defines the viewBox.
1207  if(!fBoundingBox) {
1208  PrintStr("@<?xml version=\"1.0\" standalone=\"no\"?>");
1209  PrintStr("@<svg width=\"");
1211  PrintStr("\" height=\"");
1214  PrintStr("\" viewBox=\"0 0");
1217  PrintStr("\" xmlns=\"http://www.w3.org/2000/svg\">");
1218  PrintStr("@");
1219  Initialize();
1220  fBoundingBox = kTRUE;
1221  }
1222 }
1223 
1224 ////////////////////////////////////////////////////////////////////////////////
1225 /// Set the range for the paper in centimetres
1226 
1227 void TSVG::Range(Float_t xsize, Float_t ysize)
1228 {
1229  Float_t xps, yps, xncm, yncm, dxwn, dywn, xwkwn, ywkwn, xymax;
1230 
1231  fXsize = xsize;
1232  fYsize = ysize;
1233 
1234  xps = xsize;
1235  yps = ysize;
1236 
1237  if( xsize <= xps && ysize < yps) {
1238  if ( xps > yps ) xymax = xps;
1239  else xymax = yps;
1240  xncm = xsize/xymax;
1241  yncm = ysize/xymax;
1242  dxwn = ((xps/xymax)-xncm)/2;
1243  dywn = ((yps/xymax)-yncm)/2;
1244  } else {
1245  if (xps/yps < 1) xwkwn = xps/yps;
1246  else xwkwn = 1;
1247  if (yps/xps < 1) ywkwn = yps/xps;
1248  else ywkwn = 1;
1249 
1250  if (xsize < ysize) {
1251  xncm = ywkwn*xsize/ysize;
1252  yncm = ywkwn;
1253  dxwn = (xwkwn-xncm)/2;
1254  dywn = 0;
1255  if( dxwn < 0) {
1256  xncm = xwkwn;
1257  dxwn = 0;
1258  yncm = xwkwn*ysize/xsize;
1259  dywn = (ywkwn-yncm)/2;
1260  }
1261  } else {
1262  xncm = xwkwn;
1263  yncm = xwkwn*ysize/xsize;
1264  dxwn = 0;
1265  dywn = (ywkwn-yncm)/2;
1266  if( dywn < 0) {
1267  yncm = ywkwn;
1268  dywn = 0;
1269  xncm = ywkwn*xsize/ysize;
1270  dxwn = (xwkwn-xncm)/2;
1271  }
1272  }
1273  }
1274  fRange = kTRUE;
1275 }
1276 
1277 ////////////////////////////////////////////////////////////////////////////////
1278 /// Set color index for fill areas
1279 
1281 {
1282  fFillColor = cindex;
1283  if (gStyle->GetFillColor() <= 0) cindex = 0;
1284 }
1285 
1286 ////////////////////////////////////////////////////////////////////////////////
1287 /// Set color index for lines
1288 
1290 {
1291  fLineColor = cindex;
1292 }
1293 
1294 ////////////////////////////////////////////////////////////////////////////////
1295 /// Change the line style
1296 ///
1297 /// - linestyle = 2 dashed
1298 /// - linestyle = 3 dotted
1299 /// - linestyle = 4 dash-dotted
1300 /// - linestyle = else solid (1 in is used most of the time)
1301 
1303 {
1304  fLineStyle = linestyle;
1305 }
1306 
1307 ////////////////////////////////////////////////////////////////////////////////
1308 /// Set the lines width.
1309 
1311 {
1312  fLineWidth = linewidth;
1313 }
1314 
1315 ////////////////////////////////////////////////////////////////////////////////
1316 /// Set color index for markers.
1317 
1319 {
1320  fMarkerColor = cindex;
1321 }
1322 
1323 ////////////////////////////////////////////////////////////////////////////////
1324 /// Set color with its color index
1325 
1327 {
1328  if (color < 0) color = 0;
1329  TColor *col = gROOT->GetColor(color);
1330  if (col) {
1331  SetColor(col->GetRed(), col->GetGreen(), col->GetBlue());
1332  Float_t a = col->GetAlpha();
1333  if (a<1.) PrintStr(Form(" fill-opacity=\"%3.2f\" stroke-opacity=\"%3.2f\"",a,a));
1334  } else {
1335  SetColor(1., 1., 1.);
1336  }
1337 }
1338 
1339 ////////////////////////////////////////////////////////////////////////////////
1340 /// Set color with its R G B components
1341 ///
1342 /// - r: % of red in [0,1]
1343 /// --g: % of green in [0,1]
1344 /// - b: % of blue in [0,1]
1345 
1347 {
1348  if (r <= 0. && g <= 0. && b <= 0. ) {
1349  PrintFast(7,"\"black\"");
1350  } else if (r >= 1. && g >= 1. && b >= 1. ) {
1351  PrintFast(7,"\"white\"");
1352  } else {
1353  char str[12];
1354  snprintf(str,12,"\"#%2.2x%2.2x%2.2x\"",Int_t(255.*r)
1355  ,Int_t(255.*g)
1356  ,Int_t(255.*b));
1357  PrintStr(str);
1358  }
1359 }
1360 
1361 ////////////////////////////////////////////////////////////////////////////////
1362 /// Set color index for text
1363 
1365 {
1366  fTextColor = cindex;
1367 }
1368 
1369 ////////////////////////////////////////////////////////////////////////////////
1370 /// Draw text
1371 ///
1372 /// - xx: x position of the text
1373 /// - yy: y position of the text
1374 /// - chars: text to be drawn
1375 
1376 void TSVG::Text(Double_t xx, Double_t yy, const char *chars)
1377 {
1378  static const char *fontFamily[] = {
1379  "Times" , "Times" , "Times",
1380  "Helvetica", "Helvetica", "Helvetica" , "Helvetica",
1381  "Courier" , "Courier" , "Courier" , "Courier",
1382  "Times" ,"Times" , "ZapfDingbats", "Times"};
1383 
1384  static const char *fontWeight[] = {
1385  "normal", "bold", "bold",
1386  "normal", "normal", "bold" , "bold",
1387  "normal", "normal", "bold" , "bold",
1388  "normal", "normal", "normal", "normal"};
1389 
1390  static const char *fontStyle[] = {
1391  "italic", "normal" , "italic",
1392  "normal", "oblique", "normal", "oblique",
1393  "normal", "oblique", "normal", "oblique",
1394  "normal", "normal" , "normal", "italic"};
1395 
1396  Double_t ix = XtoSVG(xx);
1397  Double_t iy = YtoSVG(yy);
1398  Double_t txalh = fTextAlign/10;
1399  if (txalh <1) txalh = 1; else if (txalh > 3) txalh = 3;
1400  Double_t txalv = fTextAlign%10;
1401  if (txalv <1) txalv = 1; else if (txalv > 3) txalv = 3;
1402 
1403  Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
1404  Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
1405  Float_t fontrap = 1.09; //scale down compared to X11
1406  Float_t ftsize;
1407 
1408  Int_t font = abs(fTextFont)/10;
1409  if (font > 42 || font < 1) font = 1;
1410  if (wh < hh) {
1411  ftsize = fTextSize*fXsize*gPad->GetAbsWNDC();
1412  } else {
1413  ftsize = fTextSize*fYsize*gPad->GetAbsHNDC();
1414  }
1415  Int_t ifont = font-1;
1416 
1417  Double_t fontsize = CMtoSVG(ftsize/fontrap);
1418  if( fontsize <= 0) return;
1419 
1420  if (txalv == 3) iy = iy+fontsize;
1421  if (txalv == 2) iy = iy+(fontsize/2);
1422 
1423  if (fTextAngle != 0.) {
1424  PrintStr("@");
1425  PrintFast(21,"<g transform=\"rotate(");
1427  PrintFast(1,",");
1428  WriteReal(ix, kFALSE);
1429  PrintFast(1,",");
1430  WriteReal(iy, kFALSE);
1431  PrintFast(3,")\">");
1432  }
1433 
1434  PrintStr("@");
1435  PrintFast(9,"<text x=\"");
1436  WriteReal(ix, kFALSE);
1437  PrintFast(5,"\" y=\"");
1438  WriteReal(iy, kFALSE);
1439  PrintFast(1,"\"");
1440  if (txalh == 2) {
1441  PrintFast(21," text-anchor=\"middle\"");
1442  } else if (txalh == 3) {
1443  PrintFast(18," text-anchor=\"end\"");
1444  }
1445  PrintFast(6," fill=");
1447  PrintFast(12," font-size=\"");
1448  WriteReal(fontsize, kFALSE);
1449  PrintFast(15,"\" font-family=\"");
1450  PrintStr(fontFamily[ifont]);
1451  if (strcmp(fontWeight[ifont],"normal")) {
1452  PrintFast(15,"\" font-weight=\"");
1453  PrintStr(fontWeight[ifont]);
1454  }
1455  if (strcmp(fontStyle[ifont],"normal")) {
1456  PrintFast(14,"\" font-style=\"");
1457  PrintStr(fontStyle[ifont]);
1458  }
1459  PrintFast(2,"\">");
1460  PrintStr("@");
1461 
1462  if (font == 12 || font == 15) {
1463  Int_t ichar = chars[0]+848;
1464  Int_t ic = ichar;
1465 
1466  // Math Symbols (cf: http://www.fileformat.info/info/unicode/category/Sm/list.htm)
1467  if (ic == 755) ichar = 8804;
1468  if (ic == 759) ichar = 9827;
1469  if (ic == 760) ichar = 9830;
1470  if (ic == 761) ichar = 9829;
1471  if (ic == 762) ichar = 9824;
1472  if (ic == 766) ichar = 8594;
1473  if (ic == 776) ichar = 247;
1474  if (ic == 757) ichar = 8734;
1475  if (ic == 758) ichar = 402;
1476  if (ic == 771) ichar = 8805;
1477  if (ic == 774) ichar = 8706;
1478  if (ic == 775) ichar = 8226;
1479  if (ic == 779) ichar = 8776;
1480  if (ic == 805) ichar = 8719;
1481  if (ic == 821) ichar = 8721;
1482  if (ic == 834) ichar = 8747;
1483  if (ic == 769) ichar = 177;
1484  if (ic == 772) ichar = 215;
1485  if (ic == 768) ichar = 176;
1486  if (ic == 791) ichar = 8745;
1487  if (ic == 793) ichar = 8835; // SUPERSET OF
1488  if (ic == 794) ichar = 8839; // SUPERSET OF OR EQUAL TO
1489  if (ic == 795) ichar = 8836; // NOT A SUBSET OF
1490  if (ic == 796) ichar = 8834;
1491  if (ic == 893) ichar = 8722;
1492  if (ic == 803) ichar = 169; // COPYRIGHT SIGN
1493  if (ic == 819) ichar = 169; // COPYRIGHT SIGN
1494  if (ic == 804) ichar = 8482;
1495  if (ic == 770) ichar = 34;
1496  if (ic == 823) ichar = 10072;
1497  if (ic == 781) ichar = 10072;
1498  if (ic == 824) ichar = 9117; // LEFT PARENTHESIS LOWER HOOK
1499  if (ic == 822) ichar = 9115; // LEFT PARENTHESIS UPPER HOOK
1500  if (ic == 767) ichar = 8595; // DOWNWARDS ARROW
1501  if (ic == 763) ichar = 8596; // LEFT RIGHT ARROW
1502  if (ic == 764) ichar = 8592; // LEFTWARDS ARROW
1503  if (ic == 788) ichar = 8855; // CIRCLED TIMES
1504  if (ic == 784) ichar = 8501;
1505  if (ic == 777) ichar = 8800;
1506  if (ic == 797) ichar = 8838;
1507  if (ic == 800) ichar = 8736;
1508  if (ic == 812) ichar = 8656; // LEFTWARDS DOUBLE ARROW
1509  if (ic == 817) ichar = 60; // LESS-THAN SIGN
1510  if (ic == 833) ichar = 62; // GREATER-THAN SIGN
1511  if (ic == 778) ichar = 8803; // STRICTLY EQUIVALENT TO
1512  if (ic == 809) ichar = 8743; // LOGICAL AND
1513  if (ic == 802) ichar = 9415; // CIRCLED LATIN CAPITAL LETTER R
1514  if (ic == 780) ichar = 8230; // HORIZONTAL ELLIPSIS
1515  if (ic == 801) ichar = 8711; // NABLA
1516  if (ic == 783) ichar = 8629; // DOWNWARDS ARROW WITH CORNER LEFTWARDS
1517  if (ic == 782) ichar = 8213;
1518  if (ic == 799) ichar = 8713;
1519  if (ic == 792) ichar = 8746;
1520  if (ic == 828) ichar = 9127;
1521  if (ic == 765) ichar = 8593; // UPWARDS ARROW
1522  if (ic == 789) ichar = 8853; // CIRCLED PLUS
1523  if (ic == 813) ichar = 8657; // UPWARDS DOUBLE ARROW
1524  if (ic == 773) ichar = 8733; // PROPORTIONAL TO
1525  if (ic == 790) ichar = 8709; // EMPTY SET
1526  if (ic == 810) ichar = 8744;
1527  if (ic == 756) ichar = 8260;
1528  if (ic == 807) ichar = 8231;
1529  if (ic == 808) ichar = 8989; // TOP RIGHT CORNER
1530  if (ic == 814) ichar = 8658; // RIGHTWARDS DOUBLE ARROW
1531  if (ic == 806) ichar = 8730; // SQUARE ROOT
1532  if (ic == 827) ichar = 9123;
1533  if (ic == 829) ichar = 9128;
1534  if (ic == 786) ichar = 8476;
1535  if (ic == 785) ichar = 8465;
1536  if (ic == 787) ichar = 8472;
1537 
1538  // Greek characters
1539  if (ic == 918) ichar = 934;
1540  if (ic == 919) ichar = 915;
1541  if (ic == 920) ichar = 919;
1542  if (ic == 923) ichar = 922;
1543  if (ic == 924) ichar = 923;
1544  if (ic == 925) ichar = 924;
1545  if (ic == 926) ichar = 925;
1546  if (ic == 929) ichar = 920;
1547  if (ic == 930) ichar = 929;
1548  if (ic == 936) ichar = 926;
1549  if (ic == 915) ichar = 935;
1550  if (ic == 937) ichar = 936;
1551  if (ic == 935) ichar = 937;
1552  if (ic == 938) ichar = 918;
1553  if (ic == 951) ichar = 947;
1554  if (ic == 798) ichar = 949;
1555  if (ic == 970) ichar = 950;
1556  if (ic == 952) ichar = 951;
1557  if (ic == 961) ichar = 952;
1558  if (ic == 955) ichar = 954;
1559  if (ic == 956) ichar = 955;
1560  if (ic == 957) ichar = 956;
1561  if (ic == 958) ichar = 957;
1562  if (ic == 968) ichar = 958;
1563  if (ic == 934) ichar = 962;
1564  if (ic == 962) ichar = 961;
1565  if (ic == 966) ichar = 969;
1566  if (ic == 950) ichar = 966;
1567  if (ic == 947) ichar = 967;
1568  if (ic == 969) ichar = 968;
1569  if (ic == 967) ichar = 969;
1570  if (ic == 954) ichar = 966;
1571  if (ic == 922) ichar = 952;
1572  if (ic == 753) ichar = 965;
1573  PrintStr(Form("&#%4.4d;",ichar));
1574  } else {
1575  Int_t len=strlen(chars);
1576  for (Int_t i=0; i<len;i++) {
1577  if (chars[i]!='\n') {
1578  if (chars[i]=='<') {
1579  PrintFast(4,"&lt;");
1580  } else if (chars[i]=='>') {
1581  PrintFast(4,"&gt;");
1582  } else if (chars[i]=='\305') {
1583  PrintFast(7,"&#8491;"); // ANGSTROM SIGN
1584  } else if (chars[i]=='\345') {
1585  PrintFast(6,"&#229;");
1586  } else if (chars[i]=='&') {
1587  PrintFast(5,"&amp;");
1588  } else {
1589  PrintFast(1,&chars[i]);
1590  }
1591  }
1592  }
1593  }
1594  PrintStr("@");
1595  PrintFast(7,"</text>");
1596 
1597  if (fTextAngle != 0.) {
1598  PrintStr("@");
1599  PrintFast(4,"</g>");
1600  }
1601 }
1602 
1603 ////////////////////////////////////////////////////////////////////////////////
1604 /// Write a string of characters in NDC
1605 
1606 void TSVG::TextNDC(Double_t u, Double_t v, const char *chars)
1607 {
1608  Double_t x = gPad->GetX1() + u*(gPad->GetX2() - gPad->GetX1());
1609  Double_t y = gPad->GetY1() + v*(gPad->GetY2() - gPad->GetY1());
1610  Text(x, y, chars);
1611 }
1612 
1613 ////////////////////////////////////////////////////////////////////////////////
1614 /// Convert U from NDC coordinate to SVG
1615 
1617 {
1618  Double_t cm = fXsize*(gPad->GetAbsXlowNDC() + u*gPad->GetAbsWNDC());
1619  return 0.5 + 72*cm/2.54;
1620 }
1621 
1622 ////////////////////////////////////////////////////////////////////////////////
1623 /// Convert V from NDC coordinate to SVG
1624 
1626 {
1627  Double_t cm = fYsize*(gPad->GetAbsYlowNDC() + v*gPad->GetAbsHNDC());
1628  return 0.5 + 72*cm/2.54;
1629 }
1630 
1631 ////////////////////////////////////////////////////////////////////////////////
1632 /// Convert X from world coordinate to SVG
1633 
1635 {
1636  Double_t u = (x - gPad->GetX1())/(gPad->GetX2() - gPad->GetX1());
1637  return UtoSVG(u);
1638 }
1639 
1640 ////////////////////////////////////////////////////////////////////////////////
1641 /// Convert Y from world coordinate to SVG
1642 
1644 {
1645  Double_t v = (y - gPad->GetY1())/(gPad->GetY2() - gPad->GetY1());
1646  return fYsizeSVG-VtoSVG(v);
1647 }
1648 
1649 ////////////////////////////////////////////////////////////////////////////////
1650 /// Begin the Cell Array painting
1651 
1653  Double_t)
1654 {
1655  Warning("TSVG::CellArrayBegin", "not yet implemented");
1656 }
1657 
1658 ////////////////////////////////////////////////////////////////////////////////
1659 /// Paint the Cell Array
1660 
1662 {
1663  Warning("TSVG::CellArrayFill", "not yet implemented");
1664 }
1665 
1666 ////////////////////////////////////////////////////////////////////////////////
1667 /// End the Cell Array painting
1668 
1670 {
1671  Warning("TSVG::CellArrayEnd", "not yet implemented");
1672 }
1673 
1674 ////////////////////////////////////////////////////////////////////////////////
1675 /// Not needed in SVG case
1676 
1678 {
1679  Warning("TSVG::DrawPS", "not yet implemented");
1680 }
void SetLineColor(Color_t cindex=1)
Set color index for lines.
Definition: TSVG.cxx:1289
const char * GetLineStyleString(Int_t i=1) const
Return line style string (used by PostScript).
Definition: TStyle.cxx:787
const char * GetHeaderPS() const
Definition: TStyle.h:292
char * fBuffer
Definition: TVirtualPS.h:52
An array of TObjects.
Definition: TObjArray.h:39
void On()
Activate an already open SVG file.
Definition: TSVG.cxx:181
T1 Sign(T1 a, T2 b)
Definition: TMathBase.h:155
short Style_t
Definition: RtypesCore.h:76
Double_t UtoSVG(Double_t u)
Convert U from NDC coordinate to SVG.
Definition: TSVG.cxx:1616
Collectable string class.
Definition: TObjString.h:32
float Float_t
Definition: RtypesCore.h:53
const char Option_t
Definition: RtypesCore.h:62
R__EXTERN TStyle * gStyle
Definition: TStyle.h:423
void SetFillColor(Color_t cindex=1)
Set color index for fill areas.
Definition: TSVG.cxx:1280
void Text(Double_t x, Double_t y, const char *string)
Draw text.
Definition: TSVG.cxx:1376
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.
Definition: TSVG.cxx:285
void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Draw a Box.
Definition: TSVG.cxx:205
Int_t fType
Definition: TSVG.h:35
Size_t fMarkerSize
Definition: TAttMarker.h:37
#define gROOT
Definition: TROOT.h:340
Double_t fYsizeSVG
Definition: TSVG.h:38
Basic string class.
Definition: TString.h:137
void GetPaperSize(Float_t &xsize, Float_t &ysize) const
Set paper size for PostScript output.
Definition: TStyle.cxx:805
void Off()
Deactivate an already open SVG file.
Definition: TSVG.cxx:197
Float_t GetLineScalePS() const
Definition: TStyle.h:295
int Int_t
Definition: RtypesCore.h:41
TArc * a
Definition: textangle.C:12
const Bool_t kFALSE
Definition: Rtypes.h:92
Float_t GetGreen() const
Definition: TColor.h:61
Double_t CMtoSVG(Double_t u)
Definition: TSVG.h:49
void SetLineStyle(Style_t linestyle=1)
Change the line style.
Definition: TSVG.cxx:1302
void SetMarkerColor(Color_t cindex=1)
Set color index for markers.
Definition: TSVG.cxx:1318
virtual void WriteReal(Float_t r, Bool_t space=kTRUE)
Write a Real number to the file.
Definition: TVirtualPS.cxx:182
void CellArrayBegin(Int_t W, Int_t H, Double_t x1, Double_t x2, Double_t y1, Double_t y2)
Begin the Cell Array painting.
Definition: TSVG.cxx:1652
void TextNDC(Double_t u, Double_t v, const char *string)
Write a string of characters in NDC.
Definition: TSVG.cxx:1606
void NewPage()
Start the SVG page.
Definition: TSVG.cxx:1195
static const double x2[5]
Double_t x[n]
Definition: legend1.C:17
void SetTextColor(Color_t cindex=1)
Set color index for text.
Definition: TSVG.cxx:1364
virtual void PrintStr(const char *string="")
Output the string str in the output buffer.
Definition: TVirtualPS.cxx:69
Double_t XtoSVG(Double_t x)
Convert X from world coordinate to SVG.
Definition: TSVG.cxx:1634
Float_t GetBlue() const
Definition: TColor.h:62
static Vc_ALWAYS_INLINE Vector< T > abs(const Vector< T > &x)
Definition: vector.h:450
void DrawPS(Int_t n, Float_t *xw, Float_t *yw)
Not needed in SVG case.
Definition: TSVG.cxx:1677
void SetLineScale(Float_t=3)
Definition: TSVG.h:72
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Float_t fXsize
Definition: TSVG.h:33
char * out
Definition: TBase64.cxx:29
short Color_t
Definition: RtypesCore.h:79
Style_t fMarkerStyle
Definition: TAttMarker.h:36
Float_t fTextAngle
Definition: TAttText.h:35
Style_t fLineStyle
Definition: TAttLine.h:36
void Close(Option_t *opt="")
Close a SVG file.
Definition: TSVG.cxx:165
ROOT::R::TRInterface & r
Definition: Object.C:4
void SetLineWidth(Width_t linewidth=1)
Set the lines width.
Definition: TSVG.cxx:1310
SVector< double, 2 > v
Definition: Dict.h:5
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
void DrawPolyMarker(Int_t n, Float_t *x, Float_t *y)
Paint PolyMarker.
Definition: TSVG.cxx:568
Int_t fSizBuffer
Definition: TVirtualPS.h:49
Color_t fLineColor
Definition: TAttLine.h:35
Interface to SVG.
Definition: TSVG.h:30
virtual Color_t GetFillColor() const
Definition: TAttFill.h:43
Width_t fLineWidth
Definition: TAttLine.h:37
TMarker * m
Definition: textangle.C:8
char * Form(const char *fmt,...)
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
std::ofstream * fStream
Definition: TVirtualPS.h:51
Font_t fTextFont
Definition: TAttText.h:39
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2240
short Width_t
Definition: RtypesCore.h:78
PyObject * fType
Bool_t fBoundingBox
Definition: TSVG.h:36
virtual ~TSVG()
Default SVG destructor.
Definition: TSVG.cxx:157
2-D graphics point (world coordinates).
Definition: TPoints.h:29
void SetColor(Int_t color=1)
Set color with its color index.
Definition: TSVG.cxx:1326
static const double x1[5]
#define ClassImp(name)
Definition: Rtypes.h:279
double Double_t
Definition: RtypesCore.h:55
void CellArrayEnd()
End the Cell Array painting.
Definition: TSVG.cxx:1669
virtual void PrintFast(Int_t nch, const char *string="")
Fast version of Print.
Definition: TVirtualPS.cxx:100
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
void CellArrayFill(Int_t r, Int_t g, Int_t b)
Paint the Cell Array.
Definition: TSVG.cxx:1661
Double_t y[n]
Definition: legend1.C:17
The color creation and management class.
Definition: TColor.h:23
Float_t GetRed() const
Definition: TColor.h:60
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:493
Float_t fTextSize
Definition: TAttText.h:36
void Range(Float_t xrange, Float_t yrange)
Set the range for the paper in centimetres.
Definition: TSVG.cxx:1227
Int_t fLenBuffer
Definition: TVirtualPS.h:48
void Open(const char *filename, Int_t type=-111)
Open a SVG file.
Definition: TSVG.cxx:109
Color_t fFillColor
Definition: TAttFill.h:35
R__EXTERN TVirtualPS * gVirtualPS
Definition: TVirtualPS.h:91
Float_t GetAlpha() const
Definition: TColor.h:66
#define gPad
Definition: TVirtualPad.h:288
void DrawPolyLine(Int_t n, TPoints *xy)
Draw a PolyLine.
Definition: TSVG.cxx:433
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition: TVirtualPS.h:40
void MovePS(Double_t x, Double_t y)
Move to a new position (ix, iy).
Definition: TSVG.cxx:1174
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
Float_t fYsize
Definition: TSVG.h:34
Bool_t fRange
Definition: TSVG.h:37
Double_t VtoSVG(Double_t v)
Convert V from NDC coordinate to SVG.
Definition: TSVG.cxx:1625
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:99
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
Color_t fTextColor
Definition: TAttText.h:38
void DrawPolyLineNDC(Int_t n, TPoints *uv)
Draw a PolyLine in NDC space.
Definition: TSVG.cxx:504
const Int_t n
Definition: legend1.C:16
void Initialize()
Initialize the SVG file.
Definition: TSVG.cxx:1139
Double_t YtoSVG(Double_t y)
Convert Y from world coordinate to SVG.
Definition: TSVG.cxx:1643
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
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904