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 || opSpec == 76) {
1369 newSpec.fFont = GetTextFont();
1370 if (gPad->GetPainter()->IsCocoa()) {
1371 if (opSpec == 75) letter = '\201'; // AA Angstroem
1372 else if (opSpec == 76) letter = '\214'; // aa Angstroem
1373 } else {
1374 if (opSpec == 75) letter = '\305'; // AA Angstroem
1375 else if (opSpec == 76) letter = '\345'; // aa Angstroem
1376 }
1377 }
1378 if(opSpec == 80)
1379 letter = '\042'; // #forall
1380 else if (opSpec == 81)
1381 letter = '\044'; // #exists
1382 else if (opSpec == 82)
1383 letter = '\055'; // #textendash
1384 else if (opSpec == 83)
1385 letter = '\276'; // #textemdash
1386
1388 props = 1.8 ; // scale factor for #sum(66)
1389 propi = 2.3 ; // scale factor for #int(79)
1390
1391 if (opSpec==66 ) {
1392 newSpec.fSize = spec.fSize*props;
1393 } else if (opSpec==79) {
1394 newSpec.fSize = spec.fSize*propi;
1395 }
1396 if (!fShow) {
1397 fs1 = Anal1(newSpec,&letter,1);
1398 if (opSpec == 79 || opSpec == 66)
1399 fs1.Set(fs1.Width(),fs1.Over()*0.45,fs1.Over()*0.45);
1400
1402 Savefs(&fs1);
1403 } else {
1404 fs1 = Readfs();
1406 if (opSpec!=66 && opSpec!=79)
1407 Analyse(x,y,newSpec,&letter,1);
1408 else {
1409 Analyse(x,y+fs1.Under()/2.,newSpec,&letter,1);
1410 }
1411 }
1412 result = fs1+fs2;
1413 }
1414 else if (opAbove>-1) {
1415 if (!fShow) {
1417 Savefs(&fs1);
1418 } else {
1419 fs1 = Readfs();
1421 Double_t sub = GetHeight()*spec.fSize/14;
1422 switch(opAbove) {
1423 case 0: { // bar
1424 Double_t xx[2], yy[2];
1425 xx[0] = x; xx[1] = x + fs1.Width();
1426 yy[0] = yy[1] = y - sub - fs1.Over();
1427 DrawPolyLine(2, xx, yy, spec, 0.03);
1428 break;
1429 }
1430 case 1: { // vec
1431 Double_t xx[3], yy[3],
1432 dd = GetHeight()*spec.fSize/8, // arrow size
1433 midy = y - sub - fs1.Over() - dd; // middle arrow line
1434 xx[0] = x; xx[1] = x + fs1.Width();
1435 yy[0] = yy[1] = midy;
1436 DrawPolyLine(2, xx, yy, spec, 0.03);
1437 xx[1] = x + fs1.Width(); xx[0] = xx[2] = xx[1] - 2*dd;
1438 yy[0] = midy - dd; yy[1] = midy; yy[2] = midy + dd;
1439 DrawPolyLine(3, xx, yy, spec, 0.03);
1440 break;
1441 }
1442 case 2: { // dot
1443 Double_t dd = std::max(0.5*GetLineWidth(), 0.5*sub), // dot size
1444 midx = x + fs1.Width()/2,
1445 midy = y - sub - fs1.Over() - dd;
1446 Double_t xx[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1447 yy[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1448 DrawPolyLine(5, xx, yy, spec, 10.);
1449 break;
1450 }
1451 case 3: { // hat
1452 Double_t xx[3], yy[3];
1453 xx[1] = x + fs1.Width()/2;
1454 xx[0] = xx[1] - fs1.Width()/3;
1455 xx[2] = xx[1] + fs1.Width()/3;
1456 yy[0] = y - sub - fs1.Over();
1457 yy[1] = yy[0] - 2*sub;
1458 yy[2] = yy[0];
1459 DrawPolyLine(3, xx, yy, spec, 0.03);
1460 break;
1461 }
1462 case 4: { // ddot
1463 Double_t dd = std::max(0.5*GetLineWidth(), 0.5*sub), // dot size
1464 midx = x + fs1.Width()/2 - 1.5*sub,
1465 midy = y - sub - fs1.Over() - dd;
1466 Double_t xx1[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1467 yy1[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1468 DrawPolyLine(5, xx1, yy1, spec, 10.);
1469 midx = x + fs1.Width()/2 + 1.5*sub;
1470 Double_t xx2[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1471 yy2[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1472 DrawPolyLine(5, xx2, yy2, spec, 10.);
1473 break;
1474 }
1475 case 5: { // acute
1476 Double_t xx[2], yy[2];
1477 xx[0] = x + fs1.Width()/2; xx[1] = xx[0] + 3*sub;
1478 yy[0] = y - sub - fs1.Over();
1479 yy[1] = yy[0] - 2.5*sub;
1480 DrawPolyLine(2, xx, yy, spec, 0.03);
1481 break;
1482 }
1483 case 6: { // grave
1484 Double_t xx[2], yy[2];
1485 xx[0] = x + fs1.Width()/2 + sub; xx[1] = xx[0] - 2*sub;
1486 yy[0] = y - sub - fs1.Over();
1487 yy[1] = yy[0] - 2*sub;
1488 DrawPolyLine(2, xx, yy, spec, 0.03);
1489 break;
1490 }
1491 case 7: { // check
1492 Double_t xx[3], yy[3];
1493 xx[1] = x+fs1.Width()/2; xx[0] = xx[1] - 2*sub; xx[2] = xx[1] + 2*sub;
1494 yy[1] = y - sub - fs1.Over();
1495 yy[0] = yy[2] = yy[1] - 2*sub;
1496 DrawPolyLine(3, xx, yy, spec, 0.03);
1497 break;
1498 }
1499 case 8: { // tilde
1500 Double_t x2 = x+fs1.Width()/2, y2 = y -fs1.Over();
1501 // tilde must be drawn separately on screen and on PostScript
1502 // because an adjustment is required along Y for PostScript.
1503
1504 Double_t xx, yy;
1505 if (auto ps = gPad->GetPainter()->GetPS()) {
1506 if (!strstr(ps->GetTitle(), "IMG"))
1507 y2 -= 4*sub;
1508 Rotate(gPad, spec.fAngle, x2, y2, xx, yy);
1509 ps->SetTextAlign(22);
1510 ps->Text(xx, yy, "~");
1511 } else {
1512 if (gPad->GetPainter()->IsCocoa())
1513 y2 -= 4.7*sub;
1514 Rotate(gPad, spec.fAngle, x2, y2, xx, yy);
1515 // TODO: use pad painter SetAttText and DrawText directly
1516 TText tilde;
1517 tilde.SetTextFont(fTextFont);
1518 tilde.SetTextColor(spec.fColor);
1519 tilde.SetTextSize(0.9*spec.fSize);
1520 tilde.SetTextAlign(22);
1521 tilde.SetTextAngle(fTextAngle);
1522 tilde.PaintText(xx,yy,"~");
1523 }
1524 break;
1525 }
1526 case 9: { // slash
1527 Double_t xx[2], yy[2];
1528 xx[0] = x + 0.8*fs1.Width();
1529 yy[0] = y - fs1.Over() - sub;
1530 xx[1] = x + 0.3*fs1.Width();
1531 yy[1] = yy[0] + fs1.Height() + 2*sub;
1532 DrawPolyLine(2, xx, yy, spec, 0.03);
1533 break;
1534 }
1535 }
1536 }
1537 Double_t div = 3;
1538 if (opAbove==1) div=4;
1539 result.Set(fs1.Width(),fs1.Over()+GetHeight()*spec.fSize/div,fs1.Under());
1540 }
1541 else if (opSquareBracket) { // operator #[]{arg}
1542 Double_t l = GetHeight()*spec.fSize/4;
1543 Double_t l2 = l/2 ;
1544 if (!fShow) {
1545 fs1 = Anal1(spec,text+3,length-3);
1546 Savefs(&fs1);
1547 } else {
1548 fs1 = Readfs();
1549 Analyse(x+l2+l,y,spec,text+3,length-3);
1550 DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec);
1551 DrawLine(x+l2,y-fs1.Over(),x+l2+l,y-fs1.Over(),spec);
1552 DrawLine(x+l2,y+fs1.Under(),x+l2+l,y+fs1.Under(),spec);
1553 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec);
1554 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+l,y-fs1.Over(),spec);
1555 DrawLine(x+l2+fs1.Width()+2*l,y+fs1.Under(),x+l2+fs1.Width()+l,y+fs1.Under(),spec);
1556 }
1557 result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1558 }
1559 else if (opParen) { // operator #(){arg}
1560 Double_t l = GetHeight()*spec.fSize/4;
1561 Double_t radius2,radius1 , dw, l2 = l/2 ;
1562 Double_t angle = 35 ;
1563 if (!fShow) {
1564 fs1 = Anal1(spec,text+3,length-3);
1565 Savefs(&fs1);
1566 radius2 = fs1.Height() ;
1567 radius1 = radius2 * 2 / 3;
1568 dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ;
1569 } else {
1570 fs1 = Readfs();
1571 radius2 = fs1.Height();
1572 radius1 = radius2 * 2 / 3;
1573 dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ;
1574 Double_t x1 = x+l2+radius1 ;
1575 Double_t x2 = x+5*l2+2*dw+fs1.Width()-radius1 ;
1576 Double_t y1 = y - (fs1.Over() - fs1.Under())/2. ;
1579 Analyse(x+3*l2+dw,y,spec,text+3,length-3);
1580 }
1581 // result = TLatexFormSize(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1582 result.Set(fs1.Width()+3*l+2*dw,fs1.Over(),fs1.Under());
1583 }
1584 else if (opAbs) { // operator #||{arg}
1585 Double_t l = GetHeight()*spec.fSize/4;
1586 Double_t l2 = l/2 ;
1587 if (!fShow) {
1588 fs1 = Anal1(spec,text+3,length-3);
1589 Savefs(&fs1);
1590 } else {
1591 fs1 = Readfs();
1592 Analyse(x+l2+l,y,spec,text+3,length-3);
1593 DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec);
1594 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec);
1595 }
1596 result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1597 }
1598 else if (opBigCurly) { // big curly bracket #{}{arg}
1599 Double_t l = GetHeight()*spec.fSize/4;
1600 Double_t l2 = l/2 ;
1601 Double_t l8 , ltip;
1602
1603 if (!fShow) {
1604 fs1 = Anal1(spec,text+3,length-3);
1605 l8 = fs1.Height()/8 ;
1606 ltip = TMath::Min(l8,l) ;
1607 l = ltip ;
1608 Savefs(&fs1);
1609 } else {
1610 fs1 = Readfs();
1611 Double_t y2 = y + (fs1.Under()-fs1.Over())/2 ;
1612 l8 = fs1.Height()/8 ;
1613 ltip = TMath::Min(l8,l) ;
1614 l = ltip ;
1615 Analyse(x+l+ltip+l2,y,spec,text+3,length-3);
1616 // Draw open curly bracket
1617 // Vertical lines
1618 DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip,y2-ltip,spec);
1619 DrawLine(x+l2+ltip,y2+ltip,x+l2+ltip,y+fs1.Under(),spec);
1620 // top and bottom lines
1621 DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip+l,y-fs1.Over(),spec);
1622 DrawLine(x+l2+ltip,y+fs1.Under(),x+l2+ltip+l,y+fs1.Under(),spec);
1623 // < sign
1626
1627 // Draw close curly bracket
1628 // vertical lines
1629 DrawLine(x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y2-ltip,spec);
1630 DrawLine(x+l2+ltip+fs1.Width()+2*l,y2+ltip,x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec);
1631 // Top and bottom lines
1632 DrawLine(x+l2+fs1.Width()+l+ltip,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),spec);
1633 DrawLine(x+l2+fs1.Width()+l+ltip,y+fs1.Under(),x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec);
1634 // > sign
1635 DrawLine(x+l2+ltip+2*l+fs1.Width(),y2-ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec);
1636 DrawLine(x+l2+ltip+2*l+fs1.Width(),y2+ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec);
1637 }
1638 result.Set(fs1.Width()+3*l+2*ltip,fs1.Over(),fs1.Under());
1639 }
1640 else if (opFrac>-1) { // \frac found
1641 if (opCurlyCurly==-1) { // }{ not found
1642 // arguments missing for \frac
1643 fError = "Missing denominator for #frac";
1644 delete[] text;
1645 return TLatexFormSize(0,0,0);
1646 }
1647 Double_t height = GetHeight()*spec.fSize/8;
1648 if (!fShow) {
1651 Savefs(&fs1);
1652 Savefs(&fs2);
1653 } else {
1654 fs2 = Readfs();
1655 fs1 = Readfs();
1657 if (fs1.Width()<fs2.Width()) {
1658 addW1 = (fs2.Width()-fs1.Width())/2;
1659 addW2 = 0;
1660 } else {
1661 addW1 = 0;
1662 addW2 = (fs1.Width()-fs2.Width())/2;
1663 }
1664 Analyse(x+addW2,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // denominator
1665 Analyse(x+addW1,y-fs1.Under()-3*height,spec,text+opFrac+6,opCurlyCurly-opFrac-6); //numerator
1666
1667 DrawLine(x,y-2*height,x+std::max(fs1.Width(),fs2.Width()),y-2*height,spec);
1668 }
1669
1670 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
1671
1672 }
1673 else if (opSplitLine>-1) { // \splitline found
1674 if (opCurlyCurly==-1) { // }{ not found
1675 // arguments missing for \splitline
1676 fError = "Missing second line for #splitline";
1677 delete[] text;
1678 return TLatexFormSize(0,0,0);
1679 }
1680 Double_t height = GetHeight()*spec.fSize/8;
1681 if (!fShow) {
1684 Savefs(&fs1);
1685 Savefs(&fs2);
1686 } else {
1687 fs2 = Readfs();
1688 fs1 = Readfs();
1689 Analyse(x,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // second line
1690 Analyse(x,y-fs1.Under()-3*height,spec,text+opSplitLine+11,opCurlyCurly-opSplitLine-11); //first line
1691 }
1692
1693 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
1694
1695 }
1696 else if (opSqrt>-1) { // \sqrt found
1697 if (!fShow) {
1698 if (opSquareCurly>-1) {
1699 // power nth #sqrt[n]{arg}
1702 Savefs(&fs1);
1703 Savefs(&fs2);
1704 result.Set(fs2.Width()+ GetHeight()*spec.fSize/10+std::max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width()),
1705 fs2.Over()+fs1.Height()+GetHeight()*spec.fSize/4,fs2.Under());
1706 } else {
1708 Savefs(&fs1);
1709 result.Set(fs1.Width()+GetHeight()*spec.fSize/2,fs1.Over()+GetHeight()*spec.fSize/4,fs1.Under());
1710 }
1711 } else {
1712 if (opSquareCurly>-1) { // ]{
1713 fs2 = Readfs();
1714 fs1 = Readfs();
1715 Double_t pas = std::max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width());
1716 Double_t pas2 = pas + GetHeight()*spec.fSize/10;
1717 Double_t y1 = y-fs2.Over() ;
1718 Double_t y2 = y+fs2.Under() ;
1719 Double_t y3 = y1-GetHeight()*spec.fSize/4;
1721 Analyse(x,y-fs2.Over()-fs1.Under(),specNewSize,text+opSqrt+6,opSquareCurly-opSqrt-6); // indice
1722 DrawLine(x,y1,x+pas,y2,spec);
1724 DrawLine(x+pas,y3,x+pas2+fs2.Width(),y3,spec);
1725 } else {
1726 fs1 = Readfs();
1727 Double_t x1 = x+GetHeight()*spec.fSize*2/5 ;
1728 Double_t x2 = x+GetHeight()*spec.fSize/2+fs1.Width() ;
1729 Double_t y1 = y-fs1.Over() ;
1730 Double_t y2 = y+fs1.Under() ;
1731 Double_t y3 = y1-GetHeight()*spec.fSize/4;
1732
1734
1736 SetLineWidth(1);
1737 Double_t dx = (y2-y3)/8;
1738 UInt_t a,d;
1740 if (a>12) SetLineWidth(std::max(2,(Int_t)(dx/2)));
1741 DrawLine(x1-2*dx,y1,x1-dx,y2,spec);
1742 if (a>12) SetLineWidth(std::max(1,(Int_t)(dx/4)));
1746 }
1747 }
1748 }
1749 else if (opColor>-1) { // \color found
1750 if (opSquareCurly==-1) {
1751 // color number is not specified
1752 fError = "Missing color number. Syntax is #color[(Int_t)nb]{ ... }";
1753 delete[] text;
1754 return TLatexFormSize(0,0,0);
1755 }
1759 nb[opSquareCurly-opColor-7] = 0;
1760 if (sscanf(nb,"%d",&newSpec.fColor) < 1) {
1761 delete[] nb;
1762 // color number is invalid
1763 fError = "Invalid color number. Syntax is #color[(Int_t)nb]{ ... }";
1764 delete[] text;
1765 return TLatexFormSize(0,0,0);
1766 }
1767 delete[] nb;
1768 if (!fShow) {
1770 } else {
1772 }
1773 }
1774 else if (opUrl>-1) { // \url found
1775 if (opSquareCurly==-1) {
1776 // url is not specified
1777 fError = "Missing url. Syntax is #url[http://...]{ ... }";
1778 delete[] text;
1779 return TLatexFormSize(0,0,0);
1780 }
1782 fName = TString(text + opUrl + 5, opSquareCurly - opUrl - 5);
1783 if (!fShow) {
1785 } else {
1787 }
1788 fName = "";
1789 }
1790 else if (opFont>-1) { // \font found
1791 if (opSquareCurly==-1) {
1792 // font number is not specified
1793 fError = "Missing font number. Syntax is #font[nb]{ ... }";
1794 delete[] text;
1795 return TLatexFormSize(0,0,0);
1796 }
1800 nb[opSquareCurly-opFont-6] = 0;
1801 if (sscanf(nb,"%d",&newSpec.fFont) < 1) {
1802 delete[] nb;
1803 // font number is invalid
1804 fError = "Invalid font number. Syntax is #font[(Int_t)nb]{ ... }";
1805 delete[] text;
1806 return TLatexFormSize(0,0,0);
1807 }
1808 delete[] nb;
1809 if (!fShow) {
1811 } else {
1813 }
1814 }
1815 else if (opKern>-1) { // #kern found
1816 if (opSquareCurly==-1) {
1817 // horizontal shift is not specified
1818 fError = "Missing horizontal shift number. Syntax is #kern[dx]{ ... }";
1819 delete[] text;
1820 return TLatexFormSize(0,0,0);
1821 }
1824 dxc[opSquareCurly-opKern-6] = 0;
1825 Float_t dx = 0;
1826 if (sscanf(dxc,"%f",&dx) < 1) {
1827 delete[] dxc;
1828 // horizontal shift number is invalid
1829 fError = "Invalid horizontal shift number. Syntax is #kern[(Float_t)dx]{ ... }";
1830 delete[] text;
1831 return TLatexFormSize(0,0,0);
1832 }
1833 delete[] dxc;
1834 if (!fShow) {
1836 Savefs(&fs1);
1837 Double_t ddx = dx * fs1.Width();
1838 result = TLatexFormSize(fs1.Width() + ddx, fs1.Over(), fs1.Under());
1839 } else {
1840 fs1 = Readfs();
1841 Double_t ddx = dx * fs1.Width();
1843 }
1844 }
1845 else if (opLower>-1) { // #lower found
1846 if (opSquareCurly==-1) {
1847 // vertical shift is not specified
1848 fError = "Missing vertical shift number. Syntax is #lower[dy]{ ... }";
1849 delete[] text;
1850 return TLatexFormSize(0,0,0);
1851 }
1854 dyc[opSquareCurly-opLower-7] = 0;
1855 Float_t dy = 0;
1856 if (sscanf(dyc,"%f",&dy) < 1) {
1857 delete[] dyc;
1858 // vertical shift number is invalid
1859 fError = "Invalid vertical shift number. Syntax is #lower[(Float_t)dy]{ ... }";
1860 delete[] text;
1861 return TLatexFormSize(0,0,0);
1862 }
1863 delete[] dyc;
1864 if (!fShow) {
1866 Savefs(&fs1);
1867 Double_t ddy = dy * (fs1.Over() + fs1.Under());
1868 result = TLatexFormSize(fs1.Width(), fs1.Over() + ddy, fs1.Under() + ddy);
1869 } else {
1870 fs1 = Readfs();
1871 Double_t ddy = dy * (fs1.Over() + fs1.Under());
1873 }
1874 }
1875 else if (opScale>-1) { // \scale found
1876 if (opSquareCurly==-1) {
1877 // scale factor is not specified
1878 fError = "Missing scale factor. Syntax is #scale[(Double_t)nb]{ ... }";
1879 delete[] text;
1880 return TLatexFormSize(0,0,0);
1881 }
1885 nb[opSquareCurly-opScale-7] = 0;
1886 if (sscanf(nb,"%lf",&newSpec.fSize) < 1) {
1887 delete[] nb;
1888 // scale factor is invalid
1889 fError = "Invalid scale factor. Syntax is #factor[(Double_t)nb]{ ... }";
1890 delete[] text;
1891 return TLatexFormSize(0,0,0);
1892 }
1893 newSpec.fSize *= spec.fSize;
1894 delete[] nb;
1895 if (!fShow) {
1897 } else {
1899 }
1900 }
1901 else if (opBf>-1) { // operator #bf{arg}
1903 Int_t lut[] = {3, 13, 1, 6, 7, 4, 5, 10, 11, 8, 9, 12, 2, 14, 15};
1904 Int_t fontId = (newSpec.fFont/10);
1905 if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1];
1906 newSpec.fFont = fontId*10 + newSpec.fFont%10;
1907 if (!fShow) {
1908 fs1 = Anal1(newSpec,text+3,length-3);
1909 Savefs(&fs1);
1910 } else {
1911 fs1 = Readfs();
1913 }
1914 result = fs1;
1915 }
1916 else if (opMbox>-1) { // dummy operator #mbox{arg}
1918 if (!fShow) {
1919 fs1 = Anal1(newSpec,text+5,length-5);
1920 Savefs(&fs1);
1921 } else {
1922 fs1 = Readfs();
1924 }
1925 result = fs1;
1926 }
1927 else if (opIt>-1) { // operator #it{arg}
1929 Int_t lut[] = {13, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 15, 1, 14, 12};
1930 Int_t fontId = (newSpec.fFont/10);
1931 if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1];
1932 newSpec.fFont = fontId*10 + newSpec.fFont%10;
1933 fItalic = !fItalic;
1934 if (!fShow) {
1935 fs1 = Anal1(newSpec,text+3,length-3);
1936 Savefs(&fs1);
1937 } else {
1938 fs1 = Readfs();
1940 }
1941 fItalic = !fItalic;
1942 result = fs1;
1943 }
1944 else { // no operators found, it is a character string
1945 SetTextSize(spec.fSize);
1946 SetTextAngle(spec.fAngle);
1947 SetTextColor(spec.fColor);
1948 SetTextFont(spec.fFont);
1949 SetTextAlign(11);
1951 UInt_t w=0,h=0;
1952
1953 Int_t leng = strlen(text) ;
1954
1955 quote1 = quote2 = kFALSE ;
1956 Char_t *p ;
1957 for (i=0 ; i<leng ; i++) {
1958 switch (text[i]) {
1959 case '\'' : quote1 = !quote1 ; break ; // single quote symbol not correctly interpreted when PostScript
1960 case '"' : quote2 = !quote2 ; break ;
1961 }
1962 //if (quote1 || quote2) continue ;
1963 if (text[i] == '@') { // @ symbol not correctly interpreted when PostScript
1964 p = &text[i] ;
1965 if ( *(p+1) == '{' || *(p+1) == '}' || *(p+1) == '[' || *(p+1) == ']') {
1966 while (*p != 0) {
1967 *p = *(p+1) ; p++ ;
1968 }
1969 leng-- ;
1970 }
1971 }
1972 }
1973 text[leng] = 0 ;
1974
1975 if (fShow) {
1976 // paint the Latex sub-expression per sub-expression
1977 Double_t xx, yy;
1978 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1979 if (fName.Length() > 0) gPad->PaintTextUrl(xx, yy, text, fName.Data());
1980 else gPad->PaintText(xx, yy, text);
1981 } else {
1983 Double_t width = w;
1984 UInt_t a,d;
1986 fs1.Set(width,a,d);
1987 }
1988
1989 result = fs1;
1990 }
1991
1992 delete[] text;
1993
1994 return result;
1995}
1996
1997////////////////////////////////////////////////////////////////////////////////
1998/// Make a copy of this object with the new parameters
1999/// And copy object attributes
2000
2002{
2003 TLatex *newtext = new TLatex(x, y, text);
2006 newtext->SetBit(kCanDelete);
2007 if (TestBit(kTextNDC)) newtext->SetNDC();
2008 newtext->AppendPad();
2009 return newtext;
2010}
2011
2012////////////////////////////////////////////////////////////////////////////////
2013/// Draw this TLatex with new coordinates in NDC.
2014
2016{
2018 newtext->SetNDC();
2019 return newtext;
2020}
2021
2022
2023////////////////////////////////////////////////////////////////////////////////
2024/// Draw a poly line in a Latex formula
2025/// Is scale_width parameter >=1, fill area will be drawn
2026/// Otherwise line width will be scaled proportional to current font size
2027/// If not specified - default line width will be used
2029{
2030 if (!gPad)
2031 return;
2032
2033 Rotate(gPad, spec.fAngle, npoints, xx, yy);
2034
2035 if (scale_width >= 1.) {
2036 TAttFill fill(spec.fColor, 1001);
2037 fill.Modify();
2038 gPad->PaintFillArea(npoints, xx, yy, "f");
2039 return;
2040 }
2041
2042 auto prevWidth = GetLineWidth();
2043 if (scale_width) {
2044 Int_t lineWidth = TMath::Nint(GetHeight() * spec.fSize * scale_width);
2045 SetLineWidth(lineWidth > prevWidth ? lineWidth : prevWidth);
2046 }
2047
2048 SetLineColor(spec.fColor);
2050
2051 gPad->PaintPolyLine(npoints, xx, yy);
2052 if (scale_width)
2054}
2055
2056
2057////////////////////////////////////////////////////////////////////////////////
2058/// Draw a line in a Latex formula
2059
2061{
2062 if (!gPad) return;
2063 Double_t xx[2] = { x1, x2 };
2064 Double_t yy[2] = { y1, y2 };
2065 Rotate(gPad, spec.fAngle, 2, xx, yy);
2066 SetLineColor(spec.fColor);
2068 gPad->PaintLine(xx[0], yy[0], xx[1], yy[1]);
2069}
2070
2071////////////////////////////////////////////////////////////////////////////////
2072/// Draw an arc of ellipse in a Latex formula (right or left parenthesis)
2073
2075{
2076 if (!gPad)
2077 return;
2078 if (r < 1)
2079 r = 1;
2080
2081 const Int_t np = 40;
2082 Double_t dphi = 2*kPI/np;
2083 Double_t x[np+3], y[np+3];
2084
2085 SetLineColor(spec.fColor);
2086 TAttLine::Modify(); //Change line attributes only if necessary
2087
2088 for (Int_t i = 0; i <= np; i++) {
2089 Double_t angle = i*dphi;
2090 x[i] = x1 + r*TMath::Cos(angle);
2091 y[i] = y1 + r*TMath::Sin(angle);
2092 }
2093 Rotate(gPad, spec.fAngle, np+1, x, y);
2094
2095 gPad->PaintPolyLine(np+1, x, y);
2096}
2097
2098////////////////////////////////////////////////////////////////////////////////
2099/// Draw an arc of ellipse in a Latex formula (right or left parenthesis)
2100
2103{
2104 if (!gPad)
2105 return;
2106 if (r1 < 1)
2107 r1 = 1;
2108 if (r2 < 1)
2109 r2 = 1;
2110
2111 const Int_t np = 40;
2112 Double_t dphi = (phimax-phimin)*kPI/(180*np);
2113 Double_t x[np+3], y[np+3];
2114
2115 SetLineColor(spec.fColor);
2116 TAttLine::Modify(); //Change line attributes only if necessary
2117
2118 for (Int_t i = 0; i <= np; i++) {
2119 Double_t angle = phimin*kPI/180 + i*dphi;
2120 x[i] = x1 + r1*TMath::Cos(angle);
2121 y[i] = y1 + r2*TMath::Sin(angle);
2122 }
2123
2124 Rotate(gPad, spec.fAngle, np+1, x, y);
2125
2126 gPad->PaintPolyLine(np+1,x,y);
2127}
2128
2129////////////////////////////////////////////////////////////////////////////////
2130/// Paint.
2131
2132void TLatex::Paint(Option_t *)
2133{
2134 if (!gPad) return ;
2135 Double_t xsave = fX;
2136 Double_t ysave = fY;
2137 if (TestBit(kTextNDC)) {
2138 fX = gPad->GetX1() + xsave*(gPad->GetX2() - gPad->GetX1());
2139 fY = gPad->GetY1() + ysave*(gPad->GetY2() - gPad->GetY1());
2141 } else {
2142 PaintLatex(gPad->XtoPad(fX),gPad->YtoPad(fY),GetTextAngle(),GetTextSize(),GetTitle());
2143 }
2144 fX = xsave;
2145 fY = ysave;
2146}
2147
2148////////////////////////////////////////////////////////////////////////////////
2149/// Main drawing function
2150///
2151/// Warning: Unlike most others "XYZ::PaintXYZ" methods, PaintLatex modifies
2152/// the TLatex data members.
2153
2155{
2156 if (size<=0 || strlen(text1) <= 0) return; // do not paint empty text or text with size <= 0
2157
2158 TAttText::Modify(); // Change text attributes only if necessary.
2159
2160 auto ps = gPad->GetPainter()->GetPS();
2161
2162 if (ps && ps->InheritsFrom("TTeXDump")) {
2163 TString t(text1);
2164 if (t.Index("#")>=0 || t.Index("^")>=0 || t.Index("\\")>=0) {
2165 t.ReplaceAll("#LT","\\langle");
2166 t.ReplaceAll("#GT","\\rangle");
2167 t.ReplaceAll("#club","\\clubsuit");
2168 t.ReplaceAll("#spade","\\spadesuit");
2169 t.ReplaceAll("#heart","\\heartsuit");
2170 t.ReplaceAll("#diamond","\\diamondsuit");
2171 t.ReplaceAll("#voidn","\\wp");
2172 t.ReplaceAll("#voidb","f");
2173 t.ReplaceAll("#ocopyright","\\copyright");
2174 t.ReplaceAll("#trademark","TM");
2175 t.ReplaceAll("#void3","TM");
2176 t.ReplaceAll("#oright","R");
2177 t.ReplaceAll("#void1","R");
2178 t.ReplaceAll("#3dots","\\ldots");
2179 t.ReplaceAll("#lbar","\\mid");
2180 t.ReplaceAll("#bar","\\wwbar");
2181 t.ReplaceAll("#void8","\\mid");
2182 t.ReplaceAll("#divide","\\div");
2183 t.ReplaceAll("#Jgothic","\\Im");
2184 t.ReplaceAll("#Rgothic","\\Re");
2185 t.ReplaceAll("#doublequote","\"");
2186 t.ReplaceAll("#plus","+");
2187 t.ReplaceAll("#minus","-");
2188 t.ReplaceAll("#/","/");
2189 t.ReplaceAll("#upoint",".");
2190 t.ReplaceAll("#aa","\\mbox{\\aa}");
2191 t.ReplaceAll("#AA","\\mbox{\\AA}");
2192
2193 t.ReplaceAll("#omicron","o");
2194 t.ReplaceAll("#Alpha","A");
2195 t.ReplaceAll("#Beta","B");
2196 t.ReplaceAll("#Epsilon","E");
2197 t.ReplaceAll("#Zeta","Z");
2198 t.ReplaceAll("#Eta","H");
2199 t.ReplaceAll("#Iota","I");
2200 t.ReplaceAll("#Kappa","K");
2201 t.ReplaceAll("#Mu","M");
2202 t.ReplaceAll("#Nu","N");
2203 t.ReplaceAll("#Omicron","O");
2204 t.ReplaceAll("#Rho","P");
2205 t.ReplaceAll("#Tau","T");
2206 t.ReplaceAll("#Chi","X");
2207 t.ReplaceAll("#varomega","\\varpi");
2208
2209 t.ReplaceAll("#varUpsilon","?");
2210 t.ReplaceAll("#corner","?");
2211 t.ReplaceAll("#ltbar","?");
2212 t.ReplaceAll("#bottombar","?");
2213 t.ReplaceAll("#notsubset","?");
2214 t.ReplaceAll("#arcbottom","?");
2215 t.ReplaceAll("#cbar","?");
2216 t.ReplaceAll("#arctop","?");
2217 t.ReplaceAll("#topbar","?");
2218 t.ReplaceAll("#arcbar","?");
2219 t.ReplaceAll("#downleftarrow","?");
2220 t.ReplaceAll("#splitline","\\genfrac{}{}{0pt}{}");
2221
2222 t.ReplaceAll("#","\\");
2223 t.ReplaceAll("%","\\%");
2224 }
2225 ps->SetTextAngle(angle);
2226 ps->Text(x, y, t.Data());
2227 } else {
2229 }
2230}
2231
2232////////////////////////////////////////////////////////////////////////////////
2233/// Drawing function
2234
2236{
2237 if (!gPad)
2238 return 0;
2240 if(newText.Length() == 0)
2241 return 0;
2242 newText.ReplaceAll("#hbox","#mbox");
2243
2244 fError = nullptr;
2246 Error("PaintLatex1", "%s\n==> %s", fError, text1);
2247 return 0;
2248 }
2249 fError = nullptr;
2250
2251 // Do not use Latex if font is low precision.
2252 if (fTextFont % 10 < 2) {
2253 gPad->GetPainter()->SetTextAngle(angle);
2254 gPad->PaintText(x, y, text1);
2255 return 1;
2256 }
2257
2258 // Paint the text using TMathText if contains a "\"
2259 if (strstr(text1,"\\")) {
2260 auto ps = gPad->GetPainter()->GetPS();
2261 // If PDF or SVG, paint using TLatex
2262 if (ps && (ps->InheritsFrom("TPDF") || ps->InheritsFrom("TSVG"))) {
2263 newText.ReplaceAll("\\","#");
2264 } else {
2265 TMathText tm;
2266 tm.SetTextAlign(GetTextAlign());
2267 tm.SetTextFont(GetTextFont());
2268 tm.SetTextColor(GetTextColor());
2269 tm.PaintMathText(x, y, angle, size, text1);
2270 return 1;
2271 }
2272 }
2273
2276 if (fTextFont % 10 > 2) {
2278 SetTextFont(10*(saveFont/10) + 2);
2279 }
2280
2281 Int_t length = newText.Length();
2282 const Char_t *text = newText.Data();
2283
2284 Double_t xsave = fX;
2285 Double_t ysave = fY;
2286 fX = x;
2287 fY = y;
2288 gPad->XYtoAbsPixel(fX, fY, x, y);
2289 fShow = kFALSE;
2291
2292 fOriginSize = size;
2293
2294 // Get current line attributes.
2297
2299 spec.fAngle = angle;
2300 spec.fSize = size;
2301 spec.fColor = GetTextColor();
2302 spec.fFont = GetTextFont();
2306 if (fError) {
2307 Error("PaintLatex1", "%s\n==> %s", fError, text);
2308 } else {
2309 fShow = kTRUE;
2310 newSpec.fSize = size;
2311
2312 switch (valign) {
2313 case 0: y -= fs.Under(); break;
2314 case 1: break;
2315 case 2: y += fs.Height()*0.5-fs.Under() + 1.; break;
2316 case 3: y += fs.Over(); break;
2317 }
2318 switch (halign) {
2319 case 2: x -= fs.Width()/2; break;
2320 case 3: x -= fs.Width(); break;
2321 }
2323 }
2324
2328 SetTextColor(spec.fColor);
2332 fTabSize.clear();
2333 fX = xsave;
2334 fY = ysave;
2335 return fError ? 0 : 1;
2336}
2337
2338////////////////////////////////////////////////////////////////////////////////
2339/// Check if the Latex syntax is correct
2340
2342{
2343 const Char_t *kWord1[] = {"{}^{","{}_{","^{","_{","#scale{","#color{","#url{","#font{","#sqrt{","#[]{","#{}{","#||{",
2344 "#bar{","#vec{","#dot{","#hat{","#ddot{","#acute{","#grave{","#check{","#tilde{","#slash{","#bf{","#it{","#mbox{",
2345 "\\scale{","\\color{","\\font{","\\sqrt{","\\[]{","\\{}{","\\||{","#(){","\\(){",
2346 "\\bar{","\\vec{","\\dot{","\\hat{","\\ddot{","\\acute{","\\grave{","\\check{","\\bf{","\\it{","\\mbox{"}; // check for }
2347 const Char_t *kWord2[] = {"#scale[","#color[","#url[","#font[","#sqrt[","#kern[","#lower[","\\scale[","\\color[","\\font[","\\sqrt[","\\kern[","\\lower["}; // check for ]{ + }
2348 const Char_t *kWord3[] = {"#frac{","\\frac{","#splitline{","\\splitline{"}; // check for }{ then }
2349 const Char_t *kLeft1[] = {"#left[","\\left[","#left{","\\left{","#left|","\\left|","#left(","\\left("};
2350 const Char_t *kLeft2[] = {"#[]{","#[]{","#{}{","#{}{","#||{","#||{","#(){","#(){"};
2351 const Char_t *kRight[] = {"#right]","\\right]","#right}","\\right}","#right|","\\right|","#right)","\\right)"};
2352 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};
2353 const Int_t lkWord2[] = {7,7,5,6,6,6,7,7,7,6,6,6,7} ;
2354 const Int_t lkWord3[] = {6,6,11,11} ;
2355 Int_t nkWord1 = 45, nkWord2 = 13, nkWord3 = 4;
2356 Int_t i,k ;
2358 Int_t lLeft1 = 6 ;
2359 Int_t lLeft2 = 4 ;
2360 Int_t lRight = 7 ;
2361 nLeft1 = nRight = 8 ;
2362 nOfLeft = nOfRight = 0 ;
2363
2364 Char_t buf[11] ; for (i=0;i<11;i++) buf[i]=0;
2365 Bool_t opFound ;
2366 Int_t opFrac = 0;
2367 Int_t length = text.Length() ;
2368
2371 Int_t error = 0 ;
2373
2374 // first find and replace all occurrences of "kLeft1" keyword by "kLeft2" keyword,
2375 // and all occurrences of "kRight" keyword by "}".
2376 i = 0 ;
2377 while (i < length) {
2378 // The string in 'buf' does not need to be null terminated,
2379 // we will only check with strncmp.
2380 strncpy(buf,&text[i],TMath::Min(7,length-i));
2381 opFound = kFALSE ;
2382 for (k = 0 ; k < nLeft1 ; k++) {
2383 if (strncmp(buf,kLeft1[k],lLeft1)==0) {
2384 nOfLeft++ ;
2385 i+=lLeft1 ;
2386 opFound = kTRUE ;
2387 break ;
2388 }
2389 }
2390 if (opFound) continue ;
2391
2392 for(k=0;k<nRight;k++) {
2393 if (strncmp(buf,kRight[k],lRight)==0) {
2394 nOfRight++ ;
2395 i+=lRight ;
2396 opFound = kTRUE ;
2397 break ;
2398 }
2399 }
2400 if (!opFound) i++ ;
2401 }
2402 if (nOfLeft != nOfRight) {
2403 printf(" nOfLeft = %d, nOfRight = %d\n",nOfLeft,nOfRight) ;
2404 error = 1 ;
2405 fError = "Operators \"#left\" and \"#right\" don't match !" ;
2406 goto ERROR_END ;
2407 }
2408
2409 for (k = 0 ; k < nLeft1 ; k++) {
2410 text.ReplaceAll(kLeft1[k],lLeft1,kLeft2[k],lLeft2) ;
2411 }
2412 for (k = 0 ; k < nRight ; k++) {
2413 text.ReplaceAll(kRight[k],lRight,"}",1) ;
2414 }
2415 length = text.Length() ;
2416
2418 while (i< length){
2419 switch (text[i]) {
2420 case '"' : quote1 = !quote1 ; break ;
2421 case '\'': quote2 = !quote2 ; break ;
2422 }
2423 // The string in 'buf' does not need to be null terminated,
2424 // we will only check with strncmp
2425 strncpy(buf,&text[i],TMath::Min(11,length-i));
2426 opFound = kFALSE ;
2427
2428 for(k=0;k<nkWord1;k++) {
2429 if (strncmp(buf,kWord1[k],lkWord1[k])==0) {
2430 nOfKW1++ ;
2431 i+=lkWord1[k] ;
2432 opFound = kTRUE ;
2433 nOfCurlyBracket++ ;
2434 break ;
2435 }
2436 }
2437 if (opFound) continue ;
2438
2439 for(k=0;k<nkWord2;k++) {
2440 if (strncmp(buf,kWord2[k],lkWord2[k])==0) {
2441 nOfKW2++ ;
2442 i+=lkWord2[k] ;
2443 opFound = kTRUE ;
2445 break ;
2446 }
2447 }
2448 if (opFound) continue ;
2449
2450 for(k=0;k<nkWord3;k++) {
2451 if (strncmp(buf,kWord3[k],lkWord3[k])==0) {
2452 nOfKW3++ ;
2453 i+=lkWord3[k] ;
2454 opFound = kTRUE ;
2455 opFrac++ ;
2456 nOfCurlyBracket++ ;
2457 break ;
2458 }
2459 }
2460 if (opFound) continue ;
2461 if (strncmp(buf,"}{",2) == 0 && opFrac) {
2462 opFrac-- ;
2463 nOfCurlyCurly++ ;
2464 i+= 2;
2465 }
2466 else if (strncmp(buf,"]{",2) == 0 && nOfSquareBracket) {
2467 nOfSquareCurly++ ;
2468 i+= 2 ;
2469 nOfCurlyBracket++ ;
2471 }
2472 else if (strncmp(buf,"@{",2) == 0 || strncmp(buf,"@}",2) == 0) {
2473 i+= 2 ;
2474 }
2475 else if (strncmp(buf,"@[",2) == 0 || strncmp(buf,"@]",2) == 0) {
2476 i+= 2 ;
2477 }
2478 else if (text[i] == ']' ) { // not belonging to a key word, add @ in front
2479 text.Insert(i,"@") ;
2480 length++ ;
2481 i+=2 ;
2482 }
2483 else if (text[i] == '[' ) { // not belonging to a key word, add @ in front
2484 text.Insert(i,"@") ;
2485 length++ ;
2486 i+=2 ;
2487 }
2488 else if (text[i] == '{' ) { // not belonging to a key word, add @ in front
2489 text.Insert(i,"@") ;
2490 length++ ;
2491 i+=2 ;
2492 }
2493 else if (text[i] == '}' ) {
2494 if ( nOfCurlyBracket) {
2495 nOfCurlyBracket-- ;
2496 i++ ;
2497 } else { // extra }, add @ in front
2498 text.Insert(i,"@") ;
2499 length++ ;
2500 i+=2 ;
2501 }
2502 } else {
2503 i++ ;
2504 buf[1] = 0 ;
2505 }
2506 }
2507
2508 if (nOfKW2 != nOfSquareCurly) {
2509 error = 1 ;
2510 fError = "Invalid number of \"]{\"" ;
2511 }
2512 else if (nOfKW3 != nOfCurlyCurly) {
2513 error = 1 ;
2514 fError = "Error in syntax of \"#frac\"" ;
2515 }
2516 else if (nOfCurlyBracket < 0) {
2517 error = 1 ;
2518 fError = "Missing \"{\"" ;
2519 }
2520 else if (nOfCurlyBracket > 0) {
2521 error = 1 ;
2522 fError = "Missing \"}\"" ;
2523 }
2524 else if (nOfSquareBracket < 0) {
2525 error = 1 ;
2526 fError = "Missing \"[\"" ;
2527 }
2528 else if (nOfSquareBracket > 0) {
2529 error = 1 ;
2530 fError = "Missing \"]\"" ;
2531 }
2532
2533 ERROR_END:
2534 return error ;
2535}
2536
2537////////////////////////////////////////////////////////////////////////////////
2538/// First parsing of the analyse sequence
2539
2541{
2542 fTabSize.reserve(100); // ensure 100 entries before memory reallocation required
2543 fShow = kFALSE;
2544 fOriginSize = size;
2545
2546 //get current line attributes
2549
2551 spec.fAngle = angle;
2552 spec.fSize = GetTextSizePercent(size);
2553 spec.fColor = GetTextColor();
2554 spec.fFont = GetTextFont();
2557
2559
2562 SetTextFont(spec.fFont);
2563 SetTextColor(spec.fColor);
2567 return fs;
2568}
2569
2570////////////////////////////////////////////////////////////////////////////////
2571/// Return height of current pad in pixels
2572
2574{
2575 if (!gPad) return 0.;
2576 Double_t w = gPad->GetAbsWNDC()*Double_t(gPad->GetWw());
2577 Double_t h = gPad->GetAbsHNDC()*Double_t(gPad->GetWh());
2578 if (w < h)
2579 return w;
2580 else
2581 return h;
2582}
2583
2584////////////////////////////////////////////////////////////////////////////////
2585/// Return size of the formula along X in pad coordinates when the text precision
2586/// is smaller than 3.
2587
2589{
2590 if (!gPad) return 0.;
2592 if( newText.Length() == 0) return 0;
2593
2594 // The text is a TMathText.
2595 if ( newText.Contains("\\") ) {
2596 TMathText tm(0., 0., newText.Data());
2597 return tm.GetXsize();
2598 }
2599
2600 fError = nullptr;
2602 Error("GetXsize", "%s\n==> %s", fError, GetTitle());
2603 return 0;
2604 }
2605 fError = nullptr;
2606
2607 const Char_t *text = newText.Data() ;
2611 fTabSize.clear();
2612 return std::abs(gPad->AbsPixeltoX(fs.Width()) - gPad->AbsPixeltoX(0));
2613}
2614
2615////////////////////////////////////////////////////////////////////////////////
2616/// Return text size in pixels
2617
2619{
2620 if (!gPad) return;
2622 if( newText.Length() == 0) return;
2623
2624 // The text is a TMathText.
2625 if ( newText.Contains("\\") ) {
2626 TMathText tm(0., 0., newText.Data());
2627 tm.GetBoundingBox(w, h);
2628 return;
2629 }
2630
2631 fError = nullptr;
2633 Error("GetBoundingBox", "%s\n==> %s", fError, GetTitle());
2634 return;
2635 }
2636 fError = nullptr;
2637
2638 if (angle) {
2639 Int_t cBoxX[4], cBoxY[4];
2640 Int_t ptx, pty;
2641 if (TestBit(kTextNDC)) {
2642 ptx = gPad->UtoPixel(fX);
2643 pty = gPad->VtoPixel(fY);
2644 } else {
2645 ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX));
2646 pty = gPad->YtoAbsPixel(gPad->YtoPad(fY));
2647 }
2649 Int_t x1 = cBoxX[0];
2650 Int_t x2 = cBoxX[0];
2651 Int_t y1 = cBoxY[0];
2652 Int_t y2 = cBoxY[0];
2653 for (Int_t i=1; i<4; i++) {
2654 if (cBoxX[i] < x1) x1 = cBoxX[i];
2655 if (cBoxX[i] > x2) x2 = cBoxX[i];
2656 if (cBoxY[i] < y1) y1 = cBoxY[i];
2657 if (cBoxY[i] > y2) y2 = cBoxY[i];
2658 }
2659 w = x2-x1;
2660 h = y2-y1;
2661 } else {
2662 const Char_t *text = newText.Data() ;
2664 fTabSize.clear();
2665 w = (UInt_t)fs.Width();
2666 h = (UInt_t)fs.Height();
2667 }
2668}
2669
2670////////////////////////////////////////////////////////////////////////////////
2671/// Return size of the formula along Y in pad coordinates when the text precision
2672/// is smaller than 3.
2673
2675{
2676 if (!gPad) return 0.;
2678 if( newText.Length() == 0) return 0;
2679
2680 // The text is a TMathText.
2681 if ( newText.Contains("\\") ) {
2682 TMathText tm(0., 0., newText.Data());
2683 return tm.GetYsize();
2684 }
2685
2686 fError = nullptr;
2688 Error("GetYsize", "%s\n==> %s", fError, GetTitle());
2689 return 0;
2690 }
2691 fError = nullptr;
2692
2693 const Char_t *text = newText.Data();
2697 fTabSize.clear();
2698 return std::abs(gPad->AbsPixeltoY(fs.Height()) - gPad->AbsPixeltoY(0));
2699}
2700
2701////////////////////////////////////////////////////////////////////////////////
2702/// Read fs in fTabSize
2703
2705{
2706 if (fTabSize.empty()) {
2707 Error("Readfs", "No data in fTabSize stack");
2708 return TLatexFormSize(0,0,0);
2709 }
2710
2712 fTabSize.pop_back();
2713 return result;
2714}
2715
2716////////////////////////////////////////////////////////////////////////////////
2717/// Save fs values in array fTabSize
2718
2720{
2721 fTabSize.emplace_back(*fs);
2722}
2723
2724////////////////////////////////////////////////////////////////////////////////
2725/// Save primitive as a C++ statement(s) on output stream out
2726
2727void TLatex::SavePrimitive(std::ostream &out, Option_t *option)
2728{
2730 out, Class(), "tex",
2731 TString::Format("%g, %g, \"%s\"", fX, fY, TString(GetTitle()).ReplaceSpecialCppChars().Data()), kFALSE);
2732
2733 SaveTextAttributes(out, "tex", 11, 0, 1, 62, 0.05);
2734 SaveLineAttributes(out, "tex", 1, 1, 1);
2735
2736 if (TestBit(kTextNDC))
2737 out << " tex->SetNDC();\n";
2738
2739 SavePrimitiveDraw(out, "tex", option);
2740}
2741
2742////////////////////////////////////////////////////////////////////////////////
2743/// Set relative size of subscripts and superscripts
2744
2746{
2748}
2749
2750////////////////////////////////////////////////////////////////////////////////
2751/// Set limit for text resizing of subscripts and superscripts
2752
2754{
2756}
#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:2751
Double_t GetXsize()
Return size of the formula along X in pad coordinates when the text precision is smaller than 3.
Definition TLatex.cxx:2586
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:2571
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:2058
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:2099
static TClass * Class()
virtual void SetIndiceSize(Double_t factorSize)
Set relative size of subscripts and superscripts.
Definition TLatex.cxx:2743
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:2233
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:2672
TLatexFormSize FirstParse(Double_t angle, Double_t size, const Char_t *text)
First parsing of the analyse sequence.
Definition TLatex.cxx:2538
TLatexFormSize Readfs()
Read fs in fTabSize.
Definition TLatex.cxx:2702
void GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle=kFALSE) override
Return text size in pixels.
Definition TLatex.cxx:2616
TLatex * DrawLatexNDC(Double_t x, Double_t y, const char *text)
Draw this TLatex with new coordinates in NDC.
Definition TLatex.cxx:2013
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:2072
virtual void PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Main drawing function.
Definition TLatex.cxx:2152
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:2725
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:2026
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:1999
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:2130
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:2339
void Savefs(TLatexFormSize *fs)
Save fs values in array fTabSize.
Definition TLatex.cxx:2717
@ 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:539
virtual void GetTextAscentDescent(UInt_t &a, UInt_t &d, const char *text) const
Return text ascent and descent for string text.
Definition TText.cxx:504
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:403
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