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