Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TLatex.cxx
Go to the documentation of this file.
1// @(#)root/graf:$Id$
2// Author: Nicolas Brun, Olivier Couet, Oleksandr Grebenyuk
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#include "TROOT.h"
13#include "TLatex.h"
14#include "TMathText.h"
15#include "TMath.h"
16#include "TVirtualPad.h"
17#include "TVirtualPadPainter.h"
18#include "TVirtualPS.h"
19
20#include <cstdio>
21#include <iostream>
22
24
25
26/** \class TLatex
27\ingroup BasicGraphics
28
29To draw Mathematical Formula.
30
31TLatex's purpose is to write mathematical equations. The syntax is very similar
32to the Latex's one. It provides several functionalities:
33
34- [Subscripts and Superscripts](\ref L1)
35- [Fractions](\ref L2)
36- [Splitting Lines](\ref L3)
37- [Roots](\ref L4)
38- [Mathematical Symbols](\ref L5)
39- [Delimiters](\ref L6)
40- [Greek Letters](\ref L7)
41- [Accents](\ref L8)
42- [Changing Style](\ref L9)
43- [Alignment Rules](\ref L10)
44- [Character Adjustment](\ref L11)
45- [Italic and Boldface](\ref L12)
46- [Examples](\ref L13)
47- [Interface to TMathText](\ref L14)
48- [URL links](\ref L15)
49
50When the font precision (see `TAttText`) is low (0 or 1), TLatex is
51painted as a normal TText, the control characters are not interpreted.
52
53\anchor L1
54## Subscripts and Superscripts
55Subscripts and superscripts are made with the `_` and `^`
56commands. These commands can be combined to make complicated subscript and
57superscript expressions. You may adjust the display of subscripts and
58superscripts by using the two functions `SetIndiceSize(Double_t)`,
59which set relative size of subscripts and superscripts, and
60`SetLimitIndiceSize(Int_t)`, which set limits for text resizing of
61subscripts and superscripts.
62
63Examples:
64
65Begin_Macro
66{
67 TCanvas *cl = new TCanvas("cl","cl",10,10,700,500);
68 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
69 Double_t dy = 1./7.;
70 Tl.DrawText(.1, dy, "x^{2y} :"); Tl.DrawLatex(.5, dy, "x^{2y}");
71 Tl.DrawText(.1, 2*dy, "x_{2y} :"); Tl.DrawLatex(.5, 2*dy, "x_{2y}");
72 Tl.DrawText(.1, 3*dy, "x^{y^{2}} :"); Tl.DrawLatex(.5, 3*dy, "x^{y^{2}}");
73 Tl.DrawText(.1, 4*dy, "x^{y_{1}} :"); Tl.DrawLatex(.5, 4*dy, "x^{y_{1}}");
74 Tl.DrawText(.1, 5*dy, "x^{y}_{1} :"); Tl.DrawLatex(.5, 5*dy, "x^{y}_{1}");
75 Tl.DrawText(.1, 6*dy, "x_{1}^{y} :"); Tl.DrawLatex(.5, 6*dy, "x_{1}^{y}");
76}
77End_Macro
78
79The best way to put the subscripts and superscripts before the character and not
80after, is to use an empty character:
81
82Begin_Macro
83{
84 TCanvas *cl = new TCanvas("cl","cl",10,10,700,100);
85 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
86 Tl.DrawText(.1, .5, "{}^{40}_{20}Ca :"); Tl.DrawLatex(.5, .5, "{}^{40}_{20}Ca");
87}
88End_Macro
89
90The subscripts and superscripts operators apply not only on one character but
91on all the "normal text" preceding them. In the following example the second
92`E` is lower than the first one because the operator `_` is
93applied on `/f` which has a descending part, and not only on `f`
94which as no descending part.
95
96Begin_Macro
97{
98 TCanvas *cl = new TCanvas("cl","cl",10,10,700,100);
99 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
100 Tl.DrawText(.1, .5, "f_{E}/f_{E} :"); Tl.DrawLatex(.5, .5, "f_{E}/f_{E}");
101}
102End_Macro
103
104To make sure the second operator `_` applies only on `f` a dummy operator `^{}`
105should be introduced to separate the `f` from the `/`.
106
107Begin_Macro
108{
109 TCanvas *cl = new TCanvas("cl","cl",10,10,700,100);
110 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
111 Tl.DrawText(.1, .5, "f_{E}/^{}f_{E} :"); Tl.DrawLatex(.5, .5, "f_{E}/^{}f_{E}");
112}
113End_Macro
114
115\anchor L2
116## Fractions
117Fractions denoted by the `/` symbol are made in the obvious way.
118The `#frac` command is used for large fractions in displayed formula;
119it has two arguments: the numerator and the denominator.
120
121Examples:
122
123Begin_Macro
124{
125 TCanvas *cl = new TCanvas("cl","cl",10,10,700,100);
126 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
127 Tl.DrawText(.1, .5, "x = #frac{y+z/2}{y^{2}+1} :"); Tl.DrawLatex(.5, .5, "x = #frac{y+z/2}{y^{2}+1}");
128}
129End_Macro
130
131\anchor L3
132## Splitting Lines
133Text can be split in two lines via the command `#splitline`.
134
135Examples:
136
137Begin_Macro
138{
139 TCanvas *cl = new TCanvas("cl","cl",10,10,700,100);
140 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
141 Tl.DrawText(.1, .5, "#splitline{21 April 2003}{14:02:30} :"); Tl.DrawLatex(.6, .5, "#splitline{21 April 2003}{14:02:30}");
142}
143End_Macro
144
145\anchor L4
146## Roots
147The `#sqrt` command produces the square root of its argument; it has
148an optional first argument for other roots.
149
150Examples:
151
152Begin_Macro
153{
154 TCanvas *cl = new TCanvas("cl","cl",10,10,700,100);
155 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
156 Tl.DrawText(.1, .5, "#sqrt{10} #sqrt[3]{10} :"); Tl.DrawLatex(.5, .5, "#sqrt{10} #sqrt[3]{10}");
157}
158End_Macro
159
160\anchor L5
161## Mathematical Symbols
162TLatex can display dozens of special mathematical symbols. A few of them, such
163as `+` and `>` , are produced by typing the corresponding
164keyboard character. Others are obtained with the commands in the following
165table:
166
167Begin_Macro
168mathsymbols.C
169End_Macro
170
171
172\anchor L6
173## Delimiters
174TLatex provides 4 kinds of proportional delimiters:
175
176 #[]{....} or "a la" Latex #left[.....#right] : big square brackets
177 #{}{....} or #left{.....#right} : big curly brackets
178 #||{....} or #left|.....#right| : big absolute value symbols
179 #(){....} or #left(.....#right) : big parentheses
180
181\anchor L7
182## Greek Letters
183The command to produce a lowercase Greek letter is obtained by adding a
184`#` to the name of the letter. For an uppercase Greek letter, just
185capitalize the first letter of the command name. Some letters have two
186representations. The name of the second one (the "variation") starts with "var".
187The following table gives the complete list:
188
189Begin_Macro
190greekletters.C
191End_Macro
192
193
194\anchor L8
195## Accents
196Several kind of accents are available:
197
198Begin_Macro
199{
200 TCanvas *cl = new TCanvas("cl","cl",10,10,700,300);
201 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
202 Tl.DrawText(.1, .10, "#hat : "); Tl.DrawLatex(.3, .10, " #hat{a} ");
203 Tl.DrawText(.1, .23, "#check : "); Tl.DrawLatex(.3, .23, " #check{a} ");
204 Tl.DrawText(.1, .36, "#acute : "); Tl.DrawLatex(.3, .36, " #acute{a} ");
205 Tl.DrawText(.1, .50, "#grave : "); Tl.DrawLatex(.3, .50, " #grave{a} ");
206 Tl.DrawText(.1, .63, "#dot : "); Tl.DrawLatex(.3, .63, " #dot{a} ");
207 Tl.DrawText(.1, .76, "#ddot : "); Tl.DrawLatex(.3, .76, " #ddot{a} ");
208 Tl.DrawText(.1, .90, "#tilde : "); Tl.DrawLatex(.3, .90, " #tilde{a} ");
209}
210End_Macro
211
212
213The special sign: `#slash` draws a slash on top of the text between brackets:
214
215Begin_Macro
216{
217 TCanvas *cl = new TCanvas("cl","cl",10,10,700,100);
218 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
219 Tl.DrawText(.1, .5, "#slash{E}_{T} :"); Tl.DrawLatex(.5, .5, "#slash{E}_{T}");
220}
221End_Macro
222
223Bar and vectors sign are done the following way:
224
225Begin_Macro
226{
227 TCanvas *cl = new TCanvas("cl","cl",10,10,700,100);
228 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
229 Tl.DrawText(.1, .5, "#bar{a} and #vec{a} :"); Tl.DrawLatex(.5, .5, "#bar{a} and #vec{a}");
230}
231End_Macro
232
233\anchor L9
234## Changing Style
235One can change the font, the text color, or the text size at any time using :
236`#font[font-number]{...}`, `#color[color-number]{...}`
237and `#scale[scale-factor]{...}`
238
239Examples:
240
241Begin_Macro
242{
243 TCanvas *cl = new TCanvas("cl","cl",10,10,900,300);
244 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
245 Double_t dy = 1./4.;
246 Tl.DrawText(.01, dy, "#font[12]{Times Italic} and #font[22]{Times bold} :"); Tl.DrawLatex(.7, dy, "#font[12]{Times Italic} and #font[22]{Times bold}");
247 Tl.DrawText(.01, 2*dy, "#color[2]{Red} and #color[4]{Blue} :"); Tl.DrawLatex(.7, 2*dy, "#color[2]{Red} and #color[4]{Blue}");
248 Tl.DrawText(.01, 3*dy, "#scale[1.2]{Bigger} and #scale[0.8]{Smaller} :"); Tl.DrawLatex(.7, 3*dy, "#scale[1.2]{Bigger} and #scale[0.8]{Smaller}");
249}
250End_Macro
251
252\anchor L10
253## Alignment Rules
254The `TText` alignment rules apply to the `TLatex` objects with one exception
255concerning the vertical alignment:
256
257- if the vertical alignment = 1 , subscripts are not taken into account
258- if the vertical alignment = 0 , the text is aligned to the box surrounding
259 the full text with sub and superscripts
260
261This is illustrated by the following example:
262
263Begin_Macro(source)
264{
265 TCanvas Tlva("Tlva","Tlva",500,500);
266 Tlva.SetGrid();
267 Tlva.DrawFrame(0,0,1,1);
268 const char *longstring = "K_{S}... K^{*0}... #frac{2s}{#pi#alpha^{2}} #frac{d#sigma}{dcos#theta} (e^{+}e^{-} #rightarrow f#bar{f} ) = #left| #frac{1}{1 - #Delta#alpha} #right|^{2} (1+cos^{2}#theta)";
269
270 TLatex latex;
271 latex.SetTextSize(0.025);
272 latex.SetTextAlign(13); //align at top
273 latex.DrawLatex(.2,.9,"K_{S}");
274 latex.DrawLatex(.3,.9,"K^{*0}");
275 latex.DrawLatex(.2,.8,longstring);
276
277 latex.SetTextAlign(12); //centered
278 latex.DrawLatex(.2,.6,"K_{S}");
279 latex.DrawLatex(.3,.6,"K^{*0}");
280 latex.DrawLatex(.2,.5,longstring);
281
282 latex.SetTextAlign(11); //default bottom alignment
283 latex.DrawLatex(.2,.4,"K_{S}");
284 latex.DrawLatex(.3,.4,"K^{*0}");
285 latex.DrawLatex(.2,.3,longstring);
286
287 latex.SetTextAlign(10); //special bottom alignment
288 latex.DrawLatex(.2,.2,"K_{S}");
289 latex.DrawLatex(.3,.2,"K^{*0}");
290 latex.DrawLatex(.2,.1,longstring);
291
292 latex.SetTextAlign(12);
293 latex.SetTextFont(72);
294 latex.DrawLatex(.1,.80,"13");
295 latex.DrawLatex(.1,.55,"12");
296 latex.DrawLatex(.1,.35,"11");
297 latex.DrawLatex(.1,.18,"10");
298 return Tlva;
299}
300End_Macro
301
302
303\anchor L11
304## Character Adjustment
305
306The two commands `#kern` and `#lower` enable a better control
307over character placement. The command `#kern[(Float_t)dx]{text}` moves
308the output string horizontally by the fraction `dx` of its length.
309Similarly, `#lower[(Float_t)dy]{text}` shifts the text up or down by
310the fraction `dy` of its height.
311
312Examples:
313
314Begin_Macro
315{
316 TCanvas *cl = new TCanvas("cl","cl",10,10,900,300);
317 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
318 TLatex Tt; Tt.SetTextFont(43); Tt.SetTextSize(16);
319 Double_t dy = 1./7.;
320 Tl.DrawLatex(.5, dy, "Positive k#kern[0.3]{e}#kern[0.3]{r}#kern[0.3]{n}#kern[0.3]{i}#kern[0.3]{n}#kern[0.3]{g}");
321 Tt.DrawText(.01, 2*dy, "Positive k#kern[0.3]{e}#kern[0.3]{r}#kern[0.3]{n}#kern[0.3]{i}#kern[0.3]{n}#kern[0.3]{g} :");
322 Tl.DrawLatex(.5, 3*dy, "Negative k#kern[-0.3]{e}#kern[-0.3]{r}#kern[-0.3]{n}#kern[-0.3]{i}#kern[-0.3]{n}#kern[-0.3]{g}");
323 Tt.DrawText(.01, 4*dy, "Negative k#kern[-0.3]{e}#kern[-0.3]{r}#kern[-0.3]{n}#kern[-0.3]{i}#kern[-0.3]{n}#kern[-0.3]{g} :");
324 Tl.DrawLatex(.5, 5*dy, "Vertical a#lower[0.2]{d}#lower[0.4]{j}#lower[0.1]{u}#lower[-0.1]{s}#lower[-0.3]{t}#lower[-0.4]{m}#lower[-0.2]{e}#lower[0.1]{n}t");
325 Tt.DrawText(.01, 6*dy, "Vertical a#lower[0.2]{d}#lower[0.4]{j}#lower[0.1]{u}#lower[-0.1]{s}#lower[-0.3]{t}#lower[-0.4]{m}#lower[-0.2]{e}#lower[0.1]{n}t :");
326
327}
328End_Macro
329
330\anchor L12
331## Italic and Boldface
332Text can be turned italic or boldface using the commands
333`#it` and `#bf`.
334
335Examples:
336
337Begin_Macro
338{
339 TCanvas *cl = new TCanvas("cl","cl",10,10,900,300);
340 TLatex Tl; Tl.SetTextFont(43); Tl.SetTextSize(20);
341 Double_t dy = 1./3.;
342 Tl.DrawText(.01, dy, "abc#alpha#beta#gamma, #it{abc#alpha#beta#gamma} :"); Tl.DrawLatex(.7, dy, "abc#alpha#beta#gamma, #it{abc#alpha#beta#gamma}");
343 Tl.DrawText(.01, 2*dy, "#bf{bold}, #it{italic}, #bf{#it{bold italic}}, #bf{#bf{unbold}} :"); Tl.DrawLatex(.7, 2*dy, "#bf{bold}, #it{italic}, #bf{#it{bold italic}}, #bf{#bf{unbold}}");
344}
345End_Macro
346
347\anchor L13
348## Examples
349
350Begin_Macro(source)
351{
352 TCanvas ex1("ex1","Latex",500,600);
353 TLatex Tl;
354 Tl.SetTextAlign(12);
355 Tl.SetTextSize(0.04);
356 Tl.DrawLatex(0.1,0.8,"1) C(x) = d #sqrt{#frac{2}{#lambdaD}} #int^{x}_{0}cos(#frac{#pi}{2}t^{2})dt");
357 Tl.DrawLatex(0.1,0.6,"2) C(x) = d #sqrt{#frac{2}{#lambdaD}} #int^{x}cos(#frac{#pi}{2}t^{2})dt");
358 Tl.DrawLatex(0.1,0.4,"3) R = |A|^{2} = #frac{1}{2}(#[]{#frac{1}{2}+C(V)}^{2}+#[]{#frac{1}{2}+S(V)}^{2})");
359 Tl.DrawLatex(0.1,0.2,"4) F(t) = #sum_{i=-#infty}^{#infty}A(i)cos#[]{#frac{i}{t+i}}");
360 return ex1;
361}
362End_Macro
363Begin_Macro(source)
364{
365 TCanvas ex2("ex2","Latex",500,300);
366 TLatex Tl;
367 Tl.SetTextAlign(23);
368 Tl.SetTextSize(0.08);
369 Tl.DrawLatex(0.5,0.95,"e^{+}e^{-}#rightarrowZ^{0}#rightarrowI#bar{I}, q#bar{q}");
370 Tl.DrawLatex(0.5,0.75,"|#vec{a}#bullet#vec{b}|=#Sigmaa^{i}_{jk}+b^{bj}_{i}");
371 Tl.DrawLatex(0.5,0.5,"i(#partial_{#mu}#bar{#psi}#gamma^{#mu}+m#bar{#psi}=0#Leftrightarrow(#Box+m^{2})#psi=0");
372 Tl.DrawLatex(0.5,0.3,"L_{em}=eJ^{#mu}_{em}A_{#mu} , J^{#mu}_{em}=#bar{I}#gamma_{#mu}I , M^{j}_{i}=#SigmaA_{#alpha}#tau^{#alphaj}_{i}");
373 return ex2;
374}
375End_Macro
376Begin_Macro(source)
377{
378 TCanvas ex3("ex3","Latex",500,300);
379 TPaveText pt(.1,.1,.9,.9);
380 pt.AddText("#frac{2s}{#pi#alpha^{2}} #frac{d#sigma}{dcos#theta} (e^{+}e^{-} #rightarrow f#bar{f} ) = ");
381 pt.AddText("#left| #frac{1}{1 - #Delta#alpha} #right|^{2} (1+cos^{2}#theta");
382 pt.AddText("+ 4 Re #left{ #frac{2}{1 - #Delta#alpha} #chi(s) #[]{#hat{g}_{#nu}^{e}#hat{g}_{#nu}^{f} (1 + cos^{2}#theta) + 2 #hat{g}_{a}^{e}#hat{g}_{a}^{f} cos#theta) } #right}");
383 pt.SetLabel("Born equation");
384 pt.Draw();
385 return ex3;
386}
387End_Macro
388
389
390\anchor L14
391## Interface to TMathText
392
393The class `TMathText` is a TeX math formulae interpreter. It uses plain
394TeX syntax and uses "\\" as control instead of "#". If a piece of text containing
395"\\" is given to `TLatex` then `TMathText` is automatically invoked.
396Therefore, as histograms' titles, axis titles, labels etc ... are drawn using
397`TLatex`, the `TMathText` syntax can be used for them also.
398
399\anchor L15
400## URL links
401JSROOT, standard PDF output and standard SVG output support the syntax '#url[link]{label}'.
402This can be combined with other TLatex commands, such as color or font settings.
403Begin_Macro(source)
404{
405 auto cl = new TCanvas("cl", "Use of #url in TLatex", 1200, 800);
406 auto latex = new TLatex(0.5, 0.5, "Link on #color[4]{#url[https://root.cern]{root.cern}} web site");
407 latex->SetTextSize(0.1);
408 latex->SetTextAlign(22);
409 latex->Draw();
410 cl->Print("cl.svg");
411 cl->Print("cl.pdf");
412}
413End_Macro
414*/
415
416////////////////////////////////////////////////////////////////////////////////
417/// Default constructor.
418
420{
421 fFactorSize = 1.5;
422 fFactorPos = 0.6;
423 fError = nullptr;
424 fShow = kFALSE;
425 fOriginSize = 0.04;
426 fItalic = kFALSE;
428 SetLineWidth(2);
429}
430
431////////////////////////////////////////////////////////////////////////////////
432/// Normal constructor.
433
434TLatex::TLatex(Double_t x, Double_t y, const char *text)
435 :TText(x,y,text)
436{
437 fFactorSize = 1.5;
438 fFactorPos = 0.6;
439 fError = nullptr;
440 fShow = kFALSE;
441 fOriginSize = 0.04;
442 fItalic = kFALSE;
444 SetLineWidth(2);
445}
446
447////////////////////////////////////////////////////////////////////////////////
448/// Destructor.
449
451{
452}
453
454////////////////////////////////////////////////////////////////////////////////
455/// Copy constructor.
456
458{
459 fFactorSize = 1.5;
460 fFactorPos = 0.6;
461 fError = nullptr;
462 fShow = kFALSE;
463 fOriginSize = 0.04;
464 fItalic = kFALSE;
466 latex.TLatex::Copy(*this);
467}
468
469////////////////////////////////////////////////////////////////////////////////
470///assignment operator
471
473{
474 if (this != &lt) {
476 TAttLine::operator=(lt);
477 fFactorSize = lt.fFactorSize;
478 fFactorPos = lt.fFactorPos;
479 fLimitFactorSize = lt.fLimitFactorSize;
480 fError = lt.fError;
481 fShow = lt.fShow;
482 fTabSize = lt.fTabSize;
483 fOriginSize = lt.fOriginSize;
484 fItalic = lt.fItalic;
485 }
486 return *this;
487}
488
489////////////////////////////////////////////////////////////////////////////////
490/// Copy this TLatex object to another TLatex.
491
492void TLatex::Copy(TObject &obj) const
493{
494 TText::Copy(obj);
495 TAttLine::Copy((TLatex &)obj);
496 ((TLatex&)obj).fFactorSize = fFactorSize;
497 ((TLatex&)obj).fFactorPos = fFactorPos;
498 ((TLatex&)obj).fLimitFactorSize = fLimitFactorSize;
499 ((TLatex&)obj).fError = fError;
500 ((TLatex&)obj).fShow = fShow;
501 ((TLatex&)obj).fTabSize = fTabSize;
502 ((TLatex&)obj).fOriginSize = fOriginSize;
503 ((TLatex&)obj).fItalic = fItalic;
504}
505
506////////////////////////////////////////////////////////////////////////////////
507/// Rotate array of points around fX, fY coordinate by specified angle
508
510{
512 pad->XYtoAbsPixel(fX, fY, xOrigin, yOrigin);
513
516 Double_t xx, yy;
517 for (Int_t n = 0; n < np; ++n) {
518 pad->AbsPixeltoXY( cos_angle * (x[n]-xOrigin) + sin_angle * (y[n]-yOrigin) + xOrigin,
519 -sin_angle * (x[n]-xOrigin) + cos_angle * (y[n]-yOrigin) + yOrigin,
520 xx, yy);
521 x[n] = xx;
522 y[n] = yy;
523 }
524}
525
526////////////////////////////////////////////////////////////////////////////////
527/// Rotate single point around fX, fY coordinate by specified angle
528
530{
531 xx = x;
532 yy = y;
533 Rotate(pad, angle, 1, &xx, &yy);
534}
535
536////////////////////////////////////////////////////////////////////////////////
537/// Analyse function.
538
540{
541 return Analyse(0, 0, spec, t, length);
542}
543
544////////////////////////////////////////////////////////////////////////////////
545/// Analyse and paint the TLatex formula
546///
547/// It is called twice : first for calculating the size of
548/// each portion of the formula, then to paint the formula.
549/// When analyse finds an operator or separator, it calls
550/// itself recursively to analyse the arguments of the operator.
551/// when the argument is an atom (normal text), it calculates
552/// the size of it and return it as the result.
553/// for example : if the operator #%frac{arg1}{arg2} is found :
554/// Analyse(arg1) return the size of arg1 (width, up, down)
555/// Analyse(arg2) return the size of arg2
556/// now, we know the size of #%frac{arg1}{arg2}:
557///
558/// ~~~ {.cpp}
559/// width = max(width_arg1, width_arg2)
560/// up = up_arg1 + down_arg1
561/// down = up_arg2 + down_arg2
562/// ~~~
563///
564/// so, when the user wants to paint a fraction at position (x,y),
565/// the rect used for the formula is : (x,y-up,x+width,y+down)
566///
567/// return size of zone occupied by the text/formula
568/// - `t` : chain to be analyzed
569/// - `length` : number of chars in t.
570
572{
573 const char *tab[] = { "alpha","beta","chi","delta","varepsilon","phi","gamma","eta","iota","varphi","kappa","lambda",
574 "mu","nu","omicron","pi","theta","rho","sigma","tau","upsilon","varomega","omega","xi","psi","zeta",
575 "Alpha","Beta","Chi","Delta","Epsilon","Phi","Gamma","Eta","Iota","vartheta",
576 "Kappa","Lambda","Mu","Nu","Omicron","Pi","Theta","Rho","Sigma","Tau",
577 "Upsilon","varsigma","Omega","Xi","Psi","Zeta","varUpsilon","epsilon"};
578
579 const char *tab2[] = { "leq","/","infty","voidb","club","diamond","heart",
580 "spade","leftrightarrow","leftarrow","uparrow","rightarrow",
581 "downarrow","circ","pm","doublequote","geq","times","propto",
582 "partial","bullet","divide","neq","equiv","approx","3dots",
583 "cbar","topbar","downleftarrow","aleph","Jgothic","Rgothic","voidn",
584 "otimes","oplus","oslash","cap","cup","supset","supseteq",
585 "notsubset","subset","subseteq","in","notin","angle","nabla",
586 "oright","ocopyright","trademark","prod","surd","upoint","corner","wedge",
587 "vee","Leftrightarrow","Leftarrow","Uparrow","Rightarrow",
588 "Downarrow","diamond","LT","void1","copyright","void3","sum",
589 "arctop","lbar","arcbottom","topbar","void8", "bottombar","arcbar",
590 "ltbar","AA","aa","void06","GT","int","forall","exists", "textendash", "textemdash" };
591
592 const char *tab3[] = { "bar","vec","dot","hat","ddot","acute","grave","check","tilde","slash"};
593
594 if (fError) return TLatexFormSize(0,0,0);
595
597 Int_t i, k;
598 Int_t min = 0, max = 0;
599 Bool_t cont = kTRUE;
600 while(cont) {
601 // count leading blanks
602 //while(nBlancDeb+nBlancFin<length && t[nBlancDeb]==' ') nBlancDeb++;
603
604 if (nBlancDeb==length) return TLatexFormSize(0,0,0); // empty string
605
606 // count trailing blanks
607 //while(nBlancDeb+nBlancFin<length && t[length-nBlancFin-1]==' ') nBlancFin++;
608
610
611 // remove characters { }
612 if (t[nBlancDeb]=='{' && t[length-nBlancFin-1]=='}') {
613 Int_t nBrackets = 0;
615 for(i=nBlancDeb;i<length-nBlancFin;i++) {
616 if (t[i] == '{' && !(i>0 && t[i-1] == '@')) nBrackets++;
617 if (t[i] == '}' && t[i-1]!= '@') nBrackets--;
618 if (nBrackets==0 && i<length-nBlancFin-2) {
620 break;
621 }
622 }
623
624 if (sameBrackets) {
625 // begin and end brackets match
626 nBlancDeb++;
627 nBlancFin++;
628 if (nBlancDeb+nBlancFin==length) return TLatexFormSize(0,0,0); // empty string
629 cont = kTRUE;
630 }
631
632 }
633
636 }
637
638 // make a copy of the current processed chain of characters
639 // removing leading and trailing blanks
640 length -= nBlancFin+nBlancDeb; // length of string without blanks
641 if (length <=0) {
642 Error("Analyse", "It seems there is a syntax error in the TLatex string");
643 return TLatexFormSize(0,0,0);
644 }
645 Char_t* text = new Char_t[length+1];
647 text[length] = 0;
648
649 // compute size of subscripts and superscripts
652 indiceSize = spec.fSize;
653 // subtract 0.001 because of rounding errors
655 specNewSize.fSize = indiceSize;
656
657 // recherche des operateurs
658 Int_t opPower = -1; // Position of first ^ (power)
659 Int_t opUnder = -1; // Position of first _ (indice)
660 Int_t opFrac = -1; // Position of first \frac
661 Int_t opSqrt = -1; // Position of first \sqrt
662 Int_t nBrackets = 0; // Nesting level in { }
663 Int_t nCroch = 0; // Nesting level in [ ]
664 Int_t opCurlyCurly = -1; // Position of first }{
665 Int_t opSquareCurly = -1; // Position of first ]{
666 Int_t opCloseCurly = -2; // Position of first }
667 Int_t opColor = -1; // Position of first #color
668 Int_t opUrl = -1; // Position of first #url
669 Int_t opFont = -1; // Position of first #font
670 Int_t opScale = -1; // Position of first #scale
671 Int_t opGreek = -1; // Position of a Greek letter
672 Int_t opSpec = -1; // position of a special character
673 Int_t opAbove = -1; // position of a vector/overline
674 Int_t opSquareBracket = 0 ; // position of a "[]{" operator (#[]{arg})
675 Int_t opBigCurly = 0 ; // position of a "{}{" operator (big curly bracket #{}{arg})
676 Int_t opAbs = 0 ; // position of a "||{" operator (absolute value) (#||{arg})
677 Int_t opParen = 0 ; // position of a "(){" operator (big parenthesis #(){arg})
678 Int_t abovePlace = 0 ; // true if subscripts must be written above and not after
679 Int_t opBox = 0 ; // position of #Box
680 Int_t opPerp = 0; // position of #perp
681 Int_t opOdot = 0; // position of #odot
682 Int_t opHbar = 0; // position of #hbar
683 Int_t opMinus = 0; // position of #minus
684 Int_t opPlus = 0; // position of #plus
685 Int_t opMp = 0; // position of #mp
686 Int_t opBackslash = 0; // position of #backslash
687 Int_t opParallel = 0; // position of #parallel
688 Int_t opSplitLine = -1; // Position of first #splitline
689 Int_t opKern = -1; // Position of first #kern
690 Int_t opLower = -1; // Position of first #lower
691 Int_t opBf = -1; // Position of first #bf
692 Int_t opIt = -1; // Position of first #it
693 Int_t opMbox = -1; // Position of first #mbox
694
697
698 for(i=0;i<length;i++) {
699 switch (text[i]) {
700 case '\'' : quote1 = !quote1 ; break ;
701 case '"' : quote2 = !quote2 ; break ;
702 }
703 //if (quote1 || quote2) continue ;
704 switch (text[i]) {
705 case '{':
706 if (nCroch==0) {
707 if (!(i>0 && text[i-1] == '@')) nBrackets++;
708 }
709 break;
710 case '}':
711 if (nCroch==0) {
712 if (!(i>0 && text[i-1] == '@')) nBrackets--;
713 if (nBrackets==0) {
714 if (i<length-1) if (text[i+1]=='{' && opCurlyCurly==-1) opCurlyCurly=i;
715 if (i<length-2) {
716 if (text[i+1]!='{' && !(text[i+2]=='{' && (text[i+1]=='^' || text[i+1]=='_'))
717 && opCloseCurly==-2) opCloseCurly=i;
718 }
719 else if (i<length-1) {
720 if (text[i+1]!='{' && opCloseCurly==-2) opCloseCurly=i;
721 }
722 else if (opCloseCurly==-2) opCloseCurly=i;
723 }
724 }
725 break;
726 case '[':
727 if (nBrackets==0) {
728 if (!(i>0 && text[i-1] == '@')) nCroch++;
729 }
730 break;
731 case ']':
732 if (nBrackets==0) {
733 if (!(i>0 && text[i-1] == '@')) nCroch--;
734 if (nCroch<0) {
735 // more "]" than "["
736 fError = "Missing \"[\"";
737 delete [] text;
738 return TLatexFormSize(0,0,0);
739 }
740 }
741 break;
742 }
743 if (length>i+1) {
744 Char_t buf[3];
745 strncpy(buf,&text[i],2);
746 if (strncmp(buf,"^{",2)==0) {
747 if (opPower==-1 && nBrackets==0 && nCroch==0) opPower=i;
748 if (i>3) {
749 Char_t buf1[5];
750 strncpy(buf1,&text[i-4],4);
751 if (strncmp(buf1,"#int",4)==0) {
752 abovePlace = 1;
753 if (i>4 && opCloseCurly==-2) opCloseCurly=i-5;
754 }
755 if (strncmp(buf1,"#sum",4)==0) {
756 abovePlace = 2;
757 if (i>4 && opCloseCurly==-2) opCloseCurly=i-5;
758 }
759 }
760 }
761 if (strncmp(buf,"_{",2)==0) {
762 if (opUnder==-1 && nBrackets==0 && nCroch==0) opUnder=i;
763 if (i>3) {
764 Char_t buf2[5];
765 strncpy(buf2,&text[i-4],4);
766 if (strncmp(buf2,"#int",4)==0) {
767 abovePlace = 1;
768 if (i>4 && opCloseCurly==-2) opCloseCurly=i-5;
769 }
770 if (strncmp(buf2,"#sum",4)==0) {
771 abovePlace = 2;
772 if (i>4 && opCloseCurly==-2) opCloseCurly=i-5;
773 }
774 }
775 }
776 if (strncmp(buf,"]{",2)==0)
777 if (opSquareCurly==-1 && nBrackets==0 && nCroch==0) opSquareCurly=i;
778 }
779 // detect other operators
780 if (text[i]=='\\' || (text[i]=='#' && !opFound && nBrackets==0 && nCroch==0)) {
781
782 if (length>i+10) {
783 Char_t buf[11];
784 strncpy(buf,&text[i+1],10);
785 if (strncmp(buf,"splitline{",10)==0) {
787 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
788 continue;
789 }
790 }
791 if (length>i+9) {
792 Char_t buf[10];
793 strncpy(buf,&text[i+1],9);
794 if (!opBackslash && strncmp(buf,"backslash",9)==0) {
796 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
797 continue;
798 }
799 }
800 if (length>i+8) {
801 Char_t buf[9];
802 strncpy(buf,&text[i+1],8);
803 if (!opParallel && strncmp(buf,"parallel",8)==0) {
805 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
806 continue;
807 }
808 }
809 if (length>i+6) {
810 Char_t buf[7];
811 strncpy(buf,&text[i+1],6);
812 if (strncmp(buf,"lower[",6)==0 || strncmp(buf,"lower{",6)==0) {
813 opLower=i; opFound = kTRUE;
814 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
815 continue ;
816 }
817 if (strncmp(buf,"scale[",6)==0 || strncmp(buf,"scale{",6)==0) {
818 opScale=i; opFound = kTRUE;
819 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
820 continue ;
821 }
822 if (strncmp(buf,"color[",6)==0 || strncmp(buf,"color{",6)==0) {
823 opColor=i; opFound = kTRUE;
824 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
825 continue ;
826 }
827 }
828 if (length>i+5) {
829 Char_t buf[6];
830 strncpy(buf,&text[i+1],5);
831 if (strncmp(buf,"frac{",5)==0) {
832 opFrac=i; opFound = kTRUE;
833 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
834 continue;
835 }
836 if (strncmp(buf,"sqrt{",5)==0 || strncmp(buf,"sqrt[",5)==0) {
837 opSqrt=i; opFound = kTRUE;
838 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
839 continue;
840 }
841 if (strncmp(buf,"font{",5)==0 || strncmp(buf,"font[",5)==0) {
842 opFont=i; opFound = kTRUE;
843 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
844 continue;
845 }
846 if (strncmp(buf,"kern[",5)==0 || strncmp(buf,"kern{",5)==0) {
847 opKern=i; opFound = kTRUE;
848 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
849 continue ;
850 }
851 if (!opMinus && strncmp(buf,"minus",5)==0) {
852 opMinus=1; opFound = kTRUE;
853 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
854 continue;
855 }
856 if (strncmp(buf,"mbox[",5)==0 || strncmp(buf,"mbox{",5)==0) {
857 opMbox=i; opFound = kTRUE;
858 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
859 continue ;
860 }
861 }
862 if (length>i+4) {
863 Char_t buf[5];
864 strncpy(buf,&text[i+1],4);
865 if (!opOdot && strncmp(buf,"odot",4)==0) {
866 opOdot=1; opFound = kTRUE;
867 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
868 continue;
869 }
870 if (!opHbar && strncmp(buf,"hbar",4)==0) {
871 opHbar=1; opFound = kTRUE;
872 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
873 continue;
874 }
875 if (!opPerp && strncmp(buf,"perp",4)==0) {
876 opPerp=1; opFound = kTRUE;
877 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
878 continue;
879 }
880 if (!opPlus && strncmp(buf,"plus",4)==0) {
881 opPlus=1; opFound = kTRUE;
882 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
883 continue;
884 }
885 if (strncmp(buf,"url[",4)==0 || strncmp(buf,"url{",4)==0) {
886 opUrl=i; opFound = kTRUE;
887 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
888 continue ;
889 }
890 }
891 if (length>i+3) {
892 Char_t buf[4];
893 strncpy(buf,&text[i+1],3);
894 buf[3] = 0;
895 if (strncmp(buf,"[]{",3)==0) {
897 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
898 continue;
899 }
900 if (strncmp(buf,"{}{",3)==0 ) {
902 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
903 continue;
904 }
905 if (strncmp(buf,"||{",3)==0) {
906 opAbs=1; opFound = kTRUE;
907 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
908 continue;
909 }
910 if (strncmp(buf,"(){",3)==0) {
911 opParen=1; opFound = kTRUE;
912 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
913 continue;
914 }
915 if (!opBox && strncmp(buf,"Box",3)==0) {
916 opBox=1; opFound = kTRUE;
917 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
918 continue;
919 }
920 if (strncmp(buf,"bf[",3)==0 || strncmp(buf,"bf{",3)==0) {
921 opBf=i; opFound = kTRUE;
922 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
923 continue ;
924 }
925 if (strncmp(buf,"it[",3)==0 || strncmp(buf,"it{",3)==0) {
926 opIt=i; opFound = kTRUE;
927 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
928 continue ;
929 }
930 }
931 if (length>i+2) {
932 Char_t buf[3];
933 strncpy(buf,&text[i+1],2);
934 if (!opMp && strncmp(buf,"mp",2)==0) {
935 opMp=1; opFound = kTRUE;
936 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
937 continue;
938 }
939 }
940 for(k=0;k<54;k++) {
941 if (!opFound && UInt_t(length)>i+strlen(tab[k])) {
942 if (strncmp(&text[i+1],tab[k],strlen(tab[k]))==0) {
943 opGreek=k;
944 opFound = kTRUE;
945 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
946 }
947 }
948 }
949 for(k=0;k<10;k++) {
950 if (!opFound && UInt_t(length)>i+strlen(tab3[k])) {
951 if (strncmp(&text[i+1],tab3[k],strlen(tab3[k]))==0) {
952 opAbove=k;
953 opFound = kTRUE;
954 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
955 }
956 }
957 }
958 UInt_t lastsize = 0;
959 constexpr Int_t lenTab2 = sizeof(tab2) / sizeof(const char *);
960 if (!opFound) {
961 for (k = 0; k < lenTab2; k++) {
962 if ((opSpec == -1 || strlen(tab2[k]) > lastsize) && UInt_t(length) > i + strlen(tab2[k])) {
963 if (strncmp(&text[i + 1], tab2[k], strlen(tab2[k])) == 0) {
964 lastsize = strlen(tab2[k]);
965 opSpec = k;
966 opFound = kTRUE;
967 if (i > 0 && opCloseCurly == -2)
968 opCloseCurly = i - 1;
969 }
970 }
971 }
972 }
973 }
974 }
975
980
981 // analysis of operators found
982 if (opCloseCurly>-1 && opCloseCurly<length-1) { // separator } found
983 if(!fShow) {
986 Savefs(&fs1);
987 } else {
988 fs1 = Readfs();
991 }
992 result = fs1+fs2;
993 }
994
995 else if (opPower>-1 && opUnder>-1) { // ^ and _ found
997 max = std::max(opPower,opUnder);
998 Double_t xfpos = 0. ; //GetHeight()*spec.fSize/5.;
999 Double_t prop=1, propU=1; // scale factor for #sum & #int
1000 switch (abovePlace) {
1001 case 1 :
1002 prop = .8 ; propU = 1.75 ; // Int
1003 break;
1004 case 2:
1005 prop = .9 ; propU = 1.75 ; // Sum
1006 break;
1007 }
1008 // propU acts on upper number
1009 // when increasing propU value, the upper indice position is higher
1010 // when increasing prop values, the lower indice position is lower
1011
1012 if (!fShow) {
1013 Int_t ltext = min ;
1014 if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) {
1015 // upper and lower indice before the character
1016 // like with chemical element
1017 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1018 ltext-- ;
1019 }
1020 fs1 = Anal1(spec,text,ltext);
1021 fs2 = Anal1(specNewSize,text+min+1,max-min-1);
1022 fs3 = Anal1(specNewSize,text+max+1,length-max-1);
1023 Savefs(&fs1);
1024 Savefs(&fs2);
1025 Savefs(&fs3);
1026 } else {
1027 fs3 = Readfs();
1028 fs2 = Readfs();
1029 fs1 = Readfs();
1030 Double_t pos = 0;
1031 if (!abovePlace) {
1032 Double_t addW = fs1.Width()+xfpos, addH1, addH2;
1033 if (opPower<opUnder) {
1034 addH1 = -fs1.Over()*(fFactorPos)-fs2.Under();
1035 addH2 = fs1.Under()+fs3.Over()*(fFactorPos);
1036 } else {
1037 addH1 = fs1.Under()+fs2.Over()*(fFactorPos);
1038 addH2 = -fs1.Over()*(fFactorPos)-fs3.Under();
1039 }
1040 Analyse(x+addW,y+addH2,specNewSize,text+max+1,length-max-1);
1041 Analyse(x+addW,y+addH1,specNewSize,text+min+1,max-min-1);
1042 } else {
1044 Double_t m = std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width()));
1045 pos = (m-fs1.Width())/2;
1046 if (opPower<opUnder) {
1047 addH1 = -fs1.Over()*propU-fs2.Under();
1048 addW1 = (m-fs2.Width())/2;
1049 addH2 = fs1.Under()*prop+fs3.Over();
1050 addW2 = (m-fs3.Width())/2;
1051 } else {
1052 addH1 = fs1.Under()*prop+fs2.Over();
1053 addW1 = (m-fs2.Width())/2;
1054 addH2 = -fs1.Over()*propU-fs3.Under();
1055 addW2 = (m-fs3.Width())/2;
1056 }
1057
1058 Analyse(x+addW2,y+addH2,specNewSize,text+max+1,length-max-1);
1059 Analyse(x+addW1,y+addH1,specNewSize,text+min+1,max-min-1);
1060 }
1061
1062 if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) {
1063 snprintf(&text[min-2],length-(min-2)," ") ;
1064 Analyse(x+pos,y,spec,text,min-1);
1065 } else {
1066 Analyse(x+pos,y,spec,text,min);
1067 }
1068 }
1069
1070 if (!abovePlace) {
1071 if (opPower<opUnder) {
1072 result.Set(fs1.Width()+xfpos+std::max(fs2.Width(),fs3.Width()),
1073 fs1.Over()*fFactorPos+fs2.Height(),
1074 fs1.Under()+fs3.Height()-fs3.Over()*(1-fFactorPos));
1075 } else {
1076 result.Set(fs1.Width()+xfpos+std::max(fs2.Width(),fs3.Width()),
1077 fs1.Over()*fFactorPos+fs3.Height(),
1078 fs1.Under()+fs2.Height()-fs2.Over()*(1-fFactorPos));
1079 }
1080 } else {
1081 if (opPower<opUnder) {
1082 result.Set(std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width())),
1083 fs1.Over()*propU+fs2.Height(),fs1.Under()*prop+fs3.Height());
1084 } else {
1085 result.Set(std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width())),
1086 fs1.Over()*propU+fs3.Height(),fs1.Under()*prop+fs2.Height());
1087 }
1088 }
1089 }
1090 else if (opPower>-1) { // ^ found
1091 Double_t prop=1;
1092 Double_t xfpos = 0. ; //GetHeight()*spec.fSize/5. ;
1093 switch (abovePlace) {
1094 case 1 : //int
1095 prop = 1.75 ; break ;
1096 case 2 : // sum
1097 prop = 1.75; break ;
1098 }
1099 // When increasing prop, the upper indice position is higher
1100 if (!fShow) {
1101 Int_t ltext = opPower ;
1102 if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) {
1103 // upper and lower indice before the character
1104 // like with chemical element
1105 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1106 ltext-- ;
1107 }
1108 fs1 = Anal1(spec,text,ltext);
1110 Savefs(&fs1);
1111 Savefs(&fs2);
1112 } else {
1113 fs2 = Readfs();
1114 fs1 = Readfs();
1115 Int_t pos = 0;
1116 if (!abovePlace){
1117 Double_t over = fs1.Over();
1118 if (over <= 0) over = 1.5*fs2.Over();
1120 } else {
1121 Int_t pos2=0;
1122 if (fs2.Width()>fs1.Width())
1123 pos=Int_t((fs2.Width()-fs1.Width())/2);
1124 else
1125 pos2=Int_t((fs1.Width()-fs2.Width())/2);
1126
1128 }
1129 if (opPower >= 2 && strncmp(&text[opPower-2],"{}",2)==0) {
1130 snprintf(&text[opPower-2],length-(opPower-2)," ") ;
1131 Analyse(x+pos,y,spec,text,opPower-1);
1132 } else {
1133 Analyse(x+pos,y,spec,text,opPower);
1134 }
1135 }
1136
1137 if (!abovePlace)
1138 result.Set(fs1.Width()+xfpos+fs2.Width(),
1139 fs1.Over()*fFactorPos+fs2.Over(),fs1.Under());
1140 else
1141 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Over()*prop+fs2.Height(),fs1.Under());
1142
1143 }
1144 else if (opUnder>-1) { // _ found
1145 Double_t prop = .9; // scale factor for #sum & #frac
1146 Double_t xfpos = 0.;//GetHeight()*spec.fSize/5. ;
1148 // When increasing prop, the lower indice position is lower
1149 if(!fShow) {
1150 Int_t ltext = opUnder ;
1151 if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) {
1152 // upper and lower indice before the character
1153 // like with chemical element
1154 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1155 ltext-- ;
1156 }
1157 fs1 = Anal1(spec,text,ltext);
1159 Savefs(&fs1);
1160 Savefs(&fs2);
1161 } else {
1162 fs2 = Readfs();
1163 fs1 = Readfs();
1164 Int_t pos = 0;
1165 if (!abovePlace)
1166 Analyse(x+fs1.Width()+xfpos,y+fs1.Under()+fs2.Over()*fpos,specNewSize,text+opUnder+1,length-opUnder-1);
1167 else {
1168 Int_t pos2=0;
1169 if (fs2.Width()>fs1.Width())
1170 pos=Int_t((fs2.Width()-fs1.Width())/2);
1171 else
1172 pos2=Int_t((fs1.Width()-fs2.Width())/2);
1173
1175 }
1176 if (opUnder >= 2 && strncmp(&text[opUnder-2],"{}",2)==0) {
1177 snprintf(&text[opUnder-2],length-(opUnder-2)," ") ;
1178 Analyse(x+pos,y,spec,text,opUnder-1);
1179 } else {
1180 Analyse(x+pos,y,spec,text,opUnder);
1181 }
1182 }
1183 if (!abovePlace)
1184 result.Set(fs1.Width()+xfpos+fs2.Width(),fs1.Over(),
1185 fs1.Under()+fs2.Under()+fs2.Over()*fpos);
1186 else
1187 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Over(),fs1.Under()*prop+fs2.Height());
1188 }
1189 else if (opBox) {
1190 Double_t square = GetHeight()*spec.fSize/2;
1191 if (!fShow) {
1192 fs1 = Anal1(spec,text+4,length-4);
1193 } else {
1195 Double_t adjust = GetHeight()*spec.fSize/20;
1196 Double_t x1 = x+adjust ;
1198 Double_t y1 = y;
1204 }
1206 }
1207 else if (opOdot) {
1208 Double_t square = GetHeight()*spec.fSize/2;
1209 if (!fShow) {
1210 fs1 = Anal1(spec,text+5,length-5);
1211 } else {
1212 fs1 = Analyse(x+1.3*square,y,spec,text+5,length-5);
1213 Double_t adjust = GetHeight()*spec.fSize/20;
1214 Double_t r1 = 0.62*square;
1215 Double_t y1 = y-0.3*square-adjust;
1216 DrawCircle(x+0.6*square,y1,r1,spec) ;
1217 DrawCircle(x+0.6*square,y1,r1/100,spec) ;
1218 }
1220 }
1221 else if (opHbar) {
1222 Double_t square = GetHeight()*spec.fSize/2;
1223 if (!fShow) {
1224 fs1 = Anal1(spec,text+5,length-5);
1225 } else {
1227 TText hbar;
1228 hbar.SetTextFont(12);
1229 hbar.SetTextColor(spec.fColor);
1230 hbar.SetTextSize(spec.fSize);
1231 hbar.SetTextAngle(fTextAngle);
1232 hbar.SetTextAlign(11);
1233 Double_t xx, yy;
1234 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1235 hbar.PaintText(xx,yy,"h");
1236 DrawLine(x,y-0.8*square,x+0.75*square,y-square,spec);
1237 }
1239 }
1240 else if (opMinus) {
1241 Double_t square = GetHeight()*spec.fSize/2;
1242 if (!fShow) {
1243 fs1 = Anal1(spec,text+6,length-6);
1244 } else {
1246 TText minus;
1247 minus.SetTextFont(122);
1248 minus.SetTextColor(spec.fColor);
1249 minus.SetTextSize(spec.fSize);
1250 minus.SetTextAngle(fTextAngle);
1251 minus.SetTextAlign(11);
1252 Double_t xx, yy;
1253 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1254 minus.PaintText(xx,yy,"-");
1255 }
1257 }
1258 else if (opPlus) {
1259 Double_t square = GetHeight()*spec.fSize/2;
1260 if (!fShow) {
1261 fs1 = Anal1(spec,text+5,length-5);
1262 } else {
1264 TText plus;
1265 plus.SetTextFont(122);
1266 plus.SetTextColor(spec.fColor);
1267 plus.SetTextSize(spec.fSize);
1268 plus.SetTextAngle(fTextAngle);
1269 plus.SetTextAlign(11);
1270 Double_t xx, yy;
1271 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1272 plus.PaintText(xx,yy,"+");
1273 }
1275 }
1276 else if (opMp) {
1277 Double_t square = GetHeight()*spec.fSize/2;
1278 if (!fShow) {
1279 fs1 = Anal1(spec,text+3,length-3);
1280 } else {
1282 TText mp;
1283 mp.SetTextFont(122);
1284 mp.SetTextColor(spec.fColor);
1285 mp.SetTextSize(spec.fSize);
1286 mp.SetTextAngle(fTextAngle+180);
1287 mp.SetTextAlign(11);
1288 Double_t xx, yy;
1289 Rotate(gPad, spec.fAngle, x+square, y-1.25*square, xx, yy);
1290 mp.PaintText(xx,yy,"\261");
1291 }
1293 }
1294 else if (opPerp) {
1295 Double_t square = GetHeight()*spec.fSize/1.4;
1296 if (!fShow) {
1297 fs1 = Anal1(spec,text+5,length-5);
1298 } else {
1299 fs1 = Analyse(x+0.5*square,y,spec,text+5,length-5);
1300 Double_t x0 = x + 0.50*square;
1301 Double_t x1 = x0 - 0.48*square;
1302 Double_t x2 = x0 + 0.48*square;
1303 Double_t y1 = y + 0.6*square;
1304 Double_t y2 = y1 - 1.3*square;
1306 DrawLine(x0,y1,x0,y2,spec);
1307 }
1308 result = fs1;
1309 }
1310 else if (opBackslash) {
1311 Double_t square = GetHeight()*spec.fSize/2;
1312 if (!fShow) {
1313 fs1 = Anal1(spec,text+10,length-10);
1314 } else {
1315 fs1 = Analyse(x+square,y,spec,text+10,length-10);
1316 TText bs;
1317 bs.SetTextFont(GetTextFont());
1318 bs.SetTextColor(spec.fColor);
1319 bs.SetTextSize(spec.fSize);
1320 bs.SetTextAngle(fTextAngle);
1321 bs.SetTextAlign(11);
1322 Double_t xx, yy;
1323 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1324 bs.PaintText(xx,yy,"\\");
1325 }
1327 }
1328 else if (opParallel) {
1329 Double_t square = GetHeight()*spec.fSize/1.4;
1330 if (!fShow) {
1331 fs1 = Anal1(spec,text+9,length-9);
1332 } else {
1333 fs1 = Analyse(x+0.5*square,y,spec,text+9,length-9);
1334 Double_t x1 = x + 0.15*square;
1335 Double_t x2 = x + 0.45*square;
1336 Double_t y1 = y + 0.3*square;
1337 Double_t y2 = y1- 1.3*square;
1340 }
1342 }
1343 else if (opGreek>-1) {
1345 newSpec.fFont = fItalic ? 152 : 122;
1346 char letter = 97 + opGreek;
1347 Double_t yoffset = 0.; // Greek letter too low
1348 if (opGreek>25) letter -= 58;
1349 if (opGreek == 52) letter = '\241'; //varUpsilon
1350 if (opGreek == 53) letter = '\316'; //epsilon
1351 if (!fShow) {
1352 fs1 = Anal1(newSpec,&letter,1);
1354 Savefs(&fs1);
1355 } else {
1356 fs1 = Readfs();
1359 }
1360 fs1.AddOver(TLatexFormSize(0,yoffset,0)) ;
1361 result = fs1+fs2;
1362 }
1363
1364 else if (opSpec > -1) {
1366 newSpec.fFont = fItalic ? 152 : 122;
1367 char letter = '\243' + opSpec;
1368 if (opSpec == 75) {
1369 newSpec.fFont = GetTextFont();
1370 letter = '\305'; // AA Angstroem
1371 } else if (opSpec == 76) {
1372 newSpec.fFont = GetTextFont();
1373 letter = '\345'; // aa Angstroem
1374 } else if (opSpec == 80)
1375 letter = '\042'; // #forall
1376 else if (opSpec == 81)
1377 letter = '\044'; // #exists
1378 else if (opSpec == 82)
1379 letter = '\055'; // #textendash
1380 else if (opSpec == 83)
1381 letter = '\276'; // #textemdash
1382
1384 props = 1.8 ; // scale factor for #sum(66)
1385 propi = 2.3 ; // scale factor for #int(79)
1386
1387 if (opSpec==66 ) {
1388 newSpec.fSize = spec.fSize*props;
1389 } else if (opSpec==79) {
1390 newSpec.fSize = spec.fSize*propi;
1391 }
1392 if (!fShow) {
1393 fs1 = Anal1(newSpec,&letter,1);
1394 if (opSpec == 79 || opSpec == 66)
1395 fs1.Set(fs1.Width(),fs1.Over()*0.45,fs1.Over()*0.45);
1396
1398 Savefs(&fs1);
1399 } else {
1400 fs1 = Readfs();
1402 if (opSpec!=66 && opSpec!=79)
1403 Analyse(x,y,newSpec,&letter,1);
1404 else {
1405 Analyse(x,y+fs1.Under()/2.,newSpec,&letter,1);
1406 }
1407 }
1408 result = fs1+fs2;
1409 }
1410 else if (opAbove>-1) {
1411 if (!fShow) {
1413 Savefs(&fs1);
1414 } else {
1415 fs1 = Readfs();
1417 Double_t sub = GetHeight()*spec.fSize/14;
1418 switch(opAbove) {
1419 case 0: { // bar
1420 Double_t xx[2], yy[2];
1421 xx[0] = x; xx[1] = x + fs1.Width();
1422 yy[0] = yy[1] = y - sub - fs1.Over();
1423 DrawPolyLine(2, xx, yy, spec, 0.03);
1424 break;
1425 }
1426 case 1: { // vec
1427 Double_t xx[3], yy[3],
1428 dd = GetHeight()*spec.fSize/8, // arrow size
1429 midy = y - sub - fs1.Over() - dd; // middle arrow line
1430 xx[0] = x; xx[1] = x + fs1.Width();
1431 yy[0] = yy[1] = midy;
1432 DrawPolyLine(2, xx, yy, spec, 0.03);
1433 xx[1] = x + fs1.Width(); xx[0] = xx[2] = xx[1] - 2*dd;
1434 yy[0] = midy - dd; yy[1] = midy; yy[2] = midy + dd;
1435 DrawPolyLine(3, xx, yy, spec, 0.03);
1436 break;
1437 }
1438 case 2: { // dot
1439 Double_t dd = std::max(0.5*GetLineWidth(), 0.5*sub), // dot size
1440 midx = x + fs1.Width()/2,
1441 midy = y - sub - fs1.Over() - dd;
1442 Double_t xx[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1443 yy[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1444 DrawPolyLine(5, xx, yy, spec, 10.);
1445 break;
1446 }
1447 case 3: { // hat
1448 Double_t xx[3], yy[3];
1449 xx[1] = x + fs1.Width()/2;
1450 xx[0] = xx[1] - fs1.Width()/3;
1451 xx[2] = xx[1] + fs1.Width()/3;
1452 yy[0] = y - sub - fs1.Over();
1453 yy[1] = yy[0] - 2*sub;
1454 yy[2] = yy[0];
1455 DrawPolyLine(3, xx, yy, spec, 0.03);
1456 break;
1457 }
1458 case 4: { // ddot
1459 Double_t dd = std::max(0.5*GetLineWidth(), 0.5*sub), // dot size
1460 midx = x + fs1.Width()/2 - 1.5*sub,
1461 midy = y - sub - fs1.Over() - dd;
1462 Double_t xx1[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1463 yy1[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1464 DrawPolyLine(5, xx1, yy1, spec, 10.);
1465 midx = x + fs1.Width()/2 + 1.5*sub;
1466 Double_t xx2[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1467 yy2[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1468 DrawPolyLine(5, xx2, yy2, spec, 10.);
1469 break;
1470 }
1471 case 5: { // acute
1472 Double_t xx[2], yy[2];
1473 xx[0] = x + fs1.Width()/2; xx[1] = xx[0] + 3*sub;
1474 yy[0] = y - sub - fs1.Over();
1475 yy[1] = yy[0] - 2.5*sub;
1476 DrawPolyLine(2, xx, yy, spec, 0.03);
1477 break;
1478 }
1479 case 6: { // grave
1480 Double_t xx[2], yy[2];
1481 xx[0] = x + fs1.Width()/2 + sub; xx[1] = xx[0] - 2*sub;
1482 yy[0] = y - sub - fs1.Over();
1483 yy[1] = yy[0] - 2*sub;
1484 DrawPolyLine(2, xx, yy, spec, 0.03);
1485 break;
1486 }
1487 case 7: { // check
1488 Double_t xx[3], yy[3];
1489 xx[1] = x+fs1.Width()/2; xx[0] = xx[1] - 2*sub; xx[2] = xx[1] + 2*sub;
1490 yy[1] = y - sub - fs1.Over();
1491 yy[0] = yy[2] = yy[1] - 2*sub;
1492 DrawPolyLine(3, xx, yy, spec, 0.03);
1493 break;
1494 }
1495 case 8: { // tilde
1496 Double_t x2 = x+fs1.Width()/2, y2 = y -fs1.Over();
1497 // tilde must be drawn separately on screen and on PostScript
1498 // because an adjustment is required along Y for PostScript.
1499
1500 Double_t xx, yy;
1501 if (auto ps = gPad->GetPainter()->GetPS()) {
1502 if (!strstr(ps->GetTitle(), "IMG"))
1503 y2 -= 4*sub;
1504 Rotate(gPad, spec.fAngle, x2, y2, xx, yy);
1505 ps->SetTextAlign(22);
1506 ps->Text(xx, yy, "~");
1507 } else {
1508 Rotate(gPad, spec.fAngle, x2, y2, xx, yy);
1509 // TODO: use pad painter SetAttText and DrawText directly
1510 TText tilde;
1511 tilde.SetTextFont(fTextFont);
1512 tilde.SetTextColor(spec.fColor);
1513 tilde.SetTextSize(0.9*spec.fSize);
1514 tilde.SetTextAlign(22);
1515 tilde.SetTextAngle(fTextAngle);
1516 tilde.PaintText(xx,yy,"~");
1517 }
1518 break;
1519 }
1520 case 9: { // slash
1521 Double_t xx[2], yy[2];
1522 xx[0] = x + 0.8*fs1.Width();
1523 yy[0] = y - fs1.Over() - sub;
1524 xx[1] = x + 0.3*fs1.Width();
1525 yy[1] = yy[0] + fs1.Height() + 2*sub;
1526 DrawPolyLine(2, xx, yy, spec, 0.03);
1527 break;
1528 }
1529 }
1530 }
1531 Double_t div = 3;
1532 if (opAbove==1) div=4;
1533 result.Set(fs1.Width(),fs1.Over()+GetHeight()*spec.fSize/div,fs1.Under());
1534 }
1535 else if (opSquareBracket) { // operator #[]{arg}
1536 Double_t l = GetHeight()*spec.fSize/4;
1537 Double_t l2 = l/2 ;
1538 if (!fShow) {
1539 fs1 = Anal1(spec,text+3,length-3);
1540 Savefs(&fs1);
1541 } else {
1542 fs1 = Readfs();
1543 Analyse(x+l2+l,y,spec,text+3,length-3);
1544 DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec);
1545 DrawLine(x+l2,y-fs1.Over(),x+l2+l,y-fs1.Over(),spec);
1546 DrawLine(x+l2,y+fs1.Under(),x+l2+l,y+fs1.Under(),spec);
1547 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec);
1548 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+l,y-fs1.Over(),spec);
1549 DrawLine(x+l2+fs1.Width()+2*l,y+fs1.Under(),x+l2+fs1.Width()+l,y+fs1.Under(),spec);
1550 }
1551 result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1552 }
1553 else if (opParen) { // operator #(){arg}
1554 Double_t l = GetHeight()*spec.fSize/4;
1555 Double_t radius2,radius1 , dw, l2 = l/2 ;
1556 Double_t angle = 35 ;
1557 if (!fShow) {
1558 fs1 = Anal1(spec,text+3,length-3);
1559 Savefs(&fs1);
1560 radius2 = fs1.Height() ;
1561 radius1 = radius2 * 2 / 3;
1562 dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ;
1563 } else {
1564 fs1 = Readfs();
1565 radius2 = fs1.Height();
1566 radius1 = radius2 * 2 / 3;
1567 dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ;
1568 Double_t x1 = x+l2+radius1 ;
1569 Double_t x2 = x+5*l2+2*dw+fs1.Width()-radius1 ;
1570 Double_t y1 = y - (fs1.Over() - fs1.Under())/2. ;
1573 Analyse(x+3*l2+dw,y,spec,text+3,length-3);
1574 }
1575 // result = TLatexFormSize(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1576 result.Set(fs1.Width()+3*l+2*dw,fs1.Over(),fs1.Under());
1577 }
1578 else if (opAbs) { // operator #||{arg}
1579 Double_t l = GetHeight()*spec.fSize/4;
1580 Double_t l2 = l/2 ;
1581 if (!fShow) {
1582 fs1 = Anal1(spec,text+3,length-3);
1583 Savefs(&fs1);
1584 } else {
1585 fs1 = Readfs();
1586 Analyse(x+l2+l,y,spec,text+3,length-3);
1587 DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec);
1588 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec);
1589 }
1590 result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1591 }
1592 else if (opBigCurly) { // big curly bracket #{}{arg}
1593 Double_t l = GetHeight()*spec.fSize/4;
1594 Double_t l2 = l/2 ;
1595 Double_t l8 , ltip;
1596
1597 if (!fShow) {
1598 fs1 = Anal1(spec,text+3,length-3);
1599 l8 = fs1.Height()/8 ;
1600 ltip = TMath::Min(l8,l) ;
1601 l = ltip ;
1602 Savefs(&fs1);
1603 } else {
1604 fs1 = Readfs();
1605 Double_t y2 = y + (fs1.Under()-fs1.Over())/2 ;
1606 l8 = fs1.Height()/8 ;
1607 ltip = TMath::Min(l8,l) ;
1608 l = ltip ;
1609 Analyse(x+l+ltip+l2,y,spec,text+3,length-3);
1610 // Draw open curly bracket
1611 // Vertical lines
1612 DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip,y2-ltip,spec);
1613 DrawLine(x+l2+ltip,y2+ltip,x+l2+ltip,y+fs1.Under(),spec);
1614 // top and bottom lines
1615 DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip+l,y-fs1.Over(),spec);
1616 DrawLine(x+l2+ltip,y+fs1.Under(),x+l2+ltip+l,y+fs1.Under(),spec);
1617 // < sign
1620
1621 // Draw close curly bracket
1622 // vertical lines
1623 DrawLine(x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y2-ltip,spec);
1624 DrawLine(x+l2+ltip+fs1.Width()+2*l,y2+ltip,x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec);
1625 // Top and bottom lines
1626 DrawLine(x+l2+fs1.Width()+l+ltip,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),spec);
1627 DrawLine(x+l2+fs1.Width()+l+ltip,y+fs1.Under(),x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec);
1628 // > sign
1629 DrawLine(x+l2+ltip+2*l+fs1.Width(),y2-ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec);
1630 DrawLine(x+l2+ltip+2*l+fs1.Width(),y2+ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec);
1631 }
1632 result.Set(fs1.Width()+3*l+2*ltip,fs1.Over(),fs1.Under());
1633 }
1634 else if (opFrac>-1) { // \frac found
1635 if (opCurlyCurly==-1) { // }{ not found
1636 // arguments missing for \frac
1637 fError = "Missing denominator for #frac";
1638 delete[] text;
1639 return TLatexFormSize(0,0,0);
1640 }
1641 Double_t height = GetHeight()*spec.fSize/8;
1642 if (!fShow) {
1645 Savefs(&fs1);
1646 Savefs(&fs2);
1647 } else {
1648 fs2 = Readfs();
1649 fs1 = Readfs();
1651 if (fs1.Width()<fs2.Width()) {
1652 addW1 = (fs2.Width()-fs1.Width())/2;
1653 addW2 = 0;
1654 } else {
1655 addW1 = 0;
1656 addW2 = (fs1.Width()-fs2.Width())/2;
1657 }
1658 Analyse(x+addW2,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // denominator
1659 Analyse(x+addW1,y-fs1.Under()-3*height,spec,text+opFrac+6,opCurlyCurly-opFrac-6); //numerator
1660
1661 DrawLine(x,y-2*height,x+std::max(fs1.Width(),fs2.Width()),y-2*height,spec);
1662 }
1663
1664 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
1665
1666 }
1667 else if (opSplitLine>-1) { // \splitline found
1668 if (opCurlyCurly==-1) { // }{ not found
1669 // arguments missing for \splitline
1670 fError = "Missing second line for #splitline";
1671 delete[] text;
1672 return TLatexFormSize(0,0,0);
1673 }
1674 Double_t height = GetHeight()*spec.fSize/8;
1675 if (!fShow) {
1678 Savefs(&fs1);
1679 Savefs(&fs2);
1680 } else {
1681 fs2 = Readfs();
1682 fs1 = Readfs();
1683 Analyse(x,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // second line
1684 Analyse(x,y-fs1.Under()-3*height,spec,text+opSplitLine+11,opCurlyCurly-opSplitLine-11); //first line
1685 }
1686
1687 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
1688
1689 }
1690 else if (opSqrt>-1) { // \sqrt found
1691 if (!fShow) {
1692 if (opSquareCurly>-1) {
1693 // power nth #sqrt[n]{arg}
1696 Savefs(&fs1);
1697 Savefs(&fs2);
1698 result.Set(fs2.Width()+ GetHeight()*spec.fSize/10+std::max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width()),
1699 fs2.Over()+fs1.Height()+GetHeight()*spec.fSize/4,fs2.Under());
1700 } else {
1702 Savefs(&fs1);
1703 result.Set(fs1.Width()+GetHeight()*spec.fSize/2,fs1.Over()+GetHeight()*spec.fSize/4,fs1.Under());
1704 }
1705 } else {
1706 if (opSquareCurly>-1) { // ]{
1707 fs2 = Readfs();
1708 fs1 = Readfs();
1709 Double_t pas = std::max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width());
1710 Double_t pas2 = pas + GetHeight()*spec.fSize/10;
1711 Double_t y1 = y-fs2.Over() ;
1712 Double_t y2 = y+fs2.Under() ;
1713 Double_t y3 = y1-GetHeight()*spec.fSize/4;
1715 Analyse(x,y-fs2.Over()-fs1.Under(),specNewSize,text+opSqrt+6,opSquareCurly-opSqrt-6); // indice
1716 DrawLine(x,y1,x+pas,y2,spec);
1718 DrawLine(x+pas,y3,x+pas2+fs2.Width(),y3,spec);
1719 } else {
1720 fs1 = Readfs();
1721 Double_t x1 = x+GetHeight()*spec.fSize*2/5 ;
1722 Double_t x2 = x+GetHeight()*spec.fSize/2+fs1.Width() ;
1723 Double_t y1 = y-fs1.Over() ;
1724 Double_t y2 = y+fs1.Under() ;
1725 Double_t y3 = y1-GetHeight()*spec.fSize/4;
1726
1728
1730 SetLineWidth(1);
1731 Double_t dx = (y2-y3)/8;
1732 UInt_t a,d;
1734 if (a>12) SetLineWidth(std::max(2,(Int_t)(dx/2)));
1735 DrawLine(x1-2*dx,y1,x1-dx,y2,spec);
1736 if (a>12) SetLineWidth(std::max(1,(Int_t)(dx/4)));
1740 }
1741 }
1742 }
1743 else if (opColor>-1) { // \color found
1744 if (opSquareCurly==-1) {
1745 // color number is not specified
1746 fError = "Missing color number. Syntax is #color[(Int_t)nb]{ ... }";
1747 delete[] text;
1748 return TLatexFormSize(0,0,0);
1749 }
1753 nb[opSquareCurly-opColor-7] = 0;
1754 if (sscanf(nb,"%d",&newSpec.fColor) < 1) {
1755 delete[] nb;
1756 // color number is invalid
1757 fError = "Invalid color number. Syntax is #color[(Int_t)nb]{ ... }";
1758 delete[] text;
1759 return TLatexFormSize(0,0,0);
1760 }
1761 delete[] nb;
1762 if (!fShow) {
1764 } else {
1766 }
1767 }
1768 else if (opUrl>-1) { // \url found
1769 if (opSquareCurly==-1) {
1770 // url is not specified
1771 fError = "Missing url. Syntax is #url[http://...]{ ... }";
1772 delete[] text;
1773 return TLatexFormSize(0,0,0);
1774 }
1776 fName = TString(text + opUrl + 5, opSquareCurly - opUrl - 5);
1777 if (!fShow) {
1779 } else {
1781 }
1782 fName = "";
1783 }
1784 else if (opFont>-1) { // \font found
1785 if (opSquareCurly==-1) {
1786 // font number is not specified
1787 fError = "Missing font number. Syntax is #font[nb]{ ... }";
1788 delete[] text;
1789 return TLatexFormSize(0,0,0);
1790 }
1794 nb[opSquareCurly-opFont-6] = 0;
1795 if (sscanf(nb,"%d",&newSpec.fFont) < 1) {
1796 delete[] nb;
1797 // font number is invalid
1798 fError = "Invalid font number. Syntax is #font[(Int_t)nb]{ ... }";
1799 delete[] text;
1800 return TLatexFormSize(0,0,0);
1801 }
1802 delete[] nb;
1803 if (!fShow) {
1805 } else {
1807 }
1808 }
1809 else if (opKern>-1) { // #kern found
1810 if (opSquareCurly==-1) {
1811 // horizontal shift is not specified
1812 fError = "Missing horizontal shift number. Syntax is #kern[dx]{ ... }";
1813 delete[] text;
1814 return TLatexFormSize(0,0,0);
1815 }
1818 dxc[opSquareCurly-opKern-6] = 0;
1819 Float_t dx = 0;
1820 if (sscanf(dxc,"%f",&dx) < 1) {
1821 delete[] dxc;
1822 // horizontal shift number is invalid
1823 fError = "Invalid horizontal shift number. Syntax is #kern[(Float_t)dx]{ ... }";
1824 delete[] text;
1825 return TLatexFormSize(0,0,0);
1826 }
1827 delete[] dxc;
1828 if (!fShow) {
1830 Savefs(&fs1);
1831 Double_t ddx = dx * fs1.Width();
1832 result = TLatexFormSize(fs1.Width() + ddx, fs1.Over(), fs1.Under());
1833 } else {
1834 fs1 = Readfs();
1835 Double_t ddx = dx * fs1.Width();
1837 }
1838 }
1839 else if (opLower>-1) { // #lower found
1840 if (opSquareCurly==-1) {
1841 // vertical shift is not specified
1842 fError = "Missing vertical shift number. Syntax is #lower[dy]{ ... }";
1843 delete[] text;
1844 return TLatexFormSize(0,0,0);
1845 }
1848 dyc[opSquareCurly-opLower-7] = 0;
1849 Float_t dy = 0;
1850 if (sscanf(dyc,"%f",&dy) < 1) {
1851 delete[] dyc;
1852 // vertical shift number is invalid
1853 fError = "Invalid vertical shift number. Syntax is #lower[(Float_t)dy]{ ... }";
1854 delete[] text;
1855 return TLatexFormSize(0,0,0);
1856 }
1857 delete[] dyc;
1858 if (!fShow) {
1860 Savefs(&fs1);
1861 Double_t ddy = dy * (fs1.Over() + fs1.Under());
1862 result = TLatexFormSize(fs1.Width(), fs1.Over() + ddy, fs1.Under() + ddy);
1863 } else {
1864 fs1 = Readfs();
1865 Double_t ddy = dy * (fs1.Over() + fs1.Under());
1867 }
1868 }
1869 else if (opScale>-1) { // \scale found
1870 if (opSquareCurly==-1) {
1871 // scale factor is not specified
1872 fError = "Missing scale factor. Syntax is #scale[(Double_t)nb]{ ... }";
1873 delete[] text;
1874 return TLatexFormSize(0,0,0);
1875 }
1879 nb[opSquareCurly-opScale-7] = 0;
1880 if (sscanf(nb,"%lf",&newSpec.fSize) < 1) {
1881 delete[] nb;
1882 // scale factor is invalid
1883 fError = "Invalid scale factor. Syntax is #factor[(Double_t)nb]{ ... }";
1884 delete[] text;
1885 return TLatexFormSize(0,0,0);
1886 }
1887 newSpec.fSize *= spec.fSize;
1888 delete[] nb;
1889 if (!fShow) {
1891 } else {
1893 }
1894 }
1895 else if (opBf>-1) { // operator #bf{arg}
1897 Int_t lut[] = {3, 13, 1, 6, 7, 4, 5, 10, 11, 8, 9, 12, 2, 14, 15};
1898 Int_t fontId = (newSpec.fFont/10);
1899 if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1];
1900 newSpec.fFont = fontId*10 + newSpec.fFont%10;
1901 if (!fShow) {
1902 fs1 = Anal1(newSpec,text+3,length-3);
1903 Savefs(&fs1);
1904 } else {
1905 fs1 = Readfs();
1907 }
1908 result = fs1;
1909 }
1910 else if (opMbox>-1) { // dummy operator #mbox{arg}
1912 if (!fShow) {
1913 fs1 = Anal1(newSpec,text+5,length-5);
1914 Savefs(&fs1);
1915 } else {
1916 fs1 = Readfs();
1918 }
1919 result = fs1;
1920 }
1921 else if (opIt>-1) { // operator #it{arg}
1923 Int_t lut[] = {13, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 15, 1, 14, 12};
1924 Int_t fontId = (newSpec.fFont/10);
1925 if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1];
1926 newSpec.fFont = fontId*10 + newSpec.fFont%10;
1927 fItalic = !fItalic;
1928 if (!fShow) {
1929 fs1 = Anal1(newSpec,text+3,length-3);
1930 Savefs(&fs1);
1931 } else {
1932 fs1 = Readfs();
1934 }
1935 fItalic = !fItalic;
1936 result = fs1;
1937 }
1938 else { // no operators found, it is a character string
1939 SetTextSize(spec.fSize);
1940 SetTextAngle(spec.fAngle);
1941 SetTextColor(spec.fColor);
1942 SetTextFont(spec.fFont);
1943 SetTextAlign(11);
1945 UInt_t w=0,h=0;
1946
1947 Int_t leng = strlen(text) ;
1948
1949 quote1 = quote2 = kFALSE ;
1950 Char_t *p ;
1951 for (i=0 ; i<leng ; i++) {
1952 switch (text[i]) {
1953 case '\'' : quote1 = !quote1 ; break ; // single quote symbol not correctly interpreted when PostScript
1954 case '"' : quote2 = !quote2 ; break ;
1955 }
1956 //if (quote1 || quote2) continue ;
1957 if (text[i] == '@') { // @ symbol not correctly interpreted when PostScript
1958 p = &text[i] ;
1959 if ( *(p+1) == '{' || *(p+1) == '}' || *(p+1) == '[' || *(p+1) == ']') {
1960 while (*p != 0) {
1961 *p = *(p+1) ; p++ ;
1962 }
1963 leng-- ;
1964 }
1965 }
1966 }
1967 text[leng] = 0 ;
1968
1969 if (fShow) {
1970 // paint the Latex sub-expression per sub-expression
1971 Double_t xx, yy;
1972 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1973 if (fName.Length() > 0) gPad->PaintTextUrl(xx, yy, text, fName.Data());
1974 else gPad->PaintText(xx, yy, text);
1975 } else {
1977 Double_t width = w;
1978 UInt_t a,d;
1980 fs1.Set(width,a,d);
1981 }
1982
1983 result = fs1;
1984 }
1985
1986 delete[] text;
1987
1988 return result;
1989}
1990
1991////////////////////////////////////////////////////////////////////////////////
1992/// Make a copy of this object with the new parameters
1993/// And copy object attributes
1994
1996{
1997 TLatex *newtext = new TLatex(x, y, text);
2000 newtext->SetBit(kCanDelete);
2001 if (TestBit(kTextNDC)) newtext->SetNDC();
2002 newtext->AppendPad();
2003 return newtext;
2004}
2005
2006////////////////////////////////////////////////////////////////////////////////
2007/// Draw this TLatex with new coordinates in NDC.
2008
2010{
2012 newtext->SetNDC();
2013 return newtext;
2014}
2015
2016
2017////////////////////////////////////////////////////////////////////////////////
2018/// Draw a poly line in a Latex formula
2019/// Is scale_width parameter >=1, fill area will be drawn
2020/// Otherwise line width will be scaled proportional to current font size
2021/// If not specified - default line width will be used
2023{
2024 if (!gPad)
2025 return;
2026
2027 Rotate(gPad, spec.fAngle, npoints, xx, yy);
2028
2029 if (scale_width >= 1.) {
2030 TAttFill fill(spec.fColor, 1001);
2031 fill.Modify();
2032 gPad->PaintFillArea(npoints, xx, yy, "f");
2033 return;
2034 }
2035
2036 auto prevWidth = GetLineWidth();
2037 if (scale_width) {
2038 Int_t lineWidth = TMath::Nint(GetHeight() * spec.fSize * scale_width);
2039 SetLineWidth(lineWidth > prevWidth ? lineWidth : prevWidth);
2040 }
2041
2042 SetLineColor(spec.fColor);
2044
2045 gPad->PaintPolyLine(npoints, xx, yy);
2046 if (scale_width)
2048}
2049
2050
2051////////////////////////////////////////////////////////////////////////////////
2052/// Draw a line in a Latex formula
2053
2055{
2056 if (!gPad) return;
2057 Double_t xx[2] = { x1, x2 };
2058 Double_t yy[2] = { y1, y2 };
2059 Rotate(gPad, spec.fAngle, 2, xx, yy);
2060 SetLineColor(spec.fColor);
2062 gPad->PaintLine(xx[0], yy[0], xx[1], yy[1]);
2063}
2064
2065////////////////////////////////////////////////////////////////////////////////
2066/// Draw an arc of ellipse in a Latex formula (right or left parenthesis)
2067
2069{
2070 if (!gPad)
2071 return;
2072 if (r < 1)
2073 r = 1;
2074
2075 const Int_t np = 40;
2076 Double_t dphi = 2*kPI/np;
2077 Double_t x[np+3], y[np+3];
2078
2079 SetLineColor(spec.fColor);
2080 TAttLine::Modify(); //Change line attributes only if necessary
2081
2082 for (Int_t i = 0; i <= np; i++) {
2083 Double_t angle = i*dphi;
2084 x[i] = x1 + r*TMath::Cos(angle);
2085 y[i] = y1 + r*TMath::Sin(angle);
2086 }
2087 Rotate(gPad, spec.fAngle, np+1, x, y);
2088
2089 gPad->PaintPolyLine(np+1, x, y);
2090}
2091
2092////////////////////////////////////////////////////////////////////////////////
2093/// Draw an arc of ellipse in a Latex formula (right or left parenthesis)
2094
2097{
2098 if (!gPad)
2099 return;
2100 if (r1 < 1)
2101 r1 = 1;
2102 if (r2 < 1)
2103 r2 = 1;
2104
2105 const Int_t np = 40;
2106 Double_t dphi = (phimax-phimin)*kPI/(180*np);
2107 Double_t x[np+3], y[np+3];
2108
2109 SetLineColor(spec.fColor);
2110 TAttLine::Modify(); //Change line attributes only if necessary
2111
2112 for (Int_t i = 0; i <= np; i++) {
2113 Double_t angle = phimin*kPI/180 + i*dphi;
2114 x[i] = x1 + r1*TMath::Cos(angle);
2115 y[i] = y1 + r2*TMath::Sin(angle);
2116 }
2117
2118 Rotate(gPad, spec.fAngle, np+1, x, y);
2119
2120 gPad->PaintPolyLine(np+1,x,y);
2121}
2122
2123////////////////////////////////////////////////////////////////////////////////
2124/// Paint.
2125
2126void TLatex::Paint(Option_t *)
2127{
2128 if (!gPad) return ;
2129 Double_t xsave = fX;
2130 Double_t ysave = fY;
2131 if (TestBit(kTextNDC)) {
2132 fX = gPad->GetX1() + xsave*(gPad->GetX2() - gPad->GetX1());
2133 fY = gPad->GetY1() + ysave*(gPad->GetY2() - gPad->GetY1());
2135 } else {
2136 PaintLatex(gPad->XtoPad(fX),gPad->YtoPad(fY),GetTextAngle(),GetTextSize(),GetTitle());
2137 }
2138 fX = xsave;
2139 fY = ysave;
2140}
2141
2142////////////////////////////////////////////////////////////////////////////////
2143/// Main drawing function
2144///
2145/// Warning: Unlike most others "XYZ::PaintXYZ" methods, PaintLatex modifies
2146/// the TLatex data members.
2147
2149{
2150 if (size<=0 || strlen(text1) <= 0) return; // do not paint empty text or text with size <= 0
2151
2152 TAttText::Modify(); // Change text attributes only if necessary.
2153
2154 auto ps = gPad->GetPainter()->GetPS();
2155
2156 if (ps && ps->InheritsFrom("TTeXDump")) {
2157 TString t(text1);
2158 if (t.Index("#")>=0 || t.Index("^")>=0 || t.Index("\\")>=0) {
2159 t.ReplaceAll("#LT","\\langle");
2160 t.ReplaceAll("#GT","\\rangle");
2161 t.ReplaceAll("#club","\\clubsuit");
2162 t.ReplaceAll("#spade","\\spadesuit");
2163 t.ReplaceAll("#heart","\\heartsuit");
2164 t.ReplaceAll("#diamond","\\diamondsuit");
2165 t.ReplaceAll("#voidn","\\wp");
2166 t.ReplaceAll("#voidb","f");
2167 t.ReplaceAll("#ocopyright","\\copyright");
2168 t.ReplaceAll("#trademark","TM");
2169 t.ReplaceAll("#void3","TM");
2170 t.ReplaceAll("#oright","R");
2171 t.ReplaceAll("#void1","R");
2172 t.ReplaceAll("#3dots","\\ldots");
2173 t.ReplaceAll("#lbar","\\mid");
2174 t.ReplaceAll("#bar","\\wwbar");
2175 t.ReplaceAll("#void8","\\mid");
2176 t.ReplaceAll("#divide","\\div");
2177 t.ReplaceAll("#Jgothic","\\Im");
2178 t.ReplaceAll("#Rgothic","\\Re");
2179 t.ReplaceAll("#doublequote","\"");
2180 t.ReplaceAll("#plus","+");
2181 t.ReplaceAll("#minus","-");
2182 t.ReplaceAll("#/","/");
2183 t.ReplaceAll("#upoint",".");
2184 t.ReplaceAll("#aa","\\mbox{\\aa}");
2185 t.ReplaceAll("#AA","\\mbox{\\AA}");
2186
2187 t.ReplaceAll("#omicron","o");
2188 t.ReplaceAll("#Alpha","A");
2189 t.ReplaceAll("#Beta","B");
2190 t.ReplaceAll("#Epsilon","E");
2191 t.ReplaceAll("#Zeta","Z");
2192 t.ReplaceAll("#Eta","H");
2193 t.ReplaceAll("#Iota","I");
2194 t.ReplaceAll("#Kappa","K");
2195 t.ReplaceAll("#Mu","M");
2196 t.ReplaceAll("#Nu","N");
2197 t.ReplaceAll("#Omicron","O");
2198 t.ReplaceAll("#Rho","P");
2199 t.ReplaceAll("#Tau","T");
2200 t.ReplaceAll("#Chi","X");
2201 t.ReplaceAll("#varomega","\\varpi");
2202
2203 t.ReplaceAll("#varUpsilon","?");
2204 t.ReplaceAll("#corner","?");
2205 t.ReplaceAll("#ltbar","?");
2206 t.ReplaceAll("#bottombar","?");
2207 t.ReplaceAll("#notsubset","?");
2208 t.ReplaceAll("#arcbottom","?");
2209 t.ReplaceAll("#cbar","?");
2210 t.ReplaceAll("#arctop","?");
2211 t.ReplaceAll("#topbar","?");
2212 t.ReplaceAll("#arcbar","?");
2213 t.ReplaceAll("#downleftarrow","?");
2214 t.ReplaceAll("#splitline","\\genfrac{}{}{0pt}{}");
2215
2216 t.ReplaceAll("#","\\");
2217 t.ReplaceAll("%","\\%");
2218 }
2219 ps->SetTextAngle(angle);
2220 ps->Text(x, y, t.Data());
2221 } else {
2223 }
2224}
2225
2226////////////////////////////////////////////////////////////////////////////////
2227/// Drawing function
2228
2230{
2231 if (!gPad)
2232 return 0;
2234 if(newText.Length() == 0)
2235 return 0;
2236 newText.ReplaceAll("#hbox","#mbox");
2237
2238 fError = nullptr;
2240 Error("PaintLatex1", "%s\n==> %s", fError, text1);
2241 return 0;
2242 }
2243 fError = nullptr;
2244
2245 // Do not use Latex if font is low precision.
2246 if (fTextFont % 10 < 2) {
2247 gPad->GetPainter()->SetTextAngle(angle);
2248 gPad->PaintText(x, y, text1);
2249 return 1;
2250 }
2251
2252 // Paint the text using TMathText if contains a "\"
2253 if (strstr(text1,"\\")) {
2254 auto ps = gPad->GetPainter()->GetPS();
2255 // If PDF or SVG, paint using TLatex
2256 if (ps && (ps->InheritsFrom("TPDF") || ps->InheritsFrom("TSVG"))) {
2257 newText.ReplaceAll("\\","#");
2258 } else {
2259 TMathText tm;
2260 tm.SetTextAlign(GetTextAlign());
2261 tm.SetTextFont(GetTextFont());
2262 tm.SetTextColor(GetTextColor());
2263 tm.PaintMathText(x, y, angle, size, text1);
2264 return 1;
2265 }
2266 }
2267
2270 if (fTextFont % 10 > 2) {
2272 SetTextFont(10*(saveFont/10) + 2);
2273 }
2274
2275 Int_t length = newText.Length();
2276 const Char_t *text = newText.Data();
2277
2278 Double_t xsave = fX;
2279 Double_t ysave = fY;
2280 fX = x;
2281 fY = y;
2282 gPad->XYtoAbsPixel(fX, fY, x, y);
2283 fShow = kFALSE;
2285
2286 fOriginSize = size;
2287
2288 // Get current line attributes.
2291
2293 spec.fAngle = angle;
2294 spec.fSize = size;
2295 spec.fColor = GetTextColor();
2296 spec.fFont = GetTextFont();
2300 if (fError) {
2301 Error("PaintLatex1", "%s\n==> %s", fError, text);
2302 } else {
2303 fShow = kTRUE;
2304 newSpec.fSize = size;
2305
2306 switch (valign) {
2307 case 0: y -= fs.Under(); break;
2308 case 1: break;
2309 case 2: y += fs.Height()*0.5-fs.Under() + 1.; break;
2310 case 3: y += fs.Over(); break;
2311 }
2312 switch (halign) {
2313 case 2: x -= fs.Width()/2; break;
2314 case 3: x -= fs.Width(); break;
2315 }
2317 }
2318
2322 SetTextColor(spec.fColor);
2326 fTabSize.clear();
2327 fX = xsave;
2328 fY = ysave;
2329 return fError ? 0 : 1;
2330}
2331
2332////////////////////////////////////////////////////////////////////////////////
2333/// Check if the Latex syntax is correct
2334
2336{
2337 const Char_t *kWord1[] = {"{}^{","{}_{","^{","_{","#scale{","#color{","#url{","#font{","#sqrt{","#[]{","#{}{","#||{",
2338 "#bar{","#vec{","#dot{","#hat{","#ddot{","#acute{","#grave{","#check{","#tilde{","#slash{","#bf{","#it{","#mbox{",
2339 "\\scale{","\\color{","\\font{","\\sqrt{","\\[]{","\\{}{","\\||{","#(){","\\(){",
2340 "\\bar{","\\vec{","\\dot{","\\hat{","\\ddot{","\\acute{","\\grave{","\\check{","\\bf{","\\it{","\\mbox{"}; // check for }
2341 const Char_t *kWord2[] = {"#scale[","#color[","#url[","#font[","#sqrt[","#kern[","#lower[","\\scale[","\\color[","\\font[","\\sqrt[","\\kern[","\\lower["}; // check for ]{ + }
2342 const Char_t *kWord3[] = {"#frac{","\\frac{","#splitline{","\\splitline{"}; // check for }{ then }
2343 const Char_t *kLeft1[] = {"#left[","\\left[","#left{","\\left{","#left|","\\left|","#left(","\\left("};
2344 const Char_t *kLeft2[] = {"#[]{","#[]{","#{}{","#{}{","#||{","#||{","#(){","#(){"};
2345 const Char_t *kRight[] = {"#right]","\\right]","#right}","\\right}","#right|","\\right|","#right)","\\right)"};
2346 const Int_t lkWord1[] = {4,4,2,2,7,7,5,6,6,4,4,4,5,5,5,5,6,7,7,7,7,7,4,4,6,7,7,6,6,4,4,4,4,4,5,5,5,5,6,7,7,7,4,4,6};
2347 const Int_t lkWord2[] = {7,7,5,6,6,6,7,7,7,6,6,6,7} ;
2348 const Int_t lkWord3[] = {6,6,11,11} ;
2349 Int_t nkWord1 = 45, nkWord2 = 13, nkWord3 = 4;
2350 Int_t i,k ;
2352 Int_t lLeft1 = 6 ;
2353 Int_t lLeft2 = 4 ;
2354 Int_t lRight = 7 ;
2355 nLeft1 = nRight = 8 ;
2356 nOfLeft = nOfRight = 0 ;
2357
2358 Char_t buf[11] ; for (i=0;i<11;i++) buf[i]=0;
2359 Bool_t opFound ;
2360 Int_t opFrac = 0;
2361 Int_t length = text.Length() ;
2362
2365 Int_t error = 0 ;
2367
2368 // first find and replace all occurrences of "kLeft1" keyword by "kLeft2" keyword,
2369 // and all occurrences of "kRight" keyword by "}".
2370 i = 0 ;
2371 while (i < length) {
2372 // The string in 'buf' does not need to be null terminated,
2373 // we will only check with strncmp.
2374 strncpy(buf,&text[i],TMath::Min(7,length-i));
2375 opFound = kFALSE ;
2376 for (k = 0 ; k < nLeft1 ; k++) {
2377 if (strncmp(buf,kLeft1[k],lLeft1)==0) {
2378 nOfLeft++ ;
2379 i+=lLeft1 ;
2380 opFound = kTRUE ;
2381 break ;
2382 }
2383 }
2384 if (opFound) continue ;
2385
2386 for(k=0;k<nRight;k++) {
2387 if (strncmp(buf,kRight[k],lRight)==0) {
2388 nOfRight++ ;
2389 i+=lRight ;
2390 opFound = kTRUE ;
2391 break ;
2392 }
2393 }
2394 if (!opFound) i++ ;
2395 }
2396 if (nOfLeft != nOfRight) {
2397 printf(" nOfLeft = %d, nOfRight = %d\n",nOfLeft,nOfRight) ;
2398 error = 1 ;
2399 fError = "Operators \"#left\" and \"#right\" don't match !" ;
2400 goto ERROR_END ;
2401 }
2402
2403 for (k = 0 ; k < nLeft1 ; k++) {
2404 text.ReplaceAll(kLeft1[k],lLeft1,kLeft2[k],lLeft2) ;
2405 }
2406 for (k = 0 ; k < nRight ; k++) {
2407 text.ReplaceAll(kRight[k],lRight,"}",1) ;
2408 }
2409 length = text.Length() ;
2410
2412 while (i< length){
2413 switch (text[i]) {
2414 case '"' : quote1 = !quote1 ; break ;
2415 case '\'': quote2 = !quote2 ; break ;
2416 }
2417 // The string in 'buf' does not need to be null terminated,
2418 // we will only check with strncmp
2419 strncpy(buf,&text[i],TMath::Min(11,length-i));
2420 opFound = kFALSE ;
2421
2422 for(k=0;k<nkWord1;k++) {
2423 if (strncmp(buf,kWord1[k],lkWord1[k])==0) {
2424 nOfKW1++ ;
2425 i+=lkWord1[k] ;
2426 opFound = kTRUE ;
2427 nOfCurlyBracket++ ;
2428 break ;
2429 }
2430 }
2431 if (opFound) continue ;
2432
2433 for(k=0;k<nkWord2;k++) {
2434 if (strncmp(buf,kWord2[k],lkWord2[k])==0) {
2435 nOfKW2++ ;
2436 i+=lkWord2[k] ;
2437 opFound = kTRUE ;
2439 break ;
2440 }
2441 }
2442 if (opFound) continue ;
2443
2444 for(k=0;k<nkWord3;k++) {
2445 if (strncmp(buf,kWord3[k],lkWord3[k])==0) {
2446 nOfKW3++ ;
2447 i+=lkWord3[k] ;
2448 opFound = kTRUE ;
2449 opFrac++ ;
2450 nOfCurlyBracket++ ;
2451 break ;
2452 }
2453 }
2454 if (opFound) continue ;
2455 if (strncmp(buf,"}{",2) == 0 && opFrac) {
2456 opFrac-- ;
2457 nOfCurlyCurly++ ;
2458 i+= 2;
2459 }
2460 else if (strncmp(buf,"]{",2) == 0 && nOfSquareBracket) {
2461 nOfSquareCurly++ ;
2462 i+= 2 ;
2463 nOfCurlyBracket++ ;
2465 }
2466 else if (strncmp(buf,"@{",2) == 0 || strncmp(buf,"@}",2) == 0) {
2467 i+= 2 ;
2468 }
2469 else if (strncmp(buf,"@[",2) == 0 || strncmp(buf,"@]",2) == 0) {
2470 i+= 2 ;
2471 }
2472 else if (text[i] == ']' ) { // not belonging to a key word, add @ in front
2473 text.Insert(i,"@") ;
2474 length++ ;
2475 i+=2 ;
2476 }
2477 else if (text[i] == '[' ) { // not belonging to a key word, add @ in front
2478 text.Insert(i,"@") ;
2479 length++ ;
2480 i+=2 ;
2481 }
2482 else if (text[i] == '{' ) { // not belonging to a key word, add @ in front
2483 text.Insert(i,"@") ;
2484 length++ ;
2485 i+=2 ;
2486 }
2487 else if (text[i] == '}' ) {
2488 if ( nOfCurlyBracket) {
2489 nOfCurlyBracket-- ;
2490 i++ ;
2491 } else { // extra }, add @ in front
2492 text.Insert(i,"@") ;
2493 length++ ;
2494 i+=2 ;
2495 }
2496 } else {
2497 i++ ;
2498 buf[1] = 0 ;
2499 }
2500 }
2501
2502 if (nOfKW2 != nOfSquareCurly) {
2503 error = 1 ;
2504 fError = "Invalid number of \"]{\"" ;
2505 }
2506 else if (nOfKW3 != nOfCurlyCurly) {
2507 error = 1 ;
2508 fError = "Error in syntax of \"#frac\"" ;
2509 }
2510 else if (nOfCurlyBracket < 0) {
2511 error = 1 ;
2512 fError = "Missing \"{\"" ;
2513 }
2514 else if (nOfCurlyBracket > 0) {
2515 error = 1 ;
2516 fError = "Missing \"}\"" ;
2517 }
2518 else if (nOfSquareBracket < 0) {
2519 error = 1 ;
2520 fError = "Missing \"[\"" ;
2521 }
2522 else if (nOfSquareBracket > 0) {
2523 error = 1 ;
2524 fError = "Missing \"]\"" ;
2525 }
2526
2527 ERROR_END:
2528 return error ;
2529}
2530
2531////////////////////////////////////////////////////////////////////////////////
2532/// First parsing of the analyse sequence
2533
2535{
2536 fTabSize.reserve(100); // ensure 100 entries before memory reallocation required
2537 fShow = kFALSE;
2538 fOriginSize = size;
2539
2540 //get current line attributes
2543
2545 spec.fAngle = angle;
2546 spec.fSize = GetTextSizePercent(size);
2547 spec.fColor = GetTextColor();
2548 spec.fFont = GetTextFont();
2551
2553
2556 SetTextFont(spec.fFont);
2557 SetTextColor(spec.fColor);
2561 return fs;
2562}
2563
2564////////////////////////////////////////////////////////////////////////////////
2565/// Return height of current pad in pixels
2566
2568{
2569 if (!gPad) return 0.;
2570 Double_t w = gPad->GetAbsWNDC()*Double_t(gPad->GetWw());
2571 Double_t h = gPad->GetAbsHNDC()*Double_t(gPad->GetWh());
2572 if (w < h)
2573 return w;
2574 else
2575 return h;
2576}
2577
2578////////////////////////////////////////////////////////////////////////////////
2579/// Return size of the formula along X in pad coordinates when the text precision
2580/// is smaller than 3.
2581
2583{
2584 if (!gPad) return 0.;
2586 if( newText.Length() == 0) return 0;
2587
2588 // The text is a TMathText.
2589 if ( newText.Contains("\\") ) {
2590 TMathText tm(0., 0., newText.Data());
2591 return tm.GetXsize();
2592 }
2593
2594 fError = nullptr;
2596 Error("GetXsize", "%s\n==> %s", fError, GetTitle());
2597 return 0;
2598 }
2599 fError = nullptr;
2600
2601 const Char_t *text = newText.Data() ;
2605 fTabSize.clear();
2606 return std::abs(gPad->AbsPixeltoX(fs.Width()) - gPad->AbsPixeltoX(0));
2607}
2608
2609////////////////////////////////////////////////////////////////////////////////
2610/// Return text size in pixels
2611
2613{
2614 if (!gPad) return;
2616 if( newText.Length() == 0) return;
2617
2618 // The text is a TMathText.
2619 if ( newText.Contains("\\") ) {
2620 TMathText tm(0., 0., newText.Data());
2621 tm.GetBoundingBox(w, h);
2622 return;
2623 }
2624
2625 fError = nullptr;
2627 Error("GetBoundingBox", "%s\n==> %s", fError, GetTitle());
2628 return;
2629 }
2630 fError = nullptr;
2631
2632 if (angle) {
2633 Int_t cBoxX[4], cBoxY[4];
2634 Int_t ptx, pty;
2635 if (TestBit(kTextNDC)) {
2636 ptx = gPad->UtoPixel(fX);
2637 pty = gPad->VtoPixel(fY);
2638 } else {
2639 ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX));
2640 pty = gPad->YtoAbsPixel(gPad->YtoPad(fY));
2641 }
2643 Int_t x1 = cBoxX[0];
2644 Int_t x2 = cBoxX[0];
2645 Int_t y1 = cBoxY[0];
2646 Int_t y2 = cBoxY[0];
2647 for (Int_t i=1; i<4; i++) {
2648 if (cBoxX[i] < x1) x1 = cBoxX[i];
2649 if (cBoxX[i] > x2) x2 = cBoxX[i];
2650 if (cBoxY[i] < y1) y1 = cBoxY[i];
2651 if (cBoxY[i] > y2) y2 = cBoxY[i];
2652 }
2653 w = x2-x1;
2654 h = y2-y1;
2655 } else {
2656 const Char_t *text = newText.Data() ;
2658 fTabSize.clear();
2659 w = (UInt_t)fs.Width();
2660 h = (UInt_t)fs.Height();
2661 }
2662}
2663
2664////////////////////////////////////////////////////////////////////////////////
2665/// Return size of the formula along Y in pad coordinates when the text precision
2666/// is smaller than 3.
2667
2669{
2670 if (!gPad) return 0.;
2672 if( newText.Length() == 0) return 0;
2673
2674 // The text is a TMathText.
2675 if ( newText.Contains("\\") ) {
2676 TMathText tm(0., 0., newText.Data());
2677 return tm.GetYsize();
2678 }
2679
2680 fError = nullptr;
2682 Error("GetYsize", "%s\n==> %s", fError, GetTitle());
2683 return 0;
2684 }
2685 fError = nullptr;
2686
2687 const Char_t *text = newText.Data();
2691 fTabSize.clear();
2692 return std::abs(gPad->AbsPixeltoY(fs.Height()) - gPad->AbsPixeltoY(0));
2693}
2694
2695////////////////////////////////////////////////////////////////////////////////
2696/// Read fs in fTabSize
2697
2699{
2700 if (fTabSize.empty()) {
2701 Error("Readfs", "No data in fTabSize stack");
2702 return TLatexFormSize(0,0,0);
2703 }
2704
2706 fTabSize.pop_back();
2707 return result;
2708}
2709
2710////////////////////////////////////////////////////////////////////////////////
2711/// Save fs values in array fTabSize
2712
2714{
2715 fTabSize.emplace_back(*fs);
2716}
2717
2718////////////////////////////////////////////////////////////////////////////////
2719/// Save primitive as a C++ statement(s) on output stream out
2720
2721void TLatex::SavePrimitive(std::ostream &out, Option_t *option)
2722{
2724 out, Class(), "tex",
2725 TString::Format("%g, %g, \"%s\"", fX, fY, TString(GetTitle()).ReplaceSpecialCppChars().Data()), kFALSE);
2726
2727 SaveTextAttributes(out, "tex", 11, 0, 1, 62, 0.05);
2728 SaveLineAttributes(out, "tex", 1, 1, 1);
2729
2730 if (TestBit(kTextNDC))
2731 out << " tex->SetNDC();\n";
2732
2733 SavePrimitiveDraw(out, "tex", option);
2734}
2735
2736////////////////////////////////////////////////////////////////////////////////
2737/// Set relative size of subscripts and superscripts
2738
2740{
2742}
2743
2744////////////////////////////////////////////////////////////////////////////////
2745/// Set limit for text resizing of subscripts and superscripts
2746
2748{
2750}
#define d(i)
Definition RSha256.hxx:102
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
char Char_t
Character 1 byte (char)
Definition RtypesCore.h:52
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
constexpr Double_t kPI
Definition TEllipse.cxx:26
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t SetLineWidth
Option_t Option_t SetTextSize
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 np
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 prop
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 result
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 length
Option_t Option_t SetLineColor
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t SetTextFont
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char DrawLine
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
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 text
Option_t Option_t TPoint TPoint const char y1
const Double_t kPI
Definition TLatex.cxx:23
#define gPad
const char * tab3
const char * tab2
Fill Area Attributes class.
Definition TAttFill.h:21
Line Attributes class.
Definition TAttLine.h:21
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual void Modify()
Change current line attributes if necessary.
Definition TAttLine.cxx:246
void Copy(TAttLine &attline) const
Copy this line attributes to a new TAttLine.
Definition TAttLine.cxx:176
virtual void SaveLineAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1, Int_t widdef=1)
Save line attributes as C++ statement(s) on output stream out.
Definition TAttLine.cxx:289
virtual Float_t GetTextSize() const
Return the text size.
Definition TAttText.h:39
virtual void Modify()
Change current text attributes if necessary.
Definition TAttText.cxx:364
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:48
virtual Short_t GetTextAlign() const
Return the text alignment.
Definition TAttText.h:35
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:38
Float_t fTextAngle
Text angle.
Definition TAttText.h:24
virtual Color_t GetTextColor() const
Return the text color.
Definition TAttText.h:37
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:49
virtual Float_t GetTextAngle() const
Return the text angle.
Definition TAttText.h:36
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:50
Font_t fTextFont
Text font.
Definition TAttText.h:28
virtual void SaveTextAttributes(std::ostream &out, const char *name, Int_t alidef=12, Float_t angdef=0, Int_t coldef=1, Int_t fondef=61, Float_t sizdef=1)
Save text attributes as C++ statement(s) on output stream out.
Definition TAttText.cxx:399
virtual Float_t GetTextSizePercent(Float_t size)
Return the text in percent of the pad size.
Definition TAttText.cxx:316
Short_t fTextAlign
Text alignment.
Definition TAttText.h:26
void Copy(TAttText &atttext) const
Copy this text attributes to a new TAttText.
Definition TAttText.cxx:300
TLatex helper class used to compute the size of a portion of a formula.
Definition TLatex.h:35
To draw Mathematical Formula.
Definition TLatex.h:20
virtual void SetLimitIndiceSize(Int_t limitFactorSize)
Set limit for text resizing of subscripts and superscripts.
Definition TLatex.cxx:2745
Double_t GetXsize()
Return size of the formula along X in pad coordinates when the text precision is smaller than 3.
Definition TLatex.cxx:2580
void Rotate(TVirtualPad *pad, Double_t angle, Int_t np, Double_t *x, Double_t *y)
Rotate array of points around fX, fY coordinate by specified angle.
Definition TLatex.cxx:507
Double_t GetHeight() const
Return height of current pad in pixels.
Definition TLatex.cxx:2565
void Copy(TObject &text) const override
Copy this TLatex object to another TLatex.
Definition TLatex.cxx:490
Double_t fFactorPos
! Relative position of subscripts and superscripts
Definition TLatex.h:65
Int_t fLimitFactorSize
lower bound for subscripts/superscripts size
Definition TLatex.h:66
void DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2, const TextSpec_t &spec)
Draw a line in a Latex formula.
Definition TLatex.cxx:2052
TLatexFormSize Anal1(const TextSpec_t &spec, const Char_t *t, Int_t length)
Analyse function.
Definition TLatex.cxx:537
void DrawParenthesis(Double_t x1, Double_t y1, Double_t r1, Double_t r2, Double_t phimin, Double_t phimax, const TextSpec_t &spec)
Draw an arc of ellipse in a Latex formula (right or left parenthesis)
Definition TLatex.cxx:2093
static TClass * Class()
virtual void SetIndiceSize(Double_t factorSize)
Set relative size of subscripts and superscripts.
Definition TLatex.cxx:2737
std::vector< TLatexFormSize > fTabSize
! array of values for the different zones
Definition TLatex.h:69
Int_t PaintLatex1(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Drawing function.
Definition TLatex.cxx:2227
Double_t fOriginSize
Font size of the starting font.
Definition TLatex.h:70
Double_t GetYsize()
Return size of the formula along Y in pad coordinates when the text precision is smaller than 3.
Definition TLatex.cxx:2666
TLatexFormSize FirstParse(Double_t angle, Double_t size, const Char_t *text)
First parsing of the analyse sequence.
Definition TLatex.cxx:2532
TLatexFormSize Readfs()
Read fs in fTabSize.
Definition TLatex.cxx:2696
void GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle=kFALSE) override
Return text size in pixels.
Definition TLatex.cxx:2610
TLatex * DrawLatexNDC(Double_t x, Double_t y, const char *text)
Draw this TLatex with new coordinates in NDC.
Definition TLatex.cxx:2007
void DrawCircle(Double_t x1, Double_t y1, Double_t r, const TextSpec_t &spec)
Draw an arc of ellipse in a Latex formula (right or left parenthesis)
Definition TLatex.cxx:2066
virtual void PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Main drawing function.
Definition TLatex.cxx:2146
TLatex()
Default constructor.
Definition TLatex.cxx:417
Bool_t fShow
! is true during the second pass (Painting)
Definition TLatex.h:68
~TLatex() override
Destructor.
Definition TLatex.cxx:448
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitive as a C++ statement(s) on output stream out.
Definition TLatex.cxx:2719
TLatex & operator=(const TLatex &)
assignment operator
Definition TLatex.cxx:470
void DrawPolyLine(Int_t npoints, Double_t *xx, Double_t *yy, const TextSpec_t &spec, Double_t scale_width=0.)
Draw a poly line in a Latex formula Is scale_width parameter >=1, fill area will be drawn Otherwise l...
Definition TLatex.cxx:2020
TLatex * DrawLatex(Double_t x, Double_t y, const char *text)
Make a copy of this object with the new parameters And copy object attributes.
Definition TLatex.cxx:1993
Double_t fFactorSize
! Relative size of subscripts and superscripts
Definition TLatex.h:64
const Char_t * fError
! error code
Definition TLatex.h:67
Bool_t fItalic
! Currently inside italic operator
Definition TLatex.h:71
void Paint(Option_t *option="") override
Paint.
Definition TLatex.cxx:2124
TLatexFormSize Analyse(Double_t x, Double_t y, const TextSpec_t &spec, const Char_t *t, Int_t length)
Analyse and paint the TLatex formula.
Definition TLatex.cxx:569
Int_t CheckLatexSyntax(TString &text)
Check if the Latex syntax is correct.
Definition TLatex.cxx:2333
void Savefs(TLatexFormSize *fs)
Save fs values in array fTabSize.
Definition TLatex.cxx:2711
@ kTextNDC
The text position is in NDC coordinates.
Definition TLatex.h:99
To draw TeX Mathematical Formula.
Definition TMathText.h:19
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
TString fName
Definition TNamed.h:32
Mother of all ROOT objects.
Definition TObject.h:42
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
static void SavePrimitiveDraw(std::ostream &out, const char *variable_name, Option_t *option=nullptr)
Save invocation of primitive Draw() method Skipped if option contains "nodraw" string.
Definition TObject.cxx:844
static void SavePrimitiveConstructor(std::ostream &out, TClass *cl, const char *variable_name, const char *constructor_agrs="", Bool_t empty_line=kTRUE)
Save object constructor in the output stream "out".
Definition TObject.cxx:776
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
const char * Data() const
Definition TString.h:385
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:714
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:2460
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:661
Base class for several text objects.
Definition TText.h:22
Double_t fY
Y position of text (left,center,etc..)
Definition TText.h:26
void Copy(TObject &text) const override
Copy this text to text.
Definition TText.cxx:104
TText & operator=(const TText &src)
Assignment operator.
Definition TText.cxx:95
Double_t fX
X position of text (left,center,etc..)
Definition TText.h:25
virtual void GetTextExtent(UInt_t &w, UInt_t &h, const char *text) const
Return text extent for string text.
Definition TText.cxx:611
virtual void GetTextAscentDescent(UInt_t &a, UInt_t &d, const char *text) const
Return text ascent and descent for string text.
Definition TText.cxx:576
virtual void GetControlBox(Int_t x, Int_t y, Double_t theta, Int_t cBoxX[4], Int_t cBoxY[4])
Return the text control box.
Definition TText.cxx:475
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:706
Double_t Exp(Double_t x)
Returns the base-e exponential function of x, which is e raised to the power x.
Definition TMath.h:722
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:769
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:607
constexpr Double_t Pi()
Definition TMath.h:40
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:601
TLatex helper struct holding the attributes of a piece of text.
Definition TLatex.h:26
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4