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" };
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 if (!opFound)
959 for(k=0;k<82;k++) {
960 if ((opSpec==-1 || strlen(tab2[k])>lastsize) && UInt_t(length)>i+strlen(tab2[k])) {
961 if (strncmp(&text[i+1],tab2[k],strlen(tab2[k]))==0) {
962 lastsize = strlen(tab2[k]);
963 opSpec=k;
964 opFound = kTRUE;
965 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
966 }
967 }
968 }
969 }
970 }
971
976
977 // analysis of operators found
978 if (opCloseCurly>-1 && opCloseCurly<length-1) { // separator } found
979 if(!fShow) {
982 Savefs(&fs1);
983 } else {
984 fs1 = Readfs();
987 }
988 result = fs1+fs2;
989 }
990
991 else if (opPower>-1 && opUnder>-1) { // ^ and _ found
993 max = std::max(opPower,opUnder);
994 Double_t xfpos = 0. ; //GetHeight()*spec.fSize/5.;
995 Double_t prop=1, propU=1; // scale factor for #sum & #int
996 switch (abovePlace) {
997 case 1 :
998 prop = .8 ; propU = 1.75 ; // Int
999 break;
1000 case 2:
1001 prop = .9 ; propU = 1.75 ; // Sum
1002 break;
1003 }
1004 // propU acts on upper number
1005 // when increasing propU value, the upper indice position is higher
1006 // when increasing prop values, the lower indice position is lower
1007
1008 if (!fShow) {
1009 Int_t ltext = min ;
1010 if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) {
1011 // upper and lower indice before the character
1012 // like with chemical element
1013 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1014 ltext-- ;
1015 }
1016 fs1 = Anal1(spec,text,ltext);
1017 fs2 = Anal1(specNewSize,text+min+1,max-min-1);
1018 fs3 = Anal1(specNewSize,text+max+1,length-max-1);
1019 Savefs(&fs1);
1020 Savefs(&fs2);
1021 Savefs(&fs3);
1022 } else {
1023 fs3 = Readfs();
1024 fs2 = Readfs();
1025 fs1 = Readfs();
1026 Double_t pos = 0;
1027 if (!abovePlace) {
1028 Double_t addW = fs1.Width()+xfpos, addH1, addH2;
1029 if (opPower<opUnder) {
1030 addH1 = -fs1.Over()*(fFactorPos)-fs2.Under();
1031 addH2 = fs1.Under()+fs3.Over()*(fFactorPos);
1032 } else {
1033 addH1 = fs1.Under()+fs2.Over()*(fFactorPos);
1034 addH2 = -fs1.Over()*(fFactorPos)-fs3.Under();
1035 }
1036 Analyse(x+addW,y+addH2,specNewSize,text+max+1,length-max-1);
1037 Analyse(x+addW,y+addH1,specNewSize,text+min+1,max-min-1);
1038 } else {
1040 Double_t m = std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width()));
1041 pos = (m-fs1.Width())/2;
1042 if (opPower<opUnder) {
1043 addH1 = -fs1.Over()*propU-fs2.Under();
1044 addW1 = (m-fs2.Width())/2;
1045 addH2 = fs1.Under()*prop+fs3.Over();
1046 addW2 = (m-fs3.Width())/2;
1047 } else {
1048 addH1 = fs1.Under()*prop+fs2.Over();
1049 addW1 = (m-fs2.Width())/2;
1050 addH2 = -fs1.Over()*propU-fs3.Under();
1051 addW2 = (m-fs3.Width())/2;
1052 }
1053
1054 Analyse(x+addW2,y+addH2,specNewSize,text+max+1,length-max-1);
1055 Analyse(x+addW1,y+addH1,specNewSize,text+min+1,max-min-1);
1056 }
1057
1058 if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) {
1059 snprintf(&text[min-2],length-(min-2)," ") ;
1060 Analyse(x+pos,y,spec,text,min-1);
1061 } else {
1062 Analyse(x+pos,y,spec,text,min);
1063 }
1064 }
1065
1066 if (!abovePlace) {
1067 if (opPower<opUnder) {
1068 result.Set(fs1.Width()+xfpos+std::max(fs2.Width(),fs3.Width()),
1069 fs1.Over()*fFactorPos+fs2.Height(),
1070 fs1.Under()+fs3.Height()-fs3.Over()*(1-fFactorPos));
1071 } else {
1072 result.Set(fs1.Width()+xfpos+std::max(fs2.Width(),fs3.Width()),
1073 fs1.Over()*fFactorPos+fs3.Height(),
1074 fs1.Under()+fs2.Height()-fs2.Over()*(1-fFactorPos));
1075 }
1076 } else {
1077 if (opPower<opUnder) {
1078 result.Set(std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width())),
1079 fs1.Over()*propU+fs2.Height(),fs1.Under()*prop+fs3.Height());
1080 } else {
1081 result.Set(std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width())),
1082 fs1.Over()*propU+fs3.Height(),fs1.Under()*prop+fs2.Height());
1083 }
1084 }
1085 }
1086 else if (opPower>-1) { // ^ found
1087 Double_t prop=1;
1088 Double_t xfpos = 0. ; //GetHeight()*spec.fSize/5. ;
1089 switch (abovePlace) {
1090 case 1 : //int
1091 prop = 1.75 ; break ;
1092 case 2 : // sum
1093 prop = 1.75; break ;
1094 }
1095 // When increasing prop, the upper indice position is higher
1096 if (!fShow) {
1097 Int_t ltext = opPower ;
1098 if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) {
1099 // upper and lower indice before the character
1100 // like with chemical element
1101 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1102 ltext-- ;
1103 }
1104 fs1 = Anal1(spec,text,ltext);
1106 Savefs(&fs1);
1107 Savefs(&fs2);
1108 } else {
1109 fs2 = Readfs();
1110 fs1 = Readfs();
1111 Int_t pos = 0;
1112 if (!abovePlace){
1113 Double_t over = fs1.Over();
1114 if (over <= 0) over = 1.5*fs2.Over();
1116 } else {
1117 Int_t pos2=0;
1118 if (fs2.Width()>fs1.Width())
1119 pos=Int_t((fs2.Width()-fs1.Width())/2);
1120 else
1121 pos2=Int_t((fs1.Width()-fs2.Width())/2);
1122
1124 }
1125 if (opPower >= 2 && strncmp(&text[opPower-2],"{}",2)==0) {
1126 snprintf(&text[opPower-2],length-(opPower-2)," ") ;
1127 Analyse(x+pos,y,spec,text,opPower-1);
1128 } else {
1129 Analyse(x+pos,y,spec,text,opPower);
1130 }
1131 }
1132
1133 if (!abovePlace)
1134 result.Set(fs1.Width()+xfpos+fs2.Width(),
1135 fs1.Over()*fFactorPos+fs2.Over(),fs1.Under());
1136 else
1137 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Over()*prop+fs2.Height(),fs1.Under());
1138
1139 }
1140 else if (opUnder>-1) { // _ found
1141 Double_t prop = .9; // scale factor for #sum & #frac
1142 Double_t xfpos = 0.;//GetHeight()*spec.fSize/5. ;
1144 // When increasing prop, the lower indice position is lower
1145 if(!fShow) {
1146 Int_t ltext = opUnder ;
1147 if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) {
1148 // upper and lower indice before the character
1149 // like with chemical element
1150 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1151 ltext-- ;
1152 }
1153 fs1 = Anal1(spec,text,ltext);
1155 Savefs(&fs1);
1156 Savefs(&fs2);
1157 } else {
1158 fs2 = Readfs();
1159 fs1 = Readfs();
1160 Int_t pos = 0;
1161 if (!abovePlace)
1162 Analyse(x+fs1.Width()+xfpos,y+fs1.Under()+fs2.Over()*fpos,specNewSize,text+opUnder+1,length-opUnder-1);
1163 else {
1164 Int_t pos2=0;
1165 if (fs2.Width()>fs1.Width())
1166 pos=Int_t((fs2.Width()-fs1.Width())/2);
1167 else
1168 pos2=Int_t((fs1.Width()-fs2.Width())/2);
1169
1171 }
1172 if (opUnder >= 2 && strncmp(&text[opUnder-2],"{}",2)==0) {
1173 snprintf(&text[opUnder-2],length-(opUnder-2)," ") ;
1174 Analyse(x+pos,y,spec,text,opUnder-1);
1175 } else {
1176 Analyse(x+pos,y,spec,text,opUnder);
1177 }
1178 }
1179 if (!abovePlace)
1180 result.Set(fs1.Width()+xfpos+fs2.Width(),fs1.Over(),
1181 fs1.Under()+fs2.Under()+fs2.Over()*fpos);
1182 else
1183 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Over(),fs1.Under()*prop+fs2.Height());
1184 }
1185 else if (opBox) {
1186 Double_t square = GetHeight()*spec.fSize/2;
1187 if (!fShow) {
1188 fs1 = Anal1(spec,text+4,length-4);
1189 } else {
1191 Double_t adjust = GetHeight()*spec.fSize/20;
1192 Double_t x1 = x+adjust ;
1194 Double_t y1 = y;
1200 }
1202 }
1203 else if (opOdot) {
1204 Double_t square = GetHeight()*spec.fSize/2;
1205 if (!fShow) {
1206 fs1 = Anal1(spec,text+5,length-5);
1207 } else {
1208 fs1 = Analyse(x+1.3*square,y,spec,text+5,length-5);
1209 Double_t adjust = GetHeight()*spec.fSize/20;
1210 Double_t r1 = 0.62*square;
1211 Double_t y1 = y-0.3*square-adjust;
1212 DrawCircle(x+0.6*square,y1,r1,spec) ;
1213 DrawCircle(x+0.6*square,y1,r1/100,spec) ;
1214 }
1216 }
1217 else if (opHbar) {
1218 Double_t square = GetHeight()*spec.fSize/2;
1219 if (!fShow) {
1220 fs1 = Anal1(spec,text+5,length-5);
1221 } else {
1223 TText hbar;
1224 hbar.SetTextFont(12);
1225 hbar.SetTextColor(spec.fColor);
1226 hbar.SetTextSize(spec.fSize);
1227 hbar.SetTextAngle(fTextAngle);
1228 hbar.SetTextAlign(11);
1229 Double_t xx, yy;
1230 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1231 hbar.PaintText(xx,yy,"h");
1232 DrawLine(x,y-0.8*square,x+0.75*square,y-square,spec);
1233 }
1235 }
1236 else if (opMinus) {
1237 Double_t square = GetHeight()*spec.fSize/2;
1238 if (!fShow) {
1239 fs1 = Anal1(spec,text+6,length-6);
1240 } else {
1242 TText minus;
1243 minus.SetTextFont(122);
1244 minus.SetTextColor(spec.fColor);
1245 minus.SetTextSize(spec.fSize);
1246 minus.SetTextAngle(fTextAngle);
1247 minus.SetTextAlign(11);
1248 Double_t xx, yy;
1249 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1250 minus.PaintText(xx,yy,"-");
1251 }
1253 }
1254 else if (opPlus) {
1255 Double_t square = GetHeight()*spec.fSize/2;
1256 if (!fShow) {
1257 fs1 = Anal1(spec,text+5,length-5);
1258 } else {
1260 TText plus;
1261 plus.SetTextFont(122);
1262 plus.SetTextColor(spec.fColor);
1263 plus.SetTextSize(spec.fSize);
1264 plus.SetTextAngle(fTextAngle);
1265 plus.SetTextAlign(11);
1266 Double_t xx, yy;
1267 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1268 plus.PaintText(xx,yy,"+");
1269 }
1271 }
1272 else if (opMp) {
1273 Double_t square = GetHeight()*spec.fSize/2;
1274 if (!fShow) {
1275 fs1 = Anal1(spec,text+3,length-3);
1276 } else {
1278 TText mp;
1279 mp.SetTextFont(122);
1280 mp.SetTextColor(spec.fColor);
1281 mp.SetTextSize(spec.fSize);
1282 mp.SetTextAngle(fTextAngle+180);
1283 mp.SetTextAlign(11);
1284 Double_t xx, yy;
1285 Rotate(gPad, spec.fAngle, x+square, y-1.25*square, xx, yy);
1286 mp.PaintText(xx,yy,"\261");
1287 }
1289 }
1290 else if (opPerp) {
1291 Double_t square = GetHeight()*spec.fSize/1.4;
1292 if (!fShow) {
1293 fs1 = Anal1(spec,text+5,length-5);
1294 } else {
1295 fs1 = Analyse(x+0.5*square,y,spec,text+5,length-5);
1296 Double_t x0 = x + 0.50*square;
1297 Double_t x1 = x0 - 0.48*square;
1298 Double_t x2 = x0 + 0.48*square;
1299 Double_t y1 = y + 0.6*square;
1300 Double_t y2 = y1 - 1.3*square;
1302 DrawLine(x0,y1,x0,y2,spec);
1303 }
1304 result = fs1;
1305 }
1306 else if (opBackslash) {
1307 Double_t square = GetHeight()*spec.fSize/2;
1308 if (!fShow) {
1309 fs1 = Anal1(spec,text+10,length-10);
1310 } else {
1311 fs1 = Analyse(x+square,y,spec,text+10,length-10);
1312 TText bs;
1313 bs.SetTextFont(GetTextFont());
1314 bs.SetTextColor(spec.fColor);
1315 bs.SetTextSize(spec.fSize);
1316 bs.SetTextAngle(fTextAngle);
1317 bs.SetTextAlign(11);
1318 Double_t xx, yy;
1319 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1320 bs.PaintText(xx,yy,"\\");
1321 }
1323 }
1324 else if (opParallel) {
1325 Double_t square = GetHeight()*spec.fSize/1.4;
1326 if (!fShow) {
1327 fs1 = Anal1(spec,text+9,length-9);
1328 } else {
1329 fs1 = Analyse(x+0.5*square,y,spec,text+9,length-9);
1330 Double_t x1 = x + 0.15*square;
1331 Double_t x2 = x + 0.45*square;
1332 Double_t y1 = y + 0.3*square;
1333 Double_t y2 = y1- 1.3*square;
1336 }
1338 }
1339 else if (opGreek>-1) {
1341 newSpec.fFont = fItalic ? 152 : 122;
1342 char letter = 97 + opGreek;
1343 Double_t yoffset = 0.; // Greek letter too low
1344 if (opGreek>25) letter -= 58;
1345 if (opGreek == 52) letter = '\241'; //varUpsilon
1346 if (opGreek == 53) letter = '\316'; //epsilon
1347 if (!fShow) {
1348 fs1 = Anal1(newSpec,&letter,1);
1350 Savefs(&fs1);
1351 } else {
1352 fs1 = Readfs();
1355 }
1356 fs1.AddOver(TLatexFormSize(0,yoffset,0)) ;
1357 result = fs1+fs2;
1358 }
1359
1360 else if (opSpec > -1) {
1362 newSpec.fFont = fItalic ? 152 : 122;
1363 char letter = '\243' + opSpec;
1364 if(opSpec == 75 || opSpec == 76) {
1365 newSpec.fFont = GetTextFont();
1366 if (gPad->GetPainter()->IsCocoa()) {
1367 if (opSpec == 75) letter = '\201'; // AA Angstroem
1368 if (opSpec == 76) letter = '\214'; // aa Angstroem
1369 } else {
1370 if (opSpec == 75) letter = '\305'; // AA Angstroem
1371 if (opSpec == 76) letter = '\345'; // aa Angstroem
1372 }
1373 }
1374 if(opSpec == 80 || opSpec == 81) {
1375 if (opSpec == 80) letter = '\042'; // #forall
1376 if (opSpec == 81) letter = '\044'; // #exists
1377 }
1379 props = 1.8 ; // scale factor for #sum(66)
1380 propi = 2.3 ; // scale factor for #int(79)
1381
1382 if (opSpec==66 ) {
1383 newSpec.fSize = spec.fSize*props;
1384 } else if (opSpec==79) {
1385 newSpec.fSize = spec.fSize*propi;
1386 }
1387 if (!fShow) {
1388 fs1 = Anal1(newSpec,&letter,1);
1389 if (opSpec == 79 || opSpec == 66)
1390 fs1.Set(fs1.Width(),fs1.Over()*0.45,fs1.Over()*0.45);
1391
1393 Savefs(&fs1);
1394 } else {
1395 fs1 = Readfs();
1397 if (opSpec!=66 && opSpec!=79)
1398 Analyse(x,y,newSpec,&letter,1);
1399 else {
1400 Analyse(x,y+fs1.Under()/2.,newSpec,&letter,1);
1401 }
1402 }
1403 result = fs1+fs2;
1404 }
1405 else if (opAbove>-1) {
1406 if (!fShow) {
1408 Savefs(&fs1);
1409 } else {
1410 fs1 = Readfs();
1412 Double_t sub = GetHeight()*spec.fSize/14;
1413 switch(opAbove) {
1414 case 0: { // bar
1415 Double_t xx[2], yy[2];
1416 xx[0] = x; xx[1] = x + fs1.Width();
1417 yy[0] = yy[1] = y - sub - fs1.Over();
1418 DrawPolyLine(2, xx, yy, spec, 0.03);
1419 break;
1420 }
1421 case 1: { // vec
1422 Double_t xx[3], yy[3],
1423 dd = GetHeight()*spec.fSize/8, // arrow size
1424 midy = y - sub - fs1.Over() - dd; // middle arrow line
1425 xx[0] = x; xx[1] = x + fs1.Width();
1426 yy[0] = yy[1] = midy;
1427 DrawPolyLine(2, xx, yy, spec, 0.03);
1428 xx[1] = x + fs1.Width(); xx[0] = xx[2] = xx[1] - 2*dd;
1429 yy[0] = midy - dd; yy[1] = midy; yy[2] = midy + dd;
1430 DrawPolyLine(3, xx, yy, spec, 0.03);
1431 break;
1432 }
1433 case 2: { // dot
1434 Double_t dd = std::max(0.5*GetLineWidth(), 0.5*sub), // dot size
1435 midx = x + fs1.Width()/2,
1436 midy = y - sub - fs1.Over() - dd;
1437 Double_t xx[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1438 yy[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1439 DrawPolyLine(5, xx, yy, spec, 10.);
1440 break;
1441 }
1442 case 3: { // hat
1443 Double_t xx[3], yy[3];
1444 xx[1] = x + fs1.Width()/2;
1445 xx[0] = xx[1] - fs1.Width()/3;
1446 xx[2] = xx[1] + fs1.Width()/3;
1447 yy[0] = y - sub - fs1.Over();
1448 yy[1] = yy[0] - 2*sub;
1449 yy[2] = yy[0];
1450 DrawPolyLine(3, xx, yy, spec, 0.03);
1451 break;
1452 }
1453 case 4: { // ddot
1454 Double_t dd = std::max(0.5*GetLineWidth(), 0.5*sub), // dot size
1455 midx = x + fs1.Width()/2 - 1.5*sub,
1456 midy = y - sub - fs1.Over() - dd;
1457 Double_t xx1[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1458 yy1[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1459 DrawPolyLine(5, xx1, yy1, spec, 10.);
1460 midx = x + fs1.Width()/2 + 1.5*sub;
1461 Double_t xx2[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1462 yy2[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1463 DrawPolyLine(5, xx2, yy2, spec, 10.);
1464 break;
1465 }
1466 case 5: { // acute
1467 Double_t xx[2], yy[2];
1468 xx[0] = x + fs1.Width()/2; xx[1] = xx[0] + 3*sub;
1469 yy[0] = y - sub - fs1.Over();
1470 yy[1] = yy[0] - 2.5*sub;
1471 DrawPolyLine(2, xx, yy, spec, 0.03);
1472 break;
1473 }
1474 case 6: { // grave
1475 Double_t xx[2], yy[2];
1476 xx[0] = x + fs1.Width()/2 + sub; xx[1] = xx[0] - 2*sub;
1477 yy[0] = y - sub - fs1.Over();
1478 yy[1] = yy[0] - 2*sub;
1479 DrawPolyLine(2, xx, yy, spec, 0.03);
1480 break;
1481 }
1482 case 7: { // check
1483 Double_t xx[3], yy[3];
1484 xx[1] = x+fs1.Width()/2; xx[0] = xx[1] - 2*sub; xx[2] = xx[1] + 2*sub;
1485 yy[1] = y - sub - fs1.Over();
1486 yy[0] = yy[2] = yy[1] - 2*sub;
1487 DrawPolyLine(3, xx, yy, spec, 0.03);
1488 break;
1489 }
1490 case 8: { // tilde
1491 Double_t x2 = x+fs1.Width()/2, y2 = y -fs1.Over();
1492 // tilde must be drawn separately on screen and on PostScript
1493 // because an adjustment is required along Y for PostScript.
1494
1495 Double_t xx, yy;
1496 if (auto ps = gPad->GetPainter()->GetPS()) {
1497 if (!strstr(ps->GetTitle(), "IMG"))
1498 y2 -= 4*sub;
1499 Rotate(gPad, spec.fAngle, x2, y2, xx, yy);
1500 ps->SetTextAlign(22);
1501 ps->Text(xx, yy, "~");
1502 } else {
1503 if (gPad->GetPainter()->IsCocoa())
1504 y2 -= 4.7*sub;
1505 Rotate(gPad, spec.fAngle, x2, y2, xx, yy);
1506 // TODO: use pad painter SetAttText and DrawText directly
1507 TText tilde;
1508 tilde.SetTextFont(fTextFont);
1509 tilde.SetTextColor(spec.fColor);
1510 tilde.SetTextSize(0.9*spec.fSize);
1511 tilde.SetTextAlign(22);
1512 tilde.SetTextAngle(fTextAngle);
1513 tilde.PaintText(xx,yy,"~");
1514 }
1515 break;
1516 }
1517 case 9: { // slash
1518 Double_t xx[2], yy[2];
1519 xx[0] = x + 0.8*fs1.Width();
1520 yy[0] = y - fs1.Over() - sub;
1521 xx[1] = x + 0.3*fs1.Width();
1522 yy[1] = yy[0] + fs1.Height() + 2*sub;
1523 DrawPolyLine(2, xx, yy, spec, 0.03);
1524 break;
1525 }
1526 }
1527 }
1528 Double_t div = 3;
1529 if (opAbove==1) div=4;
1530 result.Set(fs1.Width(),fs1.Over()+GetHeight()*spec.fSize/div,fs1.Under());
1531 }
1532 else if (opSquareBracket) { // operator #[]{arg}
1533 Double_t l = GetHeight()*spec.fSize/4;
1534 Double_t l2 = l/2 ;
1535 if (!fShow) {
1536 fs1 = Anal1(spec,text+3,length-3);
1537 Savefs(&fs1);
1538 } else {
1539 fs1 = Readfs();
1540 Analyse(x+l2+l,y,spec,text+3,length-3);
1541 DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec);
1542 DrawLine(x+l2,y-fs1.Over(),x+l2+l,y-fs1.Over(),spec);
1543 DrawLine(x+l2,y+fs1.Under(),x+l2+l,y+fs1.Under(),spec);
1544 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec);
1545 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+l,y-fs1.Over(),spec);
1546 DrawLine(x+l2+fs1.Width()+2*l,y+fs1.Under(),x+l2+fs1.Width()+l,y+fs1.Under(),spec);
1547 }
1548 result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1549 }
1550 else if (opParen) { // operator #(){arg}
1551 Double_t l = GetHeight()*spec.fSize/4;
1552 Double_t radius2,radius1 , dw, l2 = l/2 ;
1553 Double_t angle = 35 ;
1554 if (!fShow) {
1555 fs1 = Anal1(spec,text+3,length-3);
1556 Savefs(&fs1);
1557 radius2 = fs1.Height() ;
1558 radius1 = radius2 * 2 / 3;
1559 dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ;
1560 } else {
1561 fs1 = Readfs();
1562 radius2 = fs1.Height();
1563 radius1 = radius2 * 2 / 3;
1564 dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ;
1565 Double_t x1 = x+l2+radius1 ;
1566 Double_t x2 = x+5*l2+2*dw+fs1.Width()-radius1 ;
1567 Double_t y1 = y - (fs1.Over() - fs1.Under())/2. ;
1570 Analyse(x+3*l2+dw,y,spec,text+3,length-3);
1571 }
1572 // result = TLatexFormSize(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1573 result.Set(fs1.Width()+3*l+2*dw,fs1.Over(),fs1.Under());
1574 }
1575 else if (opAbs) { // operator #||{arg}
1576 Double_t l = GetHeight()*spec.fSize/4;
1577 Double_t l2 = l/2 ;
1578 if (!fShow) {
1579 fs1 = Anal1(spec,text+3,length-3);
1580 Savefs(&fs1);
1581 } else {
1582 fs1 = Readfs();
1583 Analyse(x+l2+l,y,spec,text+3,length-3);
1584 DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec);
1585 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec);
1586 }
1587 result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1588 }
1589 else if (opBigCurly) { // big curly bracket #{}{arg}
1590 Double_t l = GetHeight()*spec.fSize/4;
1591 Double_t l2 = l/2 ;
1592 Double_t l8 , ltip;
1593
1594 if (!fShow) {
1595 fs1 = Anal1(spec,text+3,length-3);
1596 l8 = fs1.Height()/8 ;
1597 ltip = TMath::Min(l8,l) ;
1598 l = ltip ;
1599 Savefs(&fs1);
1600 } else {
1601 fs1 = Readfs();
1602 Double_t y2 = y + (fs1.Under()-fs1.Over())/2 ;
1603 l8 = fs1.Height()/8 ;
1604 ltip = TMath::Min(l8,l) ;
1605 l = ltip ;
1606 Analyse(x+l+ltip+l2,y,spec,text+3,length-3);
1607 // Draw open curly bracket
1608 // Vertical lines
1609 DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip,y2-ltip,spec);
1610 DrawLine(x+l2+ltip,y2+ltip,x+l2+ltip,y+fs1.Under(),spec);
1611 // top and bottom lines
1612 DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip+l,y-fs1.Over(),spec);
1613 DrawLine(x+l2+ltip,y+fs1.Under(),x+l2+ltip+l,y+fs1.Under(),spec);
1614 // < sign
1617
1618 // Draw close curly bracket
1619 // vertical lines
1620 DrawLine(x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y2-ltip,spec);
1621 DrawLine(x+l2+ltip+fs1.Width()+2*l,y2+ltip,x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec);
1622 // Top and bottom lines
1623 DrawLine(x+l2+fs1.Width()+l+ltip,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),spec);
1624 DrawLine(x+l2+fs1.Width()+l+ltip,y+fs1.Under(),x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec);
1625 // > sign
1626 DrawLine(x+l2+ltip+2*l+fs1.Width(),y2-ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec);
1627 DrawLine(x+l2+ltip+2*l+fs1.Width(),y2+ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec);
1628 }
1629 result.Set(fs1.Width()+3*l+2*ltip,fs1.Over(),fs1.Under());
1630 }
1631 else if (opFrac>-1) { // \frac found
1632 if (opCurlyCurly==-1) { // }{ not found
1633 // arguments missing for \frac
1634 fError = "Missing denominator for #frac";
1635 delete[] text;
1636 return TLatexFormSize(0,0,0);
1637 }
1638 Double_t height = GetHeight()*spec.fSize/8;
1639 if (!fShow) {
1642 Savefs(&fs1);
1643 Savefs(&fs2);
1644 } else {
1645 fs2 = Readfs();
1646 fs1 = Readfs();
1648 if (fs1.Width()<fs2.Width()) {
1649 addW1 = (fs2.Width()-fs1.Width())/2;
1650 addW2 = 0;
1651 } else {
1652 addW1 = 0;
1653 addW2 = (fs1.Width()-fs2.Width())/2;
1654 }
1655 Analyse(x+addW2,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // denominator
1656 Analyse(x+addW1,y-fs1.Under()-3*height,spec,text+opFrac+6,opCurlyCurly-opFrac-6); //numerator
1657
1658 DrawLine(x,y-2*height,x+std::max(fs1.Width(),fs2.Width()),y-2*height,spec);
1659 }
1660
1661 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
1662
1663 }
1664 else if (opSplitLine>-1) { // \splitline found
1665 if (opCurlyCurly==-1) { // }{ not found
1666 // arguments missing for \splitline
1667 fError = "Missing second line for #splitline";
1668 delete[] text;
1669 return TLatexFormSize(0,0,0);
1670 }
1671 Double_t height = GetHeight()*spec.fSize/8;
1672 if (!fShow) {
1675 Savefs(&fs1);
1676 Savefs(&fs2);
1677 } else {
1678 fs2 = Readfs();
1679 fs1 = Readfs();
1680 Analyse(x,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // second line
1681 Analyse(x,y-fs1.Under()-3*height,spec,text+opSplitLine+11,opCurlyCurly-opSplitLine-11); //first line
1682 }
1683
1684 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
1685
1686 }
1687 else if (opSqrt>-1) { // \sqrt found
1688 if (!fShow) {
1689 if (opSquareCurly>-1) {
1690 // power nth #sqrt[n]{arg}
1693 Savefs(&fs1);
1694 Savefs(&fs2);
1695 result.Set(fs2.Width()+ GetHeight()*spec.fSize/10+std::max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width()),
1696 fs2.Over()+fs1.Height()+GetHeight()*spec.fSize/4,fs2.Under());
1697 } else {
1699 Savefs(&fs1);
1700 result.Set(fs1.Width()+GetHeight()*spec.fSize/2,fs1.Over()+GetHeight()*spec.fSize/4,fs1.Under());
1701 }
1702 } else {
1703 if (opSquareCurly>-1) { // ]{
1704 fs2 = Readfs();
1705 fs1 = Readfs();
1706 Double_t pas = std::max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width());
1707 Double_t pas2 = pas + GetHeight()*spec.fSize/10;
1708 Double_t y1 = y-fs2.Over() ;
1709 Double_t y2 = y+fs2.Under() ;
1710 Double_t y3 = y1-GetHeight()*spec.fSize/4;
1712 Analyse(x,y-fs2.Over()-fs1.Under(),specNewSize,text+opSqrt+6,opSquareCurly-opSqrt-6); // indice
1713 DrawLine(x,y1,x+pas,y2,spec);
1715 DrawLine(x+pas,y3,x+pas2+fs2.Width(),y3,spec);
1716 } else {
1717 fs1 = Readfs();
1718 Double_t x1 = x+GetHeight()*spec.fSize*2/5 ;
1719 Double_t x2 = x+GetHeight()*spec.fSize/2+fs1.Width() ;
1720 Double_t y1 = y-fs1.Over() ;
1721 Double_t y2 = y+fs1.Under() ;
1722 Double_t y3 = y1-GetHeight()*spec.fSize/4;
1723
1725
1727 SetLineWidth(1);
1728 Double_t dx = (y2-y3)/8;
1729 UInt_t a,d;
1731 if (a>12) SetLineWidth(std::max(2,(Int_t)(dx/2)));
1732 DrawLine(x1-2*dx,y1,x1-dx,y2,spec);
1733 if (a>12) SetLineWidth(std::max(1,(Int_t)(dx/4)));
1737 }
1738 }
1739 }
1740 else if (opColor>-1) { // \color found
1741 if (opSquareCurly==-1) {
1742 // color number is not specified
1743 fError = "Missing color number. Syntax is #color[(Int_t)nb]{ ... }";
1744 delete[] text;
1745 return TLatexFormSize(0,0,0);
1746 }
1750 nb[opSquareCurly-opColor-7] = 0;
1751 if (sscanf(nb,"%d",&newSpec.fColor) < 1) {
1752 delete[] nb;
1753 // color number is invalid
1754 fError = "Invalid color number. Syntax is #color[(Int_t)nb]{ ... }";
1755 delete[] text;
1756 return TLatexFormSize(0,0,0);
1757 }
1758 delete[] nb;
1759 if (!fShow) {
1761 } else {
1763 }
1764 }
1765 else if (opUrl>-1) { // \url found
1766 if (opSquareCurly==-1) {
1767 // url is not specified
1768 fError = "Missing url. Syntax is #url[http://...]{ ... }";
1769 delete[] text;
1770 return TLatexFormSize(0,0,0);
1771 }
1775 fName = url;
1776 delete[] url;
1777 if (!fShow) {
1779 } else {
1781 }
1782 fName = "";
1783 }
1784 else if (opFont>-1) { // \font found
1785 if (opSquareCurly==-1) {
1786 // font number is not specified
1787 fError = "Missing font number. Syntax is #font[nb]{ ... }";
1788 delete[] text;
1789 return TLatexFormSize(0,0,0);
1790 }
1794 nb[opSquareCurly-opFont-6] = 0;
1795 if (sscanf(nb,"%d",&newSpec.fFont) < 1) {
1796 delete[] nb;
1797 // font number is invalid
1798 fError = "Invalid font number. Syntax is #font[(Int_t)nb]{ ... }";
1799 delete[] text;
1800 return TLatexFormSize(0,0,0);
1801 }
1802 delete[] nb;
1803 if (!fShow) {
1805 } else {
1807 }
1808 }
1809 else if (opKern>-1) { // #kern found
1810 if (opSquareCurly==-1) {
1811 // horizontal shift is not specified
1812 fError = "Missing horizontal shift number. Syntax is #kern[dx]{ ... }";
1813 delete[] text;
1814 return TLatexFormSize(0,0,0);
1815 }
1818 dxc[opSquareCurly-opKern-6] = 0;
1819 Float_t dx = 0;
1820 if (sscanf(dxc,"%f",&dx) < 1) {
1821 delete[] dxc;
1822 // horizontal shift number is invalid
1823 fError = "Invalid horizontal shift number. Syntax is #kern[(Float_t)dx]{ ... }";
1824 delete[] text;
1825 return TLatexFormSize(0,0,0);
1826 }
1827 delete[] dxc;
1828 if (!fShow) {
1830 Savefs(&fs1);
1831 Double_t ddx = dx * fs1.Width();
1832 result = TLatexFormSize(fs1.Width() + ddx, fs1.Over(), fs1.Under());
1833 } else {
1834 fs1 = Readfs();
1835 Double_t ddx = dx * fs1.Width();
1837 }
1838 }
1839 else if (opLower>-1) { // #lower found
1840 if (opSquareCurly==-1) {
1841 // vertical shift is not specified
1842 fError = "Missing vertical shift number. Syntax is #lower[dy]{ ... }";
1843 delete[] text;
1844 return TLatexFormSize(0,0,0);
1845 }
1848 dyc[opSquareCurly-opLower-7] = 0;
1849 Float_t dy = 0;
1850 if (sscanf(dyc,"%f",&dy) < 1) {
1851 delete[] dyc;
1852 // vertical shift number is invalid
1853 fError = "Invalid vertical shift number. Syntax is #lower[(Float_t)dy]{ ... }";
1854 delete[] text;
1855 return TLatexFormSize(0,0,0);
1856 }
1857 delete[] dyc;
1858 if (!fShow) {
1860 Savefs(&fs1);
1861 Double_t ddy = dy * (fs1.Over() + fs1.Under());
1862 result = TLatexFormSize(fs1.Width(), fs1.Over() + ddy, fs1.Under() + ddy);
1863 } else {
1864 fs1 = Readfs();
1865 Double_t ddy = dy * (fs1.Over() + fs1.Under());
1867 }
1868 }
1869 else if (opScale>-1) { // \scale found
1870 if (opSquareCurly==-1) {
1871 // scale factor is not specified
1872 fError = "Missing scale factor. Syntax is #scale[(Double_t)nb]{ ... }";
1873 delete[] text;
1874 return TLatexFormSize(0,0,0);
1875 }
1879 nb[opSquareCurly-opScale-7] = 0;
1880 if (sscanf(nb,"%lf",&newSpec.fSize) < 1) {
1881 delete[] nb;
1882 // scale factor is invalid
1883 fError = "Invalid scale factor. Syntax is #factor[(Double_t)nb]{ ... }";
1884 delete[] text;
1885 return TLatexFormSize(0,0,0);
1886 }
1887 newSpec.fSize *= spec.fSize;
1888 delete[] nb;
1889 if (!fShow) {
1891 } else {
1893 }
1894 }
1895 else if (opBf>-1) { // operator #bf{arg}
1897 Int_t lut[] = {3, 13, 1, 6, 7, 4, 5, 10, 11, 8, 9, 12, 2, 14, 15};
1898 Int_t fontId = (newSpec.fFont/10);
1899 if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1];
1900 newSpec.fFont = fontId*10 + newSpec.fFont%10;
1901 if (!fShow) {
1902 fs1 = Anal1(newSpec,text+3,length-3);
1903 Savefs(&fs1);
1904 } else {
1905 fs1 = Readfs();
1907 }
1908 result = fs1;
1909 }
1910 else if (opMbox>-1) { // dummy operator #mbox{arg}
1912 if (!fShow) {
1913 fs1 = Anal1(newSpec,text+5,length-5);
1914 Savefs(&fs1);
1915 } else {
1916 fs1 = Readfs();
1918 }
1919 result = fs1;
1920 }
1921 else if (opIt>-1) { // operator #it{arg}
1923 Int_t lut[] = {13, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 15, 1, 14, 12};
1924 Int_t fontId = (newSpec.fFont/10);
1925 if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1];
1926 newSpec.fFont = fontId*10 + newSpec.fFont%10;
1927 fItalic = !fItalic;
1928 if (!fShow) {
1929 fs1 = Anal1(newSpec,text+3,length-3);
1930 Savefs(&fs1);
1931 } else {
1932 fs1 = Readfs();
1934 }
1935 fItalic = !fItalic;
1936 result = fs1;
1937 }
1938 else { // no operators found, it is a character string
1939 SetTextSize(spec.fSize);
1940 SetTextAngle(spec.fAngle);
1941 SetTextColor(spec.fColor);
1942 SetTextFont(spec.fFont);
1943 SetTextAlign(11);
1945 UInt_t w=0,h=0;
1946
1947 Int_t leng = strlen(text) ;
1948
1949 quote1 = quote2 = kFALSE ;
1950 Char_t *p ;
1951 for (i=0 ; i<leng ; i++) {
1952 switch (text[i]) {
1953 case '\'' : quote1 = !quote1 ; break ; // single quote symbol not correctly interpreted when PostScript
1954 case '"' : quote2 = !quote2 ; break ;
1955 }
1956 //if (quote1 || quote2) continue ;
1957 if (text[i] == '@') { // @ symbol not correctly interpreted when PostScript
1958 p = &text[i] ;
1959 if ( *(p+1) == '{' || *(p+1) == '}' || *(p+1) == '[' || *(p+1) == ']') {
1960 while (*p != 0) {
1961 *p = *(p+1) ; p++ ;
1962 }
1963 leng-- ;
1964 }
1965 }
1966 }
1967 text[leng] = 0 ;
1968
1969 if (fShow) {
1970 // paint the Latex sub-expression per sub-expression
1971 Double_t xx, yy;
1972 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1973 if (fName.Length() > 0) gPad->PaintTextUrl(xx, yy, text, fName.Data());
1974 else gPad->PaintText(xx, yy, text);
1975 } else {
1977 Double_t width = w;
1978 UInt_t a,d;
1980 fs1.Set(width,a,d);
1981 }
1982
1983 result = fs1;
1984 }
1985
1986 delete[] text;
1987
1988 return result;
1989}
1990
1991////////////////////////////////////////////////////////////////////////////////
1992/// Make a copy of this object with the new parameters
1993/// And copy object attributes
1994
1996{
1997 TLatex *newtext = new TLatex(x, y, text);
2000 newtext->SetBit(kCanDelete);
2001 if (TestBit(kTextNDC)) newtext->SetNDC();
2002 newtext->AppendPad();
2003 return newtext;
2004}
2005
2006////////////////////////////////////////////////////////////////////////////////
2007/// Draw this TLatex with new coordinates in NDC.
2008
2010{
2012 newtext->SetNDC();
2013 return newtext;
2014}
2015
2016
2017////////////////////////////////////////////////////////////////////////////////
2018/// Draw a poly line in a Latex formula
2019/// Is scale_width parameter >=1, fill area will be drawn
2020/// Otherwise line width will be scaled proportional to current font size
2021/// If not specified - default line width will be used
2023{
2024 if (!gPad)
2025 return;
2026
2027 Rotate(gPad, spec.fAngle, npoints, xx, yy);
2028
2029 if (scale_width >= 1.) {
2030 TAttFill fill(spec.fColor, 1001);
2031 fill.Modify();
2032 gPad->PaintFillArea(npoints, xx, yy, "f");
2033 return;
2034 }
2035
2036 auto prevWidth = GetLineWidth();
2037 if (scale_width) {
2038 Int_t lineWidth = TMath::Nint(GetHeight() * spec.fSize * scale_width);
2039 SetLineWidth(lineWidth > prevWidth ? lineWidth : prevWidth);
2040 }
2041
2042 SetLineColor(spec.fColor);
2044
2045 gPad->PaintPolyLine(npoints, xx, yy);
2046 if (scale_width)
2048}
2049
2050
2051////////////////////////////////////////////////////////////////////////////////
2052/// Draw a line in a Latex formula
2053
2055{
2056 if (!gPad) return;
2057 Double_t xx[2] = { x1, x2 };
2058 Double_t yy[2] = { y1, y2 };
2059 Rotate(gPad, spec.fAngle, 2, xx, yy);
2060 SetLineColor(spec.fColor);
2062 gPad->PaintLine(xx[0], yy[0], xx[1], yy[1]);
2063}
2064
2065////////////////////////////////////////////////////////////////////////////////
2066/// Draw an arc of ellipse in a Latex formula (right or left parenthesis)
2067
2069{
2070 if (!gPad)
2071 return;
2072 if (r < 1)
2073 r = 1;
2074
2075 const Int_t np = 40;
2076 Double_t dphi = 2*kPI/np;
2077 Double_t x[np+3], y[np+3];
2078
2079 SetLineColor(spec.fColor);
2080 TAttLine::Modify(); //Change line attributes only if necessary
2081
2082 for (Int_t i = 0; i <= np; i++) {
2083 Double_t angle = i*dphi;
2084 x[i] = x1 + r*TMath::Cos(angle);
2085 y[i] = y1 + r*TMath::Sin(angle);
2086 }
2087 Rotate(gPad, spec.fAngle, np+1, x, y);
2088
2089 gPad->PaintPolyLine(np+1, x, y);
2090}
2091
2092////////////////////////////////////////////////////////////////////////////////
2093/// Draw an arc of ellipse in a Latex formula (right or left parenthesis)
2094
2097{
2098 if (!gPad)
2099 return;
2100 if (r1 < 1)
2101 r1 = 1;
2102 if (r2 < 1)
2103 r2 = 1;
2104
2105 const Int_t np = 40;
2106 Double_t dphi = (phimax-phimin)*kPI/(180*np);
2107 Double_t x[np+3], y[np+3];
2108
2109 SetLineColor(spec.fColor);
2110 TAttLine::Modify(); //Change line attributes only if necessary
2111
2112 for (Int_t i = 0; i <= np; i++) {
2113 Double_t angle = phimin*kPI/180 + i*dphi;
2114 x[i] = x1 + r1*TMath::Cos(angle);
2115 y[i] = y1 + r2*TMath::Sin(angle);
2116 }
2117
2118 Rotate(gPad, spec.fAngle, np+1, x, y);
2119
2120 gPad->PaintPolyLine(np+1,x,y);
2121}
2122
2123////////////////////////////////////////////////////////////////////////////////
2124/// Paint.
2125
2126void TLatex::Paint(Option_t *)
2127{
2128 if (!gPad) return ;
2129 Double_t xsave = fX;
2130 Double_t ysave = fY;
2131 if (TestBit(kTextNDC)) {
2132 fX = gPad->GetX1() + xsave*(gPad->GetX2() - gPad->GetX1());
2133 fY = gPad->GetY1() + ysave*(gPad->GetY2() - gPad->GetY1());
2135 } else {
2136 PaintLatex(gPad->XtoPad(fX),gPad->YtoPad(fY),GetTextAngle(),GetTextSize(),GetTitle());
2137 }
2138 fX = xsave;
2139 fY = ysave;
2140}
2141
2142////////////////////////////////////////////////////////////////////////////////
2143/// Main drawing function
2144///
2145/// Warning: Unlike most others "XYZ::PaintXYZ" methods, PaintLatex modifies
2146/// the TLatex data members.
2147
2149{
2150 if (size<=0 || strlen(text1) <= 0) return; // do not paint empty text or text with size <= 0
2151
2152 TAttText::Modify(); // Change text attributes only if necessary.
2153
2154 auto ps = gPad->GetPainter()->GetPS();
2155
2156 if (ps && ps->InheritsFrom("TTeXDump")) {
2157 TString t(text1);
2158 if (t.Index("#")>=0 || t.Index("^")>=0 || t.Index("\\")>=0) {
2159 t.ReplaceAll("#LT","\\langle");
2160 t.ReplaceAll("#GT","\\rangle");
2161 t.ReplaceAll("#club","\\clubsuit");
2162 t.ReplaceAll("#spade","\\spadesuit");
2163 t.ReplaceAll("#heart","\\heartsuit");
2164 t.ReplaceAll("#diamond","\\diamondsuit");
2165 t.ReplaceAll("#voidn","\\wp");
2166 t.ReplaceAll("#voidb","f");
2167 t.ReplaceAll("#ocopyright","\\copyright");
2168 t.ReplaceAll("#trademark","TM");
2169 t.ReplaceAll("#void3","TM");
2170 t.ReplaceAll("#oright","R");
2171 t.ReplaceAll("#void1","R");
2172 t.ReplaceAll("#3dots","\\ldots");
2173 t.ReplaceAll("#lbar","\\mid");
2174 t.ReplaceAll("#bar","\\wwbar");
2175 t.ReplaceAll("#void8","\\mid");
2176 t.ReplaceAll("#divide","\\div");
2177 t.ReplaceAll("#Jgothic","\\Im");
2178 t.ReplaceAll("#Rgothic","\\Re");
2179 t.ReplaceAll("#doublequote","\"");
2180 t.ReplaceAll("#plus","+");
2181 t.ReplaceAll("#minus","-");
2182 t.ReplaceAll("#/","/");
2183 t.ReplaceAll("#upoint",".");
2184 t.ReplaceAll("#aa","\\mbox{\\aa}");
2185 t.ReplaceAll("#AA","\\mbox{\\AA}");
2186
2187 t.ReplaceAll("#omicron","o");
2188 t.ReplaceAll("#Alpha","A");
2189 t.ReplaceAll("#Beta","B");
2190 t.ReplaceAll("#Epsilon","E");
2191 t.ReplaceAll("#Zeta","Z");
2192 t.ReplaceAll("#Eta","H");
2193 t.ReplaceAll("#Iota","I");
2194 t.ReplaceAll("#Kappa","K");
2195 t.ReplaceAll("#Mu","M");
2196 t.ReplaceAll("#Nu","N");
2197 t.ReplaceAll("#Omicron","O");
2198 t.ReplaceAll("#Rho","P");
2199 t.ReplaceAll("#Tau","T");
2200 t.ReplaceAll("#Chi","X");
2201 t.ReplaceAll("#varomega","\\varpi");
2202
2203 t.ReplaceAll("#varUpsilon","?");
2204 t.ReplaceAll("#corner","?");
2205 t.ReplaceAll("#ltbar","?");
2206 t.ReplaceAll("#bottombar","?");
2207 t.ReplaceAll("#notsubset","?");
2208 t.ReplaceAll("#arcbottom","?");
2209 t.ReplaceAll("#cbar","?");
2210 t.ReplaceAll("#arctop","?");
2211 t.ReplaceAll("#topbar","?");
2212 t.ReplaceAll("#arcbar","?");
2213 t.ReplaceAll("#downleftarrow","?");
2214 t.ReplaceAll("#splitline","\\genfrac{}{}{0pt}{}");
2215
2216 t.ReplaceAll("#","\\");
2217 t.ReplaceAll("%","\\%");
2218 }
2219 ps->SetTextAngle(angle);
2220 ps->Text(x, y, t.Data());
2221 } else {
2223 }
2224}
2225
2226////////////////////////////////////////////////////////////////////////////////
2227/// Drawing function
2228
2230{
2231 if (!gPad)
2232 return 0;
2234 if(newText.Length() == 0)
2235 return 0;
2236 newText.ReplaceAll("#hbox","#mbox");
2237
2238 fError = nullptr;
2240 Error("PaintLatex1", "%s\n==> %s", fError, text1);
2241 return 0;
2242 }
2243 fError = nullptr;
2244
2245 // Do not use Latex if font is low precision.
2246 if (fTextFont % 10 < 2) {
2247 gPad->GetPainter()->SetTextAngle(angle);
2248 gPad->PaintText(x, y, text1);
2249 return 1;
2250 }
2251
2252 // Paint the text using TMathText if contains a "\"
2253 if (strstr(text1,"\\")) {
2254 auto ps = gPad->GetPainter()->GetPS();
2255 // If PDF or SVG, paint using TLatex
2256 if (ps && (ps->InheritsFrom("TPDF") || ps->InheritsFrom("TSVG"))) {
2257 newText.ReplaceAll("\\","#");
2258 } else {
2259 TMathText tm;
2260 tm.SetTextAlign(GetTextAlign());
2261 tm.SetTextFont(GetTextFont());
2262 tm.SetTextColor(GetTextColor());
2263 tm.PaintMathText(x, y, angle, size, text1);
2264 return 1;
2265 }
2266 }
2267
2270 if (fTextFont % 10 > 2) {
2272 SetTextFont(10*(saveFont/10) + 2);
2273 }
2274
2275 Int_t length = newText.Length();
2276 const Char_t *text = newText.Data();
2277
2278 Double_t xsave = fX;
2279 Double_t ysave = fY;
2280 fX = x;
2281 fY = y;
2282 gPad->XYtoAbsPixel(fX, fY, x, y);
2283 fShow = kFALSE;
2285
2286 fOriginSize = size;
2287
2288 // Get current line attributes.
2291
2293 spec.fAngle = angle;
2294 spec.fSize = size;
2295 spec.fColor = GetTextColor();
2296 spec.fFont = GetTextFont();
2300 if (fError) {
2301 Error("PaintLatex1", "%s\n==> %s", fError, text);
2302 } else {
2303 fShow = kTRUE;
2304 newSpec.fSize = size;
2305
2306 switch (valign) {
2307 case 0: y -= fs.Under(); break;
2308 case 1: break;
2309 case 2: y += fs.Height()*0.5-fs.Under() + 1.; break;
2310 case 3: y += fs.Over(); break;
2311 }
2312 switch (halign) {
2313 case 2: x -= fs.Width()/2; break;
2314 case 3: x -= fs.Width(); break;
2315 }
2317 }
2318
2322 SetTextColor(spec.fColor);
2326 fTabSize.clear();
2327 fX = xsave;
2328 fY = ysave;
2329 return fError ? 0 : 1;
2330}
2331
2332////////////////////////////////////////////////////////////////////////////////
2333/// Check if the Latex syntax is correct
2334
2336{
2337 const Char_t *kWord1[] = {"{}^{","{}_{","^{","_{","#scale{","#color{","#url{","#font{","#sqrt{","#[]{","#{}{","#||{",
2338 "#bar{","#vec{","#dot{","#hat{","#ddot{","#acute{","#grave{","#check{","#tilde{","#slash{","#bf{","#it{","#mbox{",
2339 "\\scale{","\\color{","\\font{","\\sqrt{","\\[]{","\\{}{","\\||{","#(){","\\(){",
2340 "\\bar{","\\vec{","\\dot{","\\hat{","\\ddot{","\\acute{","\\grave{","\\check{","\\bf{","\\it{","\\mbox{"}; // check for }
2341 const Char_t *kWord2[] = {"#scale[","#color[","#url[","#font[","#sqrt[","#kern[","#lower[","\\scale[","\\color[","\\font[","\\sqrt[","\\kern[","\\lower["}; // check for ]{ + }
2342 const Char_t *kWord3[] = {"#frac{","\\frac{","#splitline{","\\splitline{"}; // check for }{ then }
2343 const Char_t *kLeft1[] = {"#left[","\\left[","#left{","\\left{","#left|","\\left|","#left(","\\left("};
2344 const Char_t *kLeft2[] = {"#[]{","#[]{","#{}{","#{}{","#||{","#||{","#(){","#(){"};
2345 const Char_t *kRight[] = {"#right]","\\right]","#right}","\\right}","#right|","\\right|","#right)","\\right)"};
2346 const Int_t lkWord1[] = {4,4,2,2,7,7,5,6,6,4,4,4,5,5,5,5,6,7,7,7,7,7,4,4,6,7,7,6,6,4,4,4,4,4,5,5,5,5,6,7,7,7,4,4,6};
2347 const Int_t lkWord2[] = {7,7,5,6,6,6,7,7,7,6,6,6,7} ;
2348 const Int_t lkWord3[] = {6,6,11,11} ;
2349 Int_t nkWord1 = 45, nkWord2 = 13, nkWord3 = 4;
2350 Int_t i,k ;
2352 Int_t lLeft1 = 6 ;
2353 Int_t lLeft2 = 4 ;
2354 Int_t lRight = 7 ;
2355 nLeft1 = nRight = 8 ;
2356 nOfLeft = nOfRight = 0 ;
2357
2358 Char_t buf[11] ; for (i=0;i<11;i++) buf[i]=0;
2359 Bool_t opFound ;
2360 Int_t opFrac = 0;
2361 Int_t length = text.Length() ;
2362
2365 Int_t error = 0 ;
2367
2368 // first find and replace all occurrences of "kLeft1" keyword by "kLeft2" keyword,
2369 // and all occurrences of "kRight" keyword by "}".
2370 i = 0 ;
2371 while (i < length) {
2372 // The string in 'buf' does not need to be null terminated,
2373 // we will only check with strncmp.
2374 strncpy(buf,&text[i],TMath::Min(7,length-i));
2375 opFound = kFALSE ;
2376 for (k = 0 ; k < nLeft1 ; k++) {
2377 if (strncmp(buf,kLeft1[k],lLeft1)==0) {
2378 nOfLeft++ ;
2379 i+=lLeft1 ;
2380 opFound = kTRUE ;
2381 break ;
2382 }
2383 }
2384 if (opFound) continue ;
2385
2386 for(k=0;k<nRight;k++) {
2387 if (strncmp(buf,kRight[k],lRight)==0) {
2388 nOfRight++ ;
2389 i+=lRight ;
2390 opFound = kTRUE ;
2391 break ;
2392 }
2393 }
2394 if (!opFound) i++ ;
2395 }
2396 if (nOfLeft != nOfRight) {
2397 printf(" nOfLeft = %d, nOfRight = %d\n",nOfLeft,nOfRight) ;
2398 error = 1 ;
2399 fError = "Operators \"#left\" and \"#right\" don't match !" ;
2400 goto ERROR_END ;
2401 }
2402
2403 for (k = 0 ; k < nLeft1 ; k++) {
2404 text.ReplaceAll(kLeft1[k],lLeft1,kLeft2[k],lLeft2) ;
2405 }
2406 for (k = 0 ; k < nRight ; k++) {
2407 text.ReplaceAll(kRight[k],lRight,"}",1) ;
2408 }
2409 length = text.Length() ;
2410
2412 while (i< length){
2413 switch (text[i]) {
2414 case '"' : quote1 = !quote1 ; break ;
2415 case '\'': quote2 = !quote2 ; break ;
2416 }
2417 // The string in 'buf' does not need to be null terminated,
2418 // we will only check with strncmp
2419 strncpy(buf,&text[i],TMath::Min(11,length-i));
2420 opFound = kFALSE ;
2421
2422 for(k=0;k<nkWord1;k++) {
2423 if (strncmp(buf,kWord1[k],lkWord1[k])==0) {
2424 nOfKW1++ ;
2425 i+=lkWord1[k] ;
2426 opFound = kTRUE ;
2427 nOfCurlyBracket++ ;
2428 break ;
2429 }
2430 }
2431 if (opFound) continue ;
2432
2433 for(k=0;k<nkWord2;k++) {
2434 if (strncmp(buf,kWord2[k],lkWord2[k])==0) {
2435 nOfKW2++ ;
2436 i+=lkWord2[k] ;
2437 opFound = kTRUE ;
2439 break ;
2440 }
2441 }
2442 if (opFound) continue ;
2443
2444 for(k=0;k<nkWord3;k++) {
2445 if (strncmp(buf,kWord3[k],lkWord3[k])==0) {
2446 nOfKW3++ ;
2447 i+=lkWord3[k] ;
2448 opFound = kTRUE ;
2449 opFrac++ ;
2450 nOfCurlyBracket++ ;
2451 break ;
2452 }
2453 }
2454 if (opFound) continue ;
2455 if (strncmp(buf,"}{",2) == 0 && opFrac) {
2456 opFrac-- ;
2457 nOfCurlyCurly++ ;
2458 i+= 2;
2459 }
2460 else if (strncmp(buf,"]{",2) == 0 && nOfSquareBracket) {
2461 nOfSquareCurly++ ;
2462 i+= 2 ;
2463 nOfCurlyBracket++ ;
2465 }
2466 else if (strncmp(buf,"@{",2) == 0 || strncmp(buf,"@}",2) == 0) {
2467 i+= 2 ;
2468 }
2469 else if (strncmp(buf,"@[",2) == 0 || strncmp(buf,"@]",2) == 0) {
2470 i+= 2 ;
2471 }
2472 else if (text[i] == ']' ) { // not belonging to a key word, add @ in front
2473 text.Insert(i,"@") ;
2474 length++ ;
2475 i+=2 ;
2476 }
2477 else if (text[i] == '[' ) { // not belonging to a key word, add @ in front
2478 text.Insert(i,"@") ;
2479 length++ ;
2480 i+=2 ;
2481 }
2482 else if (text[i] == '{' ) { // not belonging to a key word, add @ in front
2483 text.Insert(i,"@") ;
2484 length++ ;
2485 i+=2 ;
2486 }
2487 else if (text[i] == '}' ) {
2488 if ( nOfCurlyBracket) {
2489 nOfCurlyBracket-- ;
2490 i++ ;
2491 } else { // extra }, add @ in front
2492 text.Insert(i,"@") ;
2493 length++ ;
2494 i+=2 ;
2495 }
2496 } else {
2497 i++ ;
2498 buf[1] = 0 ;
2499 }
2500 }
2501
2502 if (nOfKW2 != nOfSquareCurly) {
2503 error = 1 ;
2504 fError = "Invalid number of \"]{\"" ;
2505 }
2506 else if (nOfKW3 != nOfCurlyCurly) {
2507 error = 1 ;
2508 fError = "Error in syntax of \"#frac\"" ;
2509 }
2510 else if (nOfCurlyBracket < 0) {
2511 error = 1 ;
2512 fError = "Missing \"{\"" ;
2513 }
2514 else if (nOfCurlyBracket > 0) {
2515 error = 1 ;
2516 fError = "Missing \"}\"" ;
2517 }
2518 else if (nOfSquareBracket < 0) {
2519 error = 1 ;
2520 fError = "Missing \"[\"" ;
2521 }
2522 else if (nOfSquareBracket > 0) {
2523 error = 1 ;
2524 fError = "Missing \"]\"" ;
2525 }
2526
2527 ERROR_END:
2528 return error ;
2529}
2530
2531////////////////////////////////////////////////////////////////////////////////
2532/// First parsing of the analyse sequence
2533
2535{
2536 fTabSize.reserve(100); // ensure 100 entries before memory reallocation required
2537 fShow = kFALSE;
2538 fOriginSize = size;
2539
2540 //get current line attributes
2543
2545 spec.fAngle = angle;
2546 spec.fSize = GetTextSizePercent(size);
2547 spec.fColor = GetTextColor();
2548 spec.fFont = GetTextFont();
2551
2553
2556 SetTextFont(spec.fFont);
2557 SetTextColor(spec.fColor);
2561 return fs;
2562}
2563
2564////////////////////////////////////////////////////////////////////////////////
2565/// Return height of current pad in pixels
2566
2568{
2569 if (!gPad) return 0.;
2570 Double_t w = gPad->GetAbsWNDC()*Double_t(gPad->GetWw());
2571 Double_t h = gPad->GetAbsHNDC()*Double_t(gPad->GetWh());
2572 if (w < h)
2573 return w;
2574 else
2575 return h;
2576}
2577
2578////////////////////////////////////////////////////////////////////////////////
2579/// Return size of the formula along X in pad coordinates when the text precision
2580/// is smaller than 3.
2581
2583{
2584 if (!gPad) return 0.;
2586 if( newText.Length() == 0) return 0;
2587
2588 // The text is a TMathText.
2589 if ( newText.Contains("\\") ) {
2590 TMathText tm(0., 0., newText.Data());
2591 return tm.GetXsize();
2592 }
2593
2594 fError = nullptr;
2596 Error("GetXsize", "%s\n==> %s", fError, GetTitle());
2597 return 0;
2598 }
2599 fError = nullptr;
2600
2601 const Char_t *text = newText.Data() ;
2605 fTabSize.clear();
2606 return std::abs(gPad->AbsPixeltoX(fs.Width()) - gPad->AbsPixeltoX(0));
2607}
2608
2609////////////////////////////////////////////////////////////////////////////////
2610/// Return text size in pixels
2611
2613{
2614 if (!gPad) return;
2616 if( newText.Length() == 0) return;
2617
2618 // The text is a TMathText.
2619 if ( newText.Contains("\\") ) {
2620 TMathText tm(0., 0., newText.Data());
2621 tm.GetBoundingBox(w, h);
2622 return;
2623 }
2624
2625 fError = nullptr;
2627 Error("GetBoundingBox", "%s\n==> %s", fError, GetTitle());
2628 return;
2629 }
2630 fError = nullptr;
2631
2632 if (angle) {
2633 Int_t cBoxX[4], cBoxY[4];
2634 Int_t ptx, pty;
2635 if (TestBit(kTextNDC)) {
2636 ptx = gPad->UtoPixel(fX);
2637 pty = gPad->VtoPixel(fY);
2638 } else {
2639 ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX));
2640 pty = gPad->YtoAbsPixel(gPad->YtoPad(fY));
2641 }
2643 Int_t x1 = cBoxX[0];
2644 Int_t x2 = cBoxX[0];
2645 Int_t y1 = cBoxY[0];
2646 Int_t y2 = cBoxY[0];
2647 for (Int_t i=1; i<4; i++) {
2648 if (cBoxX[i] < x1) x1 = cBoxX[i];
2649 if (cBoxX[i] > x2) x2 = cBoxX[i];
2650 if (cBoxY[i] < y1) y1 = cBoxY[i];
2651 if (cBoxY[i] > y2) y2 = cBoxY[i];
2652 }
2653 w = x2-x1;
2654 h = y2-y1;
2655 } else {
2656 const Char_t *text = newText.Data() ;
2658 fTabSize.clear();
2659 w = (UInt_t)fs.Width();
2660 h = (UInt_t)fs.Height();
2661 }
2662}
2663
2664////////////////////////////////////////////////////////////////////////////////
2665/// Return size of the formula along Y in pad coordinates when the text precision
2666/// is smaller than 3.
2667
2669{
2670 if (!gPad) return 0.;
2672 if( newText.Length() == 0) return 0;
2673
2674 // The text is a TMathText.
2675 if ( newText.Contains("\\") ) {
2676 TMathText tm(0., 0., newText.Data());
2677 return tm.GetYsize();
2678 }
2679
2680 fError = nullptr;
2682 Error("GetYsize", "%s\n==> %s", fError, GetTitle());
2683 return 0;
2684 }
2685 fError = nullptr;
2686
2687 const Char_t *text = newText.Data();
2691 fTabSize.clear();
2692 return std::abs(gPad->AbsPixeltoY(fs.Height()) - gPad->AbsPixeltoY(0));
2693}
2694
2695////////////////////////////////////////////////////////////////////////////////
2696/// Read fs in fTabSize
2697
2699{
2700 if (fTabSize.empty()) {
2701 Error("Readfs", "No data in fTabSize stack");
2702 return TLatexFormSize(0,0,0);
2703 }
2704
2706 fTabSize.pop_back();
2707 return result;
2708}
2709
2710////////////////////////////////////////////////////////////////////////////////
2711/// Save fs values in array fTabSize
2712
2714{
2715 fTabSize.emplace_back(*fs);
2716}
2717
2718////////////////////////////////////////////////////////////////////////////////
2719/// Save primitive as a C++ statement(s) on output stream out
2720
2721void TLatex::SavePrimitive(std::ostream &out, Option_t *option)
2722{
2724 out, Class(), "tex",
2725 TString::Format("%g, %g, \"%s\"", fX, fY, TString(GetTitle()).ReplaceSpecialCppChars().Data()), kFALSE);
2726
2727 SaveTextAttributes(out, "tex", 11, 0, 1, 62, 0.05);
2728 SaveLineAttributes(out, "tex", 1, 1, 1);
2729
2730 if (TestBit(kTextNDC))
2731 out << " tex->SetNDC();\n";
2732
2733 SavePrimitiveDraw(out, "tex", option);
2734}
2735
2736////////////////////////////////////////////////////////////////////////////////
2737/// Set relative size of subscripts and superscripts
2738
2740{
2742}
2743
2744////////////////////////////////////////////////////////////////////////////////
2745/// Set limit for text resizing of subscripts and superscripts
2746
2748{
2750}
#define d(i)
Definition RSha256.hxx:102
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
char Char_t
Character 1 byte (char)
Definition RtypesCore.h:51
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
constexpr Double_t kPI
Definition TEllipse.cxx:24
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:326
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:46
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:47
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:48
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:389
virtual Float_t GetTextSizePercent(Float_t size)
Return the text in percent of the pad size.
Definition TAttText.cxx:309
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:293
TLatex helper class used to compute the size of a portion of a formula.
Definition TLatex.h:35
To draw Mathematical Formula.
Definition TLatex.h:20
virtual void SetLimitIndiceSize(Int_t limitFactorSize)
Set limit for text resizing of subscripts and superscripts.
Definition TLatex.cxx:2745
Double_t GetXsize()
Return size of the formula along X in pad coordinates when the text precision is smaller than 3.
Definition TLatex.cxx:2580
void Rotate(TVirtualPad *pad, Double_t angle, Int_t np, Double_t *x, Double_t *y)
Rotate array of points around fX, fY coordinate by specified angle.
Definition TLatex.cxx:506
Double_t GetHeight() const
Return height of current pad in pixels.
Definition TLatex.cxx:2565
void Copy(TObject &text) const override
Copy this TLatex object to another TLatex.
Definition TLatex.cxx: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:2052
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:2093
static TClass * Class()
virtual void SetIndiceSize(Double_t factorSize)
Set relative size of subscripts and superscripts.
Definition TLatex.cxx:2737
std::vector< TLatexFormSize > fTabSize
! array of values for the different zones
Definition TLatex.h:69
Int_t PaintLatex1(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Drawing function.
Definition TLatex.cxx:2227
Double_t fOriginSize
Font size of the starting font.
Definition TLatex.h:70
Double_t GetYsize()
Return size of the formula along Y in pad coordinates when the text precision is smaller than 3.
Definition TLatex.cxx:2666
TLatexFormSize FirstParse(Double_t angle, Double_t size, const Char_t *text)
First parsing of the analyse sequence.
Definition TLatex.cxx:2532
TLatexFormSize Readfs()
Read fs in fTabSize.
Definition TLatex.cxx:2696
void GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle=kFALSE) override
Return text size in pixels.
Definition TLatex.cxx:2610
@ 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:2007
void DrawCircle(Double_t x1, Double_t y1, Double_t r, const TextSpec_t &spec)
Draw an arc of ellipse in a Latex formula (right or left parenthesis)
Definition TLatex.cxx:2066
virtual void PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Main drawing function.
Definition TLatex.cxx:2146
TLatex()
Default constructor.
Definition TLatex.cxx: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:2719
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:2020
TLatex * DrawLatex(Double_t x, Double_t y, const char *text)
Make a copy of this object with the new parameters And copy object attributes.
Definition TLatex.cxx:1993
Double_t fFactorSize
! Relative size of subscripts and superscripts
Definition TLatex.h:64
const Char_t * fError
! error code
Definition TLatex.h:67
Bool_t fItalic
! Currently inside italic operator
Definition TLatex.h:71
void Paint(Option_t *option="") override
Paint.
Definition TLatex.cxx:2124
TLatexFormSize Analyse(Double_t x, Double_t y, const TextSpec_t &spec, const Char_t *t, Int_t length)
Analyse and paint the TLatex formula.
Definition TLatex.cxx:568
Int_t CheckLatexSyntax(TString &text)
Check if the Latex syntax is correct.
Definition TLatex.cxx:2333
void Savefs(TLatexFormSize *fs)
Save fs values in array fTabSize.
Definition TLatex.cxx:2711
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:1095
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:842
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:774
@ 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:425
const char * Data() const
Definition TString.h:384
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:713
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
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:106
TText & operator=(const TText &src)
Assignment operator.
Definition TText.cxx:97
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:590
virtual void GetTextAscentDescent(UInt_t &a, UInt_t &d, const char *text) const
Return text ascent and descent for string text.
Definition TText.cxx:524
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:423
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