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