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 "TVirtualPS.h"
19#include "TVirtualX.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 and standard SVG output support the syntax '#url[link]{label}'.
401This can be combined with other LaTeX 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}
411End_Macro
412*/
413
414////////////////////////////////////////////////////////////////////////////////
415/// Default constructor.
416
418{
419 fFactorSize = 1.5;
420 fFactorPos = 0.6;
421 fError = nullptr;
422 fShow = kFALSE;
423 fOriginSize = 0.04;
424 fItalic = kFALSE;
426 SetLineWidth(2);
427}
428
429////////////////////////////////////////////////////////////////////////////////
430/// Normal constructor.
431
432TLatex::TLatex(Double_t x, Double_t y, const char *text)
433 :TText(x,y,text)
434{
435 fFactorSize = 1.5;
436 fFactorPos = 0.6;
437 fError = nullptr;
438 fShow = kFALSE;
439 fOriginSize = 0.04;
440 fItalic = kFALSE;
442 SetLineWidth(2);
443}
444
445////////////////////////////////////////////////////////////////////////////////
446/// Destructor.
447
449{
450}
451
452////////////////////////////////////////////////////////////////////////////////
453/// Copy constructor.
454
456{
457 fFactorSize = 1.5;
458 fFactorPos = 0.6;
459 fError = nullptr;
460 fShow = kFALSE;
461 fOriginSize = 0.04;
462 fItalic = kFALSE;
464 latex.TLatex::Copy(*this);
465}
466
467////////////////////////////////////////////////////////////////////////////////
468///assignment operator
469
471{
472 if (this != &lt) {
474 TAttLine::operator=(lt);
475 fFactorSize = lt.fFactorSize;
476 fFactorPos = lt.fFactorPos;
477 fLimitFactorSize = lt.fLimitFactorSize;
478 fError = lt.fError;
479 fShow = lt.fShow;
480 fTabSize = lt.fTabSize;
481 fOriginSize = lt.fOriginSize;
482 fItalic = lt.fItalic;
483 }
484 return *this;
485}
486
487////////////////////////////////////////////////////////////////////////////////
488/// Copy this TLatex object to another TLatex.
489
490void TLatex::Copy(TObject &obj) const
491{
492 TText::Copy(obj);
493 TAttLine::Copy((TLatex &)obj);
494 ((TLatex&)obj).fFactorSize = fFactorSize;
495 ((TLatex&)obj).fFactorPos = fFactorPos;
496 ((TLatex&)obj).fLimitFactorSize = fLimitFactorSize;
497 ((TLatex&)obj).fError = fError;
498 ((TLatex&)obj).fShow = fShow;
499 ((TLatex&)obj).fTabSize = fTabSize;
500 ((TLatex&)obj).fOriginSize = fOriginSize;
501 ((TLatex&)obj).fItalic = fItalic;
502}
503
504////////////////////////////////////////////////////////////////////////////////
505/// Rotate array of points around fX, fY coordinate by specified angle
506
508{
510 pad->XYtoAbsPixel(fX, fY, xOrigin, yOrigin);
511
514 Double_t xx, yy;
515 for (Int_t n = 0; n < np; ++n) {
516 pad->AbsPixeltoXY( cos_angle * (x[n]-xOrigin) + sin_angle * (y[n]-yOrigin) + xOrigin,
517 -sin_angle * (x[n]-xOrigin) + cos_angle * (y[n]-yOrigin) + yOrigin,
518 xx, yy);
519 x[n] = xx;
520 y[n] = yy;
521 }
522}
523
524////////////////////////////////////////////////////////////////////////////////
525/// Rotate single point around fX, fY coordinate by specified angle
526
528{
529 xx = x;
530 yy = y;
531 Rotate(pad, angle, 1, &xx, &yy);
532}
533
534////////////////////////////////////////////////////////////////////////////////
535/// Analyse function.
536
538{
539 return Analyse(0, 0, spec, t, length);
540}
541
542////////////////////////////////////////////////////////////////////////////////
543/// Analyse and paint the TLatex formula
544///
545/// It is called twice : first for calculating the size of
546/// each portion of the formula, then to paint the formula.
547/// When analyse finds an operator or separator, it calls
548/// itself recursively to analyse the arguments of the operator.
549/// when the argument is an atom (normal text), it calculates
550/// the size of it and return it as the result.
551/// for example : if the operator #%frac{arg1}{arg2} is found :
552/// Analyse(arg1) return the size of arg1 (width, up, down)
553/// Analyse(arg2) return the size of arg2
554/// now, we know the size of #%frac{arg1}{arg2}:
555///
556/// ~~~ {.cpp}
557/// width = max(width_arg1, width_arg2)
558/// up = up_arg1 + down_arg1
559/// down = up_arg2 + down_arg2
560/// ~~~
561///
562/// so, when the user wants to paint a fraction at position (x,y),
563/// the rect used for the formula is : (x,y-up,x+width,y+down)
564///
565/// return size of zone occupied by the text/formula
566/// - `t` : chain to be analyzed
567/// - `length` : number of chars in t.
568
570{
571 const char *tab[] = { "alpha","beta","chi","delta","varepsilon","phi","gamma","eta","iota","varphi","kappa","lambda",
572 "mu","nu","omicron","pi","theta","rho","sigma","tau","upsilon","varomega","omega","xi","psi","zeta",
573 "Alpha","Beta","Chi","Delta","Epsilon","Phi","Gamma","Eta","Iota","vartheta",
574 "Kappa","Lambda","Mu","Nu","Omicron","Pi","Theta","Rho","Sigma","Tau",
575 "Upsilon","varsigma","Omega","Xi","Psi","Zeta","varUpsilon","epsilon"};
576
577 const char *tab2[] = { "leq","/","infty","voidb","club","diamond","heart",
578 "spade","leftrightarrow","leftarrow","uparrow","rightarrow",
579 "downarrow","circ","pm","doublequote","geq","times","propto",
580 "partial","bullet","divide","neq","equiv","approx","3dots",
581 "cbar","topbar","downleftarrow","aleph","Jgothic","Rgothic","voidn",
582 "otimes","oplus","oslash","cap","cup","supset","supseteq",
583 "notsubset","subset","subseteq","in","notin","angle","nabla",
584 "oright","ocopyright","trademark","prod","surd","upoint","corner","wedge",
585 "vee","Leftrightarrow","Leftarrow","Uparrow","Rightarrow",
586 "Downarrow","diamond","LT","void1","copyright","void3","sum",
587 "arctop","lbar","arcbottom","topbar","void8", "bottombar","arcbar",
588 "ltbar","AA","aa","void06","GT","int","forall","exists" };
589
590 const char *tab3[] = { "bar","vec","dot","hat","ddot","acute","grave","check","tilde","slash"};
591
592 if (fError) return TLatexFormSize(0,0,0);
593
595 Int_t i, k;
596 Int_t min = 0, max = 0;
597 Bool_t cont = kTRUE;
598 while(cont) {
599 // count leading blanks
600 //while(nBlancDeb+nBlancFin<length && t[nBlancDeb]==' ') nBlancDeb++;
601
602 if (nBlancDeb==length) return TLatexFormSize(0,0,0); // empty string
603
604 // count trailing blanks
605 //while(nBlancDeb+nBlancFin<length && t[length-nBlancFin-1]==' ') nBlancFin++;
606
608
609 // remove characters { }
610 if (t[nBlancDeb]=='{' && t[length-nBlancFin-1]=='}') {
611 Int_t nBrackets = 0;
613 for(i=nBlancDeb;i<length-nBlancFin;i++) {
614 if (t[i] == '{' && !(i>0 && t[i-1] == '@')) nBrackets++;
615 if (t[i] == '}' && t[i-1]!= '@') nBrackets--;
616 if (nBrackets==0 && i<length-nBlancFin-2) {
618 break;
619 }
620 }
621
622 if (sameBrackets) {
623 // begin and end brackets match
624 nBlancDeb++;
625 nBlancFin++;
626 if (nBlancDeb+nBlancFin==length) return TLatexFormSize(0,0,0); // empty string
627 cont = kTRUE;
628 }
629
630 }
631
634 }
635
636 // make a copy of the current processed chain of characters
637 // removing leading and trailing blanks
638 length -= nBlancFin+nBlancDeb; // length of string without blanks
639 if (length <=0) {
640 Error("Analyse", "It seems there is a syntax error in the TLatex string");
641 return TLatexFormSize(0,0,0);
642 }
643 Char_t* text = new Char_t[length+1];
645 text[length] = 0;
646
647 // compute size of subscripts and superscripts
650 indiceSize = spec.fSize;
651 // subtract 0.001 because of rounding errors
653 specNewSize.fSize = indiceSize;
654
655 // recherche des operateurs
656 Int_t opPower = -1; // Position of first ^ (power)
657 Int_t opUnder = -1; // Position of first _ (indice)
658 Int_t opFrac = -1; // Position of first \frac
659 Int_t opSqrt = -1; // Position of first \sqrt
660 Int_t nBrackets = 0; // Nesting level in { }
661 Int_t nCroch = 0; // Nesting level in [ ]
662 Int_t opCurlyCurly = -1; // Position of first }{
663 Int_t opSquareCurly = -1; // Position of first ]{
664 Int_t opCloseCurly = -2; // Position of first }
665 Int_t opColor = -1; // Position of first #color
666 Int_t opUrl = -1; // Position of first #url
667 Int_t opFont = -1; // Position of first #font
668 Int_t opScale = -1; // Position of first #scale
669 Int_t opGreek = -1; // Position of a Greek letter
670 Int_t opSpec = -1; // position of a special character
671 Int_t opAbove = -1; // position of a vector/overline
672 Int_t opSquareBracket = 0 ; // position of a "[]{" operator (#[]{arg})
673 Int_t opBigCurly = 0 ; // position of a "{}{" operator (big curly bracket #{}{arg})
674 Int_t opAbs = 0 ; // position of a "||{" operator (absolute value) (#||{arg})
675 Int_t opParen = 0 ; // position of a "(){" operator (big parenthesis #(){arg})
676 Int_t abovePlace = 0 ; // true if subscripts must be written above and not after
677 Int_t opBox = 0 ; // position of #Box
678 Int_t opPerp = 0; // position of #perp
679 Int_t opOdot = 0; // position of #odot
680 Int_t opHbar = 0; // position of #hbar
681 Int_t opMinus = 0; // position of #minus
682 Int_t opPlus = 0; // position of #plus
683 Int_t opMp = 0; // position of #mp
684 Int_t opBackslash = 0; // position of #backslash
685 Int_t opParallel = 0; // position of #parallel
686 Int_t opSplitLine = -1; // Position of first #splitline
687 Int_t opKern = -1; // Position of first #kern
688 Int_t opLower = -1; // Position of first #lower
689 Int_t opBf = -1; // Position of first #bf
690 Int_t opIt = -1; // Position of first #it
691 Int_t opMbox = -1; // Position of first #mbox
692
695
696 for(i=0;i<length;i++) {
697 switch (text[i]) {
698 case '\'' : quote1 = !quote1 ; break ;
699 case '"' : quote2 = !quote2 ; break ;
700 }
701 //if (quote1 || quote2) continue ;
702 switch (text[i]) {
703 case '{':
704 if (nCroch==0) {
705 if (!(i>0 && text[i-1] == '@')) nBrackets++;
706 }
707 break;
708 case '}':
709 if (nCroch==0) {
710 if (!(i>0 && text[i-1] == '@')) nBrackets--;
711 if (nBrackets==0) {
712 if (i<length-1) if (text[i+1]=='{' && opCurlyCurly==-1) opCurlyCurly=i;
713 if (i<length-2) {
714 if (text[i+1]!='{' && !(text[i+2]=='{' && (text[i+1]=='^' || text[i+1]=='_'))
715 && opCloseCurly==-2) opCloseCurly=i;
716 }
717 else if (i<length-1) {
718 if (text[i+1]!='{' && opCloseCurly==-2) opCloseCurly=i;
719 }
720 else if (opCloseCurly==-2) opCloseCurly=i;
721 }
722 }
723 break;
724 case '[':
725 if (nBrackets==0) {
726 if (!(i>0 && text[i-1] == '@')) nCroch++;
727 }
728 break;
729 case ']':
730 if (nBrackets==0) {
731 if (!(i>0 && text[i-1] == '@')) nCroch--;
732 if (nCroch<0) {
733 // more "]" than "["
734 fError = "Missing \"[\"";
735 delete [] text;
736 return TLatexFormSize(0,0,0);
737 }
738 }
739 break;
740 }
741 if (length>i+1) {
742 Char_t buf[3];
743 strncpy(buf,&text[i],2);
744 if (strncmp(buf,"^{",2)==0) {
745 if (opPower==-1 && nBrackets==0 && nCroch==0) opPower=i;
746 if (i>3) {
747 Char_t buf1[5];
748 strncpy(buf1,&text[i-4],4);
749 if (strncmp(buf1,"#int",4)==0) {
750 abovePlace = 1;
751 if (i>4 && opCloseCurly==-2) opCloseCurly=i-5;
752 }
753 if (strncmp(buf1,"#sum",4)==0) {
754 abovePlace = 2;
755 if (i>4 && opCloseCurly==-2) opCloseCurly=i-5;
756 }
757 }
758 }
759 if (strncmp(buf,"_{",2)==0) {
760 if (opUnder==-1 && nBrackets==0 && nCroch==0) opUnder=i;
761 if (i>3) {
762 Char_t buf2[5];
763 strncpy(buf2,&text[i-4],4);
764 if (strncmp(buf2,"#int",4)==0) {
765 abovePlace = 1;
766 if (i>4 && opCloseCurly==-2) opCloseCurly=i-5;
767 }
768 if (strncmp(buf2,"#sum",4)==0) {
769 abovePlace = 2;
770 if (i>4 && opCloseCurly==-2) opCloseCurly=i-5;
771 }
772 }
773 }
774 if (strncmp(buf,"]{",2)==0)
775 if (opSquareCurly==-1 && nBrackets==0 && nCroch==0) opSquareCurly=i;
776 }
777 // detect other operators
778 if (text[i]=='\\' || (text[i]=='#' && !opFound && nBrackets==0 && nCroch==0)) {
779
780 if (length>i+10) {
781 Char_t buf[11];
782 strncpy(buf,&text[i+1],10);
783 if (strncmp(buf,"splitline{",10)==0) {
785 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
786 continue;
787 }
788 }
789 if (length>i+9) {
790 Char_t buf[10];
791 strncpy(buf,&text[i+1],9);
792 if (!opBackslash && strncmp(buf,"backslash",9)==0) {
794 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
795 continue;
796 }
797 }
798 if (length>i+8) {
799 Char_t buf[9];
800 strncpy(buf,&text[i+1],8);
801 if (!opParallel && strncmp(buf,"parallel",8)==0) {
803 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
804 continue;
805 }
806 }
807 if (length>i+6) {
808 Char_t buf[7];
809 strncpy(buf,&text[i+1],6);
810 if (strncmp(buf,"lower[",6)==0 || strncmp(buf,"lower{",6)==0) {
811 opLower=i; opFound = kTRUE;
812 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
813 continue ;
814 }
815 if (strncmp(buf,"scale[",6)==0 || strncmp(buf,"scale{",6)==0) {
816 opScale=i; opFound = kTRUE;
817 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
818 continue ;
819 }
820 if (strncmp(buf,"color[",6)==0 || strncmp(buf,"color{",6)==0) {
821 opColor=i; opFound = kTRUE;
822 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
823 continue ;
824 }
825 }
826 if (length>i+5) {
827 Char_t buf[6];
828 strncpy(buf,&text[i+1],5);
829 if (strncmp(buf,"frac{",5)==0) {
830 opFrac=i; opFound = kTRUE;
831 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
832 continue;
833 }
834 if (strncmp(buf,"sqrt{",5)==0 || strncmp(buf,"sqrt[",5)==0) {
835 opSqrt=i; opFound = kTRUE;
836 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
837 continue;
838 }
839 if (strncmp(buf,"font{",5)==0 || strncmp(buf,"font[",5)==0) {
840 opFont=i; opFound = kTRUE;
841 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
842 continue;
843 }
844 if (strncmp(buf,"kern[",5)==0 || strncmp(buf,"kern{",5)==0) {
845 opKern=i; opFound = kTRUE;
846 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
847 continue ;
848 }
849 if (!opMinus && strncmp(buf,"minus",5)==0) {
850 opMinus=1; opFound = kTRUE;
851 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
852 continue;
853 }
854 if (strncmp(buf,"mbox[",5)==0 || strncmp(buf,"mbox{",5)==0) {
855 opMbox=i; opFound = kTRUE;
856 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
857 continue ;
858 }
859 }
860 if (length>i+4) {
861 Char_t buf[5];
862 strncpy(buf,&text[i+1],4);
863 if (!opOdot && strncmp(buf,"odot",4)==0) {
864 opOdot=1; opFound = kTRUE;
865 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
866 continue;
867 }
868 if (!opHbar && strncmp(buf,"hbar",4)==0) {
869 opHbar=1; opFound = kTRUE;
870 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
871 continue;
872 }
873 if (!opPerp && strncmp(buf,"perp",4)==0) {
874 opPerp=1; opFound = kTRUE;
875 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
876 continue;
877 }
878 if (!opPlus && strncmp(buf,"plus",4)==0) {
879 opPlus=1; opFound = kTRUE;
880 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
881 continue;
882 }
883 if (strncmp(buf,"url[",4)==0 || strncmp(buf,"url{",4)==0) {
884 opUrl=i; opFound = kTRUE;
885 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
886 continue ;
887 }
888 }
889 if (length>i+3) {
890 Char_t buf[4];
891 strncpy(buf,&text[i+1],3);
892 buf[3] = 0;
893 if (strncmp(buf,"[]{",3)==0) {
895 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
896 continue;
897 }
898 if (strncmp(buf,"{}{",3)==0 ) {
900 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
901 continue;
902 }
903 if (strncmp(buf,"||{",3)==0) {
904 opAbs=1; opFound = kTRUE;
905 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
906 continue;
907 }
908 if (strncmp(buf,"(){",3)==0) {
909 opParen=1; opFound = kTRUE;
910 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
911 continue;
912 }
913 if (!opBox && strncmp(buf,"Box",3)==0) {
914 opBox=1; opFound = kTRUE;
915 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
916 continue;
917 }
918 if (strncmp(buf,"bf[",3)==0 || strncmp(buf,"bf{",3)==0) {
919 opBf=i; opFound = kTRUE;
920 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
921 continue ;
922 }
923 if (strncmp(buf,"it[",3)==0 || strncmp(buf,"it{",3)==0) {
924 opIt=i; opFound = kTRUE;
925 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
926 continue ;
927 }
928 }
929 if (length>i+2) {
930 Char_t buf[3];
931 strncpy(buf,&text[i+1],2);
932 if (!opMp && strncmp(buf,"mp",2)==0) {
933 opMp=1; opFound = kTRUE;
934 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
935 continue;
936 }
937 }
938 for(k=0;k<54;k++) {
939 if (!opFound && UInt_t(length)>i+strlen(tab[k])) {
940 if (strncmp(&text[i+1],tab[k],strlen(tab[k]))==0) {
941 opGreek=k;
942 opFound = kTRUE;
943 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
944 }
945 }
946 }
947 for(k=0;k<10;k++) {
948 if (!opFound && UInt_t(length)>i+strlen(tab3[k])) {
949 if (strncmp(&text[i+1],tab3[k],strlen(tab3[k]))==0) {
950 opAbove=k;
951 opFound = kTRUE;
952 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
953 }
954 }
955 }
956 UInt_t lastsize = 0;
957 if (!opFound)
958 for(k=0;k<82;k++) {
959 if ((opSpec==-1 || strlen(tab2[k])>lastsize) && UInt_t(length)>i+strlen(tab2[k])) {
960 if (strncmp(&text[i+1],tab2[k],strlen(tab2[k]))==0) {
961 lastsize = strlen(tab2[k]);
962 opSpec=k;
963 opFound = kTRUE;
964 if (i>0 && opCloseCurly==-2) opCloseCurly=i-1;
965 }
966 }
967 }
968 }
969 }
970
975
976 // analysis of operators found
977 if (opCloseCurly>-1 && opCloseCurly<length-1) { // separator } found
978 if(!fShow) {
981 Savefs(&fs1);
982 } else {
983 fs1 = Readfs();
986 }
987 result = fs1+fs2;
988 }
989
990 else if (opPower>-1 && opUnder>-1) { // ^ and _ found
992 max = std::max(opPower,opUnder);
993 Double_t xfpos = 0. ; //GetHeight()*spec.fSize/5.;
994 Double_t prop=1, propU=1; // scale factor for #sum & #int
995 switch (abovePlace) {
996 case 1 :
997 prop = .8 ; propU = 1.75 ; // Int
998 break;
999 case 2:
1000 prop = .9 ; propU = 1.75 ; // Sum
1001 break;
1002 }
1003 // propU acts on upper number
1004 // when increasing propU value, the upper indice position is higher
1005 // when increasing prop values, the lower indice position is lower
1006
1007 if (!fShow) {
1008 Int_t ltext = min ;
1009 if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) {
1010 // upper and lower indice before the character
1011 // like with chemical element
1012 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1013 ltext-- ;
1014 }
1015 fs1 = Anal1(spec,text,ltext);
1016 fs2 = Anal1(specNewSize,text+min+1,max-min-1);
1017 fs3 = Anal1(specNewSize,text+max+1,length-max-1);
1018 Savefs(&fs1);
1019 Savefs(&fs2);
1020 Savefs(&fs3);
1021 } else {
1022 fs3 = Readfs();
1023 fs2 = Readfs();
1024 fs1 = Readfs();
1025 Double_t pos = 0;
1026 if (!abovePlace) {
1027 Double_t addW = fs1.Width()+xfpos, addH1, addH2;
1028 if (opPower<opUnder) {
1029 addH1 = -fs1.Over()*(fFactorPos)-fs2.Under();
1030 addH2 = fs1.Under()+fs3.Over()*(fFactorPos);
1031 } else {
1032 addH1 = fs1.Under()+fs2.Over()*(fFactorPos);
1033 addH2 = -fs1.Over()*(fFactorPos)-fs3.Under();
1034 }
1035 Analyse(x+addW,y+addH2,specNewSize,text+max+1,length-max-1);
1036 Analyse(x+addW,y+addH1,specNewSize,text+min+1,max-min-1);
1037 } else {
1039 Double_t m = std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width()));
1040 pos = (m-fs1.Width())/2;
1041 if (opPower<opUnder) {
1042 addH1 = -fs1.Over()*propU-fs2.Under();
1043 addW1 = (m-fs2.Width())/2;
1044 addH2 = fs1.Under()*prop+fs3.Over();
1045 addW2 = (m-fs3.Width())/2;
1046 } else {
1047 addH1 = fs1.Under()*prop+fs2.Over();
1048 addW1 = (m-fs2.Width())/2;
1049 addH2 = -fs1.Over()*propU-fs3.Under();
1050 addW2 = (m-fs3.Width())/2;
1051 }
1052
1053 Analyse(x+addW2,y+addH2,specNewSize,text+max+1,length-max-1);
1054 Analyse(x+addW1,y+addH1,specNewSize,text+min+1,max-min-1);
1055 }
1056
1057 if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) {
1058 snprintf(&text[min-2],length-(min-2)," ") ;
1059 Analyse(x+pos,y,spec,text,min-1);
1060 } else {
1061 Analyse(x+pos,y,spec,text,min);
1062 }
1063 }
1064
1065 if (!abovePlace) {
1066 if (opPower<opUnder) {
1067 result.Set(fs1.Width()+xfpos+std::max(fs2.Width(),fs3.Width()),
1068 fs1.Over()*fFactorPos+fs2.Height(),
1069 fs1.Under()+fs3.Height()-fs3.Over()*(1-fFactorPos));
1070 } else {
1071 result.Set(fs1.Width()+xfpos+std::max(fs2.Width(),fs3.Width()),
1072 fs1.Over()*fFactorPos+fs3.Height(),
1073 fs1.Under()+fs2.Height()-fs2.Over()*(1-fFactorPos));
1074 }
1075 } else {
1076 if (opPower<opUnder) {
1077 result.Set(std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width())),
1078 fs1.Over()*propU+fs2.Height(),fs1.Under()*prop+fs3.Height());
1079 } else {
1080 result.Set(std::max(fs1.Width(),std::max(fs2.Width(),fs3.Width())),
1081 fs1.Over()*propU+fs3.Height(),fs1.Under()*prop+fs2.Height());
1082 }
1083 }
1084 }
1085 else if (opPower>-1) { // ^ found
1086 Double_t prop=1;
1087 Double_t xfpos = 0. ; //GetHeight()*spec.fSize/5. ;
1088 switch (abovePlace) {
1089 case 1 : //int
1090 prop = 1.75 ; break ;
1091 case 2 : // sum
1092 prop = 1.75; break ;
1093 }
1094 // When increasing prop, the upper indice position is higher
1095 if (!fShow) {
1096 Int_t ltext = opPower ;
1097 if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) {
1098 // upper and lower indice before the character
1099 // like with chemical element
1100 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1101 ltext-- ;
1102 }
1103 fs1 = Anal1(spec,text,ltext);
1105 Savefs(&fs1);
1106 Savefs(&fs2);
1107 } else {
1108 fs2 = Readfs();
1109 fs1 = Readfs();
1110 Int_t pos = 0;
1111 if (!abovePlace){
1112 Double_t over = fs1.Over();
1113 if (over <= 0) over = 1.5*fs2.Over();
1115 } else {
1116 Int_t pos2=0;
1117 if (fs2.Width()>fs1.Width())
1118 pos=Int_t((fs2.Width()-fs1.Width())/2);
1119 else
1120 pos2=Int_t((fs1.Width()-fs2.Width())/2);
1121
1123 }
1124 if (opPower >= 2 && strncmp(&text[opPower-2],"{}",2)==0) {
1125 snprintf(&text[opPower-2],length-(opPower-2)," ") ;
1126 Analyse(x+pos,y,spec,text,opPower-1);
1127 } else {
1128 Analyse(x+pos,y,spec,text,opPower);
1129 }
1130 }
1131
1132 if (!abovePlace)
1133 result.Set(fs1.Width()+xfpos+fs2.Width(),
1134 fs1.Over()*fFactorPos+fs2.Over(),fs1.Under());
1135 else
1136 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Over()*prop+fs2.Height(),fs1.Under());
1137
1138 }
1139 else if (opUnder>-1) { // _ found
1140 Double_t prop = .9; // scale factor for #sum & #frac
1141 Double_t xfpos = 0.;//GetHeight()*spec.fSize/5. ;
1143 // When increasing prop, the lower indice position is lower
1144 if(!fShow) {
1145 Int_t ltext = opUnder ;
1146 if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) {
1147 // upper and lower indice before the character
1148 // like with chemical element
1149 snprintf(&text[ltext-2],length-(ltext-2),"I ") ;
1150 ltext-- ;
1151 }
1152 fs1 = Anal1(spec,text,ltext);
1154 Savefs(&fs1);
1155 Savefs(&fs2);
1156 } else {
1157 fs2 = Readfs();
1158 fs1 = Readfs();
1159 Int_t pos = 0;
1160 if (!abovePlace)
1161 Analyse(x+fs1.Width()+xfpos,y+fs1.Under()+fs2.Over()*fpos,specNewSize,text+opUnder+1,length-opUnder-1);
1162 else {
1163 Int_t pos2=0;
1164 if (fs2.Width()>fs1.Width())
1165 pos=Int_t((fs2.Width()-fs1.Width())/2);
1166 else
1167 pos2=Int_t((fs1.Width()-fs2.Width())/2);
1168
1170 }
1171 if (opUnder >= 2 && strncmp(&text[opUnder-2],"{}",2)==0) {
1172 snprintf(&text[opUnder-2],length-(opUnder-2)," ") ;
1173 Analyse(x+pos,y,spec,text,opUnder-1);
1174 } else {
1175 Analyse(x+pos,y,spec,text,opUnder);
1176 }
1177 }
1178 if (!abovePlace)
1179 result.Set(fs1.Width()+xfpos+fs2.Width(),fs1.Over(),
1180 fs1.Under()+fs2.Under()+fs2.Over()*fpos);
1181 else
1182 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Over(),fs1.Under()*prop+fs2.Height());
1183 }
1184 else if (opBox) {
1185 Double_t square = GetHeight()*spec.fSize/2;
1186 if (!fShow) {
1187 fs1 = Anal1(spec,text+4,length-4);
1188 } else {
1190 Double_t adjust = GetHeight()*spec.fSize/20;
1191 Double_t x1 = x+adjust ;
1193 Double_t y1 = y;
1199 }
1201 }
1202 else if (opOdot) {
1203 Double_t square = GetHeight()*spec.fSize/2;
1204 if (!fShow) {
1205 fs1 = Anal1(spec,text+5,length-5);
1206 } else {
1207 fs1 = Analyse(x+1.3*square,y,spec,text+5,length-5);
1208 Double_t adjust = GetHeight()*spec.fSize/20;
1209 Double_t r1 = 0.62*square;
1210 Double_t y1 = y-0.3*square-adjust;
1211 DrawCircle(x+0.6*square,y1,r1,spec) ;
1212 DrawCircle(x+0.6*square,y1,r1/100,spec) ;
1213 }
1215 }
1216 else if (opHbar) {
1217 Double_t square = GetHeight()*spec.fSize/2;
1218 if (!fShow) {
1219 fs1 = Anal1(spec,text+5,length-5);
1220 } else {
1222 TText hbar;
1223 hbar.SetTextFont(12);
1224 hbar.SetTextColor(spec.fColor);
1225 hbar.SetTextSize(spec.fSize);
1226 hbar.SetTextAngle(fTextAngle);
1227 hbar.SetTextAlign(11);
1228 Double_t xx, yy;
1229 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1230 hbar.PaintText(xx,yy,"h");
1231 DrawLine(x,y-0.8*square,x+0.75*square,y-square,spec);
1232 }
1234 }
1235 else if (opMinus) {
1236 Double_t square = GetHeight()*spec.fSize/2;
1237 if (!fShow) {
1238 fs1 = Anal1(spec,text+6,length-6);
1239 } else {
1241 TText minus;
1242 minus.SetTextFont(122);
1243 minus.SetTextColor(spec.fColor);
1244 minus.SetTextSize(spec.fSize);
1245 minus.SetTextAngle(fTextAngle);
1246 minus.SetTextAlign(11);
1247 Double_t xx, yy;
1248 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1249 minus.PaintText(xx,yy,"-");
1250 }
1252 }
1253 else if (opPlus) {
1254 Double_t square = GetHeight()*spec.fSize/2;
1255 if (!fShow) {
1256 fs1 = Anal1(spec,text+5,length-5);
1257 } else {
1259 TText plus;
1260 plus.SetTextFont(122);
1261 plus.SetTextColor(spec.fColor);
1262 plus.SetTextSize(spec.fSize);
1263 plus.SetTextAngle(fTextAngle);
1264 plus.SetTextAlign(11);
1265 Double_t xx, yy;
1266 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1267 plus.PaintText(xx,yy,"+");
1268 }
1270 }
1271 else if (opMp) {
1272 Double_t square = GetHeight()*spec.fSize/2;
1273 if (!fShow) {
1274 fs1 = Anal1(spec,text+3,length-3);
1275 } else {
1277 TText mp;
1278 mp.SetTextFont(122);
1279 mp.SetTextColor(spec.fColor);
1280 mp.SetTextSize(spec.fSize);
1281 mp.SetTextAngle(fTextAngle+180);
1282 mp.SetTextAlign(11);
1283 Double_t xx, yy;
1284 Rotate(gPad, spec.fAngle, x+square, y-1.25*square, xx, yy);
1285 mp.PaintText(xx,yy,"\261");
1286 }
1288 }
1289 else if (opPerp) {
1290 Double_t square = GetHeight()*spec.fSize/1.4;
1291 if (!fShow) {
1292 fs1 = Anal1(spec,text+5,length-5);
1293 } else {
1294 fs1 = Analyse(x+0.5*square,y,spec,text+5,length-5);
1295 Double_t x0 = x + 0.50*square;
1296 Double_t x1 = x0 - 0.48*square;
1297 Double_t x2 = x0 + 0.48*square;
1298 Double_t y1 = y + 0.6*square;
1299 Double_t y2 = y1 - 1.3*square;
1301 DrawLine(x0,y1,x0,y2,spec);
1302 }
1303 result = fs1;
1304 }
1305 else if (opBackslash) {
1306 Double_t square = GetHeight()*spec.fSize/2;
1307 if (!fShow) {
1308 fs1 = Anal1(spec,text+10,length-10);
1309 } else {
1310 fs1 = Analyse(x+square,y,spec,text+10,length-10);
1311 TText bs;
1312 bs.SetTextFont(GetTextFont());
1313 bs.SetTextColor(spec.fColor);
1314 bs.SetTextSize(spec.fSize);
1315 bs.SetTextAngle(fTextAngle);
1316 bs.SetTextAlign(11);
1317 Double_t xx, yy;
1318 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1319 bs.PaintText(xx,yy,"\\");
1320 }
1322 }
1323 else if (opParallel) {
1324 Double_t square = GetHeight()*spec.fSize/1.4;
1325 if (!fShow) {
1326 fs1 = Anal1(spec,text+9,length-9);
1327 } else {
1328 fs1 = Analyse(x+0.5*square,y,spec,text+9,length-9);
1329 Double_t x1 = x + 0.15*square;
1330 Double_t x2 = x + 0.45*square;
1331 Double_t y1 = y + 0.3*square;
1332 Double_t y2 = y1- 1.3*square;
1335 }
1337 }
1338 else if (opGreek>-1) {
1340 newSpec.fFont = fItalic ? 152 : 122;
1341 char letter = 97 + opGreek;
1342 Double_t yoffset = 0.; // Greek letter too low
1343 if (opGreek>25) letter -= 58;
1344 if (opGreek == 52) letter = '\241'; //varUpsilon
1345 if (opGreek == 53) letter = '\316'; //epsilon
1346 if (!fShow) {
1347 fs1 = Anal1(newSpec,&letter,1);
1349 Savefs(&fs1);
1350 } else {
1351 fs1 = Readfs();
1354 }
1355 fs1.AddOver(TLatexFormSize(0,yoffset,0)) ;
1356 result = fs1+fs2;
1357 }
1358
1359 else if (opSpec>-1) {
1361 newSpec.fFont = fItalic ? 152 : 122;
1362 char letter = '\243' + opSpec;
1363 if(opSpec == 75 || opSpec == 76) {
1364 newSpec.fFont = GetTextFont();
1365 if (gVirtualX->InheritsFrom("TGCocoa")) {
1366 if (opSpec == 75) letter = '\201'; // AA Angstroem
1367 if (opSpec == 76) letter = '\214'; // aa Angstroem
1368 } else {
1369 if (opSpec == 75) letter = '\305'; // AA Angstroem
1370 if (opSpec == 76) letter = '\345'; // aa Angstroem
1371 }
1372 }
1373 if(opSpec == 80 || opSpec == 81) {
1374 if (opSpec == 80) letter = '\042'; // #forall
1375 if (opSpec == 81) letter = '\044'; // #exists
1376 }
1378 props = 1.8 ; // scale factor for #sum(66)
1379 propi = 2.3 ; // scale factor for #int(79)
1380
1381 if (opSpec==66 ) {
1382 newSpec.fSize = spec.fSize*props;
1383 } else if (opSpec==79) {
1384 newSpec.fSize = spec.fSize*propi;
1385 }
1386 if (!fShow) {
1387 fs1 = Anal1(newSpec,&letter,1);
1388 if (opSpec == 79 || opSpec == 66)
1389 fs1.Set(fs1.Width(),fs1.Over()*0.45,fs1.Over()*0.45);
1390
1392 Savefs(&fs1);
1393 } else {
1394 fs1 = Readfs();
1396 if (opSpec!=66 && opSpec!=79)
1397 Analyse(x,y,newSpec,&letter,1);
1398 else {
1399 Analyse(x,y+fs1.Under()/2.,newSpec,&letter,1);
1400 }
1401 }
1402 result = fs1+fs2;
1403 }
1404 else if (opAbove>-1) {
1405 if (!fShow) {
1407 Savefs(&fs1);
1408 } else {
1409 fs1 = Readfs();
1411 Double_t sub = GetHeight()*spec.fSize/14;
1412 switch(opAbove) {
1413 case 0: { // bar
1414 Double_t xx[2], yy[2];
1415 xx[0] = x; xx[1] = x + fs1.Width();
1416 yy[0] = yy[1] = y - sub - fs1.Over();
1417 DrawPolyLine(2, xx, yy, spec, 0.03);
1418 break;
1419 }
1420 case 1: { // vec
1421 Double_t xx[3], yy[3],
1422 dd = GetHeight()*spec.fSize/8, // arrow size
1423 midy = y - sub - fs1.Over() - dd; // middle arrow line
1424 xx[0] = x; xx[1] = x + fs1.Width();
1425 yy[0] = yy[1] = midy;
1426 DrawPolyLine(2, xx, yy, spec, 0.03);
1427 xx[1] = x + fs1.Width(); xx[0] = xx[2] = xx[1] - 2*dd;
1428 yy[0] = midy - dd; yy[1] = midy; yy[2] = midy + dd;
1429 DrawPolyLine(3, xx, yy, spec, 0.03);
1430 break;
1431 }
1432 case 2: { // dot
1433 Double_t dd = std::max(0.5*GetLineWidth(), 0.5*sub), // dot size
1434 midx = x + fs1.Width()/2,
1435 midy = y - sub - fs1.Over() - dd;
1436 Double_t xx[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1437 yy[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1438 DrawPolyLine(5, xx, yy, spec, 10.);
1439 break;
1440 }
1441 case 3: { // hat
1442 Double_t xx[3], yy[3];
1443 xx[1] = x + fs1.Width()/2;
1444 xx[0] = xx[1] - fs1.Width()/3;
1445 xx[2] = xx[1] + fs1.Width()/3;
1446 yy[0] = y - sub - fs1.Over();
1447 yy[1] = yy[0] - 2*sub;
1448 yy[2] = yy[0];
1449 DrawPolyLine(3, xx, yy, spec, 0.03);
1450 break;
1451 }
1452 case 4: { // ddot
1453 Double_t dd = std::max(0.5*GetLineWidth(), 0.5*sub), // dot size
1454 midx = x + fs1.Width()/2 - 1.5*sub,
1455 midy = y - sub - fs1.Over() - dd;
1456 Double_t xx1[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1457 yy1[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1458 DrawPolyLine(5, xx1, yy1, spec, 10.);
1459 midx = x + fs1.Width()/2 + 1.5*sub;
1460 Double_t xx2[5] = { midx - dd, midx - dd, midx + dd, midx + dd, midx - dd },
1461 yy2[5] = { midy + dd, midy - dd, midy - dd, midy + dd, midy + dd };
1462 DrawPolyLine(5, xx2, yy2, spec, 10.);
1463 break;
1464 }
1465 case 5: { // acute
1466 Double_t xx[2], yy[2];
1467 xx[0] = x + fs1.Width()/2; xx[1] = xx[0] + 3*sub;
1468 yy[0] = y - sub - fs1.Over();
1469 yy[1] = yy[0] - 2.5*sub;
1470 DrawPolyLine(2, xx, yy, spec, 0.03);
1471 break;
1472 }
1473 case 6: { // grave
1474 Double_t xx[2], yy[2];
1475 xx[0] = x + fs1.Width()/2 + sub; xx[1] = xx[0] - 2*sub;
1476 yy[0] = y - sub - fs1.Over();
1477 yy[1] = yy[0] - 2*sub;
1478 DrawPolyLine(2, xx, yy, spec, 0.03);
1479 break;
1480 }
1481 case 7: { // check
1482 Double_t xx[3], yy[3];
1483 xx[1] = x+fs1.Width()/2; xx[0] = xx[1] - 2*sub; xx[2] = xx[1] + 2*sub;
1484 yy[1] = y - sub - fs1.Over();
1485 yy[0] = yy[2] = yy[1] - 2*sub;
1486 DrawPolyLine(3, xx, yy, spec, 0.03);
1487 break;
1488 }
1489 case 8: { // tilde
1490 Double_t x2 = x+fs1.Width()/2, y2 = y -fs1.Over();
1491 // tilde must be drawn separately on screen and on PostScript
1492 // because an adjustment is required along Y for PostScript.
1494 if (gVirtualPS) gVirtualPS = nullptr;
1495 Double_t y22 = y2;
1496 if (gVirtualX->InheritsFrom("TGCocoa")) y2 -= 4.7*sub;
1497 Double_t xx, yy;
1498 Rotate(gPad, spec.fAngle, x2, y2, xx, yy);
1499 TText tilde;
1500 tilde.SetTextFont(fTextFont);
1501 tilde.SetTextColor(spec.fColor);
1502 tilde.SetTextSize(0.9*spec.fSize);
1503 tilde.SetTextAlign(22);
1504 tilde.SetTextAngle(fTextAngle);
1505 tilde.PaintText(xx,yy,"~");
1506 if (saveps) {
1508 if (!strstr(gVirtualPS->GetTitle(),"IMG")) y22 -= 4*sub;
1509 Rotate(gPad, spec.fAngle, x2, y22, xx, yy);
1511 gVirtualPS->Text(xx, yy, "~");
1512 }
1513 break;
1514 }
1515 case 9: { // slash
1516 Double_t xx[2], yy[2];
1517 xx[0] = x + 0.8*fs1.Width();
1518 yy[0] = y - fs1.Over() - sub;
1519 xx[1] = x + 0.3*fs1.Width();
1520 yy[1] = yy[0] + fs1.Height() + 2*sub;
1521 DrawPolyLine(2, xx, yy, spec, 0.03);
1522 break;
1523 }
1524 }
1525 }
1526 Double_t div = 3;
1527 if (opAbove==1) div=4;
1528 result.Set(fs1.Width(),fs1.Over()+GetHeight()*spec.fSize/div,fs1.Under());
1529 }
1530 else if (opSquareBracket) { // operator #[]{arg}
1531 Double_t l = GetHeight()*spec.fSize/4;
1532 Double_t l2 = l/2 ;
1533 if (!fShow) {
1534 fs1 = Anal1(spec,text+3,length-3);
1535 Savefs(&fs1);
1536 } else {
1537 fs1 = Readfs();
1538 Analyse(x+l2+l,y,spec,text+3,length-3);
1539 DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec);
1540 DrawLine(x+l2,y-fs1.Over(),x+l2+l,y-fs1.Over(),spec);
1541 DrawLine(x+l2,y+fs1.Under(),x+l2+l,y+fs1.Under(),spec);
1542 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec);
1543 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+l,y-fs1.Over(),spec);
1544 DrawLine(x+l2+fs1.Width()+2*l,y+fs1.Under(),x+l2+fs1.Width()+l,y+fs1.Under(),spec);
1545 }
1546 result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1547 }
1548 else if (opParen) { // operator #(){arg}
1549 Double_t l = GetHeight()*spec.fSize/4;
1550 Double_t radius2,radius1 , dw, l2 = l/2 ;
1551 Double_t angle = 35 ;
1552 if (!fShow) {
1553 fs1 = Anal1(spec,text+3,length-3);
1554 Savefs(&fs1);
1555 radius2 = fs1.Height() ;
1556 radius1 = radius2 * 2 / 3;
1557 dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ;
1558 } else {
1559 fs1 = Readfs();
1560 radius2 = fs1.Height();
1561 radius1 = radius2 * 2 / 3;
1562 dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ;
1563 Double_t x1 = x+l2+radius1 ;
1564 Double_t x2 = x+5*l2+2*dw+fs1.Width()-radius1 ;
1565 Double_t y1 = y - (fs1.Over() - fs1.Under())/2. ;
1568 Analyse(x+3*l2+dw,y,spec,text+3,length-3);
1569 }
1570 // result = TLatexFormSize(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1571 result.Set(fs1.Width()+3*l+2*dw,fs1.Over(),fs1.Under());
1572 }
1573 else if (opAbs) { // operator #||{arg}
1574 Double_t l = GetHeight()*spec.fSize/4;
1575 Double_t l2 = l/2 ;
1576 if (!fShow) {
1577 fs1 = Anal1(spec,text+3,length-3);
1578 Savefs(&fs1);
1579 } else {
1580 fs1 = Readfs();
1581 Analyse(x+l2+l,y,spec,text+3,length-3);
1582 DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec);
1583 DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec);
1584 }
1585 result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under());
1586 }
1587 else if (opBigCurly) { // big curly bracket #{}{arg}
1588 Double_t l = GetHeight()*spec.fSize/4;
1589 Double_t l2 = l/2 ;
1590 Double_t l8 , ltip;
1591
1592 if (!fShow) {
1593 fs1 = Anal1(spec,text+3,length-3);
1594 l8 = fs1.Height()/8 ;
1595 ltip = TMath::Min(l8,l) ;
1596 l = ltip ;
1597 Savefs(&fs1);
1598 } else {
1599 fs1 = Readfs();
1600 Double_t y2 = y + (fs1.Under()-fs1.Over())/2 ;
1601 l8 = fs1.Height()/8 ;
1602 ltip = TMath::Min(l8,l) ;
1603 l = ltip ;
1604 Analyse(x+l+ltip+l2,y,spec,text+3,length-3);
1605 // Draw open curly bracket
1606 // Vertical lines
1607 DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip,y2-ltip,spec);
1608 DrawLine(x+l2+ltip,y2+ltip,x+l2+ltip,y+fs1.Under(),spec);
1609 // top and bottom lines
1610 DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip+l,y-fs1.Over(),spec);
1611 DrawLine(x+l2+ltip,y+fs1.Under(),x+l2+ltip+l,y+fs1.Under(),spec);
1612 // < sign
1615
1616 // Draw close curly bracket
1617 // vertical lines
1618 DrawLine(x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y2-ltip,spec);
1619 DrawLine(x+l2+ltip+fs1.Width()+2*l,y2+ltip,x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec);
1620 // Top and bottom lines
1621 DrawLine(x+l2+fs1.Width()+l+ltip,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),spec);
1622 DrawLine(x+l2+fs1.Width()+l+ltip,y+fs1.Under(),x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec);
1623 // > sign
1624 DrawLine(x+l2+ltip+2*l+fs1.Width(),y2-ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec);
1625 DrawLine(x+l2+ltip+2*l+fs1.Width(),y2+ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec);
1626 }
1627 result.Set(fs1.Width()+3*l+2*ltip,fs1.Over(),fs1.Under());
1628 }
1629 else if (opFrac>-1) { // \frac found
1630 if (opCurlyCurly==-1) { // }{ not found
1631 // arguments missing for \frac
1632 fError = "Missing denominator for #frac";
1633 delete[] text;
1634 return TLatexFormSize(0,0,0);
1635 }
1636 Double_t height = GetHeight()*spec.fSize/8;
1637 if (!fShow) {
1640 Savefs(&fs1);
1641 Savefs(&fs2);
1642 } else {
1643 fs2 = Readfs();
1644 fs1 = Readfs();
1646 if (fs1.Width()<fs2.Width()) {
1647 addW1 = (fs2.Width()-fs1.Width())/2;
1648 addW2 = 0;
1649 } else {
1650 addW1 = 0;
1651 addW2 = (fs1.Width()-fs2.Width())/2;
1652 }
1653 Analyse(x+addW2,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // denominator
1654 Analyse(x+addW1,y-fs1.Under()-3*height,spec,text+opFrac+6,opCurlyCurly-opFrac-6); //numerator
1655
1656 DrawLine(x,y-2*height,x+std::max(fs1.Width(),fs2.Width()),y-2*height,spec);
1657 }
1658
1659 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
1660
1661 }
1662 else if (opSplitLine>-1) { // \splitline found
1663 if (opCurlyCurly==-1) { // }{ not found
1664 // arguments missing for \splitline
1665 fError = "Missing second line for #splitline";
1666 delete[] text;
1667 return TLatexFormSize(0,0,0);
1668 }
1669 Double_t height = GetHeight()*spec.fSize/8;
1670 if (!fShow) {
1673 Savefs(&fs1);
1674 Savefs(&fs2);
1675 } else {
1676 fs2 = Readfs();
1677 fs1 = Readfs();
1678 Analyse(x,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // second line
1679 Analyse(x,y-fs1.Under()-3*height,spec,text+opSplitLine+11,opCurlyCurly-opSplitLine-11); //first line
1680 }
1681
1682 result.Set(std::max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
1683
1684 }
1685 else if (opSqrt>-1) { // \sqrt found
1686 if (!fShow) {
1687 if (opSquareCurly>-1) {
1688 // power nth #sqrt[n]{arg}
1691 Savefs(&fs1);
1692 Savefs(&fs2);
1693 result.Set(fs2.Width()+ GetHeight()*spec.fSize/10+std::max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width()),
1694 fs2.Over()+fs1.Height()+GetHeight()*spec.fSize/4,fs2.Under());
1695 } else {
1697 Savefs(&fs1);
1698 result.Set(fs1.Width()+GetHeight()*spec.fSize/2,fs1.Over()+GetHeight()*spec.fSize/4,fs1.Under());
1699 }
1700 } else {
1701 if (opSquareCurly>-1) { // ]{
1702 fs2 = Readfs();
1703 fs1 = Readfs();
1704 Double_t pas = std::max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width());
1705 Double_t pas2 = pas + GetHeight()*spec.fSize/10;
1706 Double_t y1 = y-fs2.Over() ;
1707 Double_t y2 = y+fs2.Under() ;
1708 Double_t y3 = y1-GetHeight()*spec.fSize/4;
1710 Analyse(x,y-fs2.Over()-fs1.Under(),specNewSize,text+opSqrt+6,opSquareCurly-opSqrt-6); // indice
1711 DrawLine(x,y1,x+pas,y2,spec);
1713 DrawLine(x+pas,y3,x+pas2+fs2.Width(),y3,spec);
1714 } else {
1715 fs1 = Readfs();
1716 Double_t x1 = x+GetHeight()*spec.fSize*2/5 ;
1717 Double_t x2 = x+GetHeight()*spec.fSize/2+fs1.Width() ;
1718 Double_t y1 = y-fs1.Over() ;
1719 Double_t y2 = y+fs1.Under() ;
1720 Double_t y3 = y1-GetHeight()*spec.fSize/4;
1721
1723
1725 SetLineWidth(1);
1726 Double_t dx = (y2-y3)/8;
1727 UInt_t a,d;
1729 if (a>12) SetLineWidth(std::max(2,(Int_t)(dx/2)));
1730 DrawLine(x1-2*dx,y1,x1-dx,y2,spec);
1731 if (a>12) SetLineWidth(std::max(1,(Int_t)(dx/4)));
1735 }
1736 }
1737 }
1738 else if (opColor>-1) { // \color found
1739 if (opSquareCurly==-1) {
1740 // color number is not specified
1741 fError = "Missing color number. Syntax is #color[(Int_t)nb]{ ... }";
1742 delete[] text;
1743 return TLatexFormSize(0,0,0);
1744 }
1748 nb[opSquareCurly-opColor-7] = 0;
1749 if (sscanf(nb,"%d",&newSpec.fColor) < 1) {
1750 delete[] nb;
1751 // color number is invalid
1752 fError = "Invalid color number. Syntax is #color[(Int_t)nb]{ ... }";
1753 delete[] text;
1754 return TLatexFormSize(0,0,0);
1755 }
1756 delete[] nb;
1757 if (!fShow) {
1759 } else {
1761 }
1762 }
1763 else if (opUrl>-1) { // \url found
1764 if (opSquareCurly==-1) {
1765 // url is not specified
1766 fError = "Missing url. Syntax is #url[http://...]{ ... }";
1767 delete[] text;
1768 return TLatexFormSize(0,0,0);
1769 }
1773 fName = url;
1774 delete[] url;
1775 if (!fShow) {
1777 } else {
1779 }
1780 fName = "";
1781 }
1782 else if (opFont>-1) { // \font found
1783 if (opSquareCurly==-1) {
1784 // font number is not specified
1785 fError = "Missing font number. Syntax is #font[nb]{ ... }";
1786 delete[] text;
1787 return TLatexFormSize(0,0,0);
1788 }
1792 nb[opSquareCurly-opFont-6] = 0;
1793 if (sscanf(nb,"%d",&newSpec.fFont) < 1) {
1794 delete[] nb;
1795 // font number is invalid
1796 fError = "Invalid font number. Syntax is #font[(Int_t)nb]{ ... }";
1797 delete[] text;
1798 return TLatexFormSize(0,0,0);
1799 }
1800 delete[] nb;
1801 if (!fShow) {
1803 } else {
1805 }
1806 }
1807 else if (opKern>-1) { // #kern found
1808 if (opSquareCurly==-1) {
1809 // horizontal shift is not specified
1810 fError = "Missing horizontal shift number. Syntax is #kern[dx]{ ... }";
1811 delete[] text;
1812 return TLatexFormSize(0,0,0);
1813 }
1816 dxc[opSquareCurly-opKern-6] = 0;
1817 Float_t dx = 0;
1818 if (sscanf(dxc,"%f",&dx) < 1) {
1819 delete[] dxc;
1820 // horizontal shift number is invalid
1821 fError = "Invalid horizontal shift number. Syntax is #kern[(Float_t)dx]{ ... }";
1822 delete[] text;
1823 return TLatexFormSize(0,0,0);
1824 }
1825 delete[] dxc;
1826 if (!fShow) {
1828 Savefs(&fs1);
1829 Double_t ddx = dx * fs1.Width();
1830 result = TLatexFormSize(fs1.Width() + ddx, fs1.Over(), fs1.Under());
1831 } else {
1832 fs1 = Readfs();
1833 Double_t ddx = dx * fs1.Width();
1835 }
1836 }
1837 else if (opLower>-1) { // #lower found
1838 if (opSquareCurly==-1) {
1839 // vertical shift is not specified
1840 fError = "Missing vertical shift number. Syntax is #lower[dy]{ ... }";
1841 delete[] text;
1842 return TLatexFormSize(0,0,0);
1843 }
1846 dyc[opSquareCurly-opLower-7] = 0;
1847 Float_t dy = 0;
1848 if (sscanf(dyc,"%f",&dy) < 1) {
1849 delete[] dyc;
1850 // vertical shift number is invalid
1851 fError = "Invalid vertical shift number. Syntax is #lower[(Float_t)dy]{ ... }";
1852 delete[] text;
1853 return TLatexFormSize(0,0,0);
1854 }
1855 delete[] dyc;
1856 if (!fShow) {
1858 Savefs(&fs1);
1859 Double_t ddy = dy * (fs1.Over() + fs1.Under());
1860 result = TLatexFormSize(fs1.Width(), fs1.Over() + ddy, fs1.Under() + ddy);
1861 } else {
1862 fs1 = Readfs();
1863 Double_t ddy = dy * (fs1.Over() + fs1.Under());
1865 }
1866 }
1867 else if (opScale>-1) { // \scale found
1868 if (opSquareCurly==-1) {
1869 // scale factor is not specified
1870 fError = "Missing scale factor. Syntax is #scale[(Double_t)nb]{ ... }";
1871 delete[] text;
1872 return TLatexFormSize(0,0,0);
1873 }
1877 nb[opSquareCurly-opScale-7] = 0;
1878 if (sscanf(nb,"%lf",&newSpec.fSize) < 1) {
1879 delete[] nb;
1880 // scale factor is invalid
1881 fError = "Invalid scale factor. Syntax is #factor[(Double_t)nb]{ ... }";
1882 delete[] text;
1883 return TLatexFormSize(0,0,0);
1884 }
1885 newSpec.fSize *= spec.fSize;
1886 delete[] nb;
1887 if (!fShow) {
1889 } else {
1891 }
1892 }
1893 else if (opBf>-1) { // operator #bf{arg}
1895 Int_t lut[] = {3, 13, 1, 6, 7, 4, 5, 10, 11, 8, 9, 12, 2, 14, 15};
1896 Int_t fontId = (newSpec.fFont/10);
1897 if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1];
1898 newSpec.fFont = fontId*10 + newSpec.fFont%10;
1899 if (!fShow) {
1900 fs1 = Anal1(newSpec,text+3,length-3);
1901 Savefs(&fs1);
1902 } else {
1903 fs1 = Readfs();
1905 }
1906 result = fs1;
1907 }
1908 else if (opMbox>-1) { // dummy operator #mbox{arg}
1910 if (!fShow) {
1911 fs1 = Anal1(newSpec,text+5,length-5);
1912 Savefs(&fs1);
1913 } else {
1914 fs1 = Readfs();
1916 }
1917 result = fs1;
1918 }
1919 else if (opIt>-1) { // operator #it{arg}
1921 Int_t lut[] = {13, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 15, 1, 14, 12};
1922 Int_t fontId = (newSpec.fFont/10);
1923 if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1];
1924 newSpec.fFont = fontId*10 + newSpec.fFont%10;
1925 fItalic = !fItalic;
1926 if (!fShow) {
1927 fs1 = Anal1(newSpec,text+3,length-3);
1928 Savefs(&fs1);
1929 } else {
1930 fs1 = Readfs();
1932 }
1933 fItalic = !fItalic;
1934 result = fs1;
1935 }
1936 else { // no operators found, it is a character string
1937 SetTextSize(spec.fSize);
1938 SetTextAngle(spec.fAngle);
1939 SetTextColor(spec.fColor);
1940 SetTextFont(spec.fFont);
1941 SetTextAlign(11);
1943 UInt_t w=0,h=0;
1944
1945 Int_t leng = strlen(text) ;
1946
1947 quote1 = quote2 = kFALSE ;
1948 Char_t *p ;
1949 for (i=0 ; i<leng ; i++) {
1950 switch (text[i]) {
1951 case '\'' : quote1 = !quote1 ; break ; // single quote symbol not correctly interpreted when PostScript
1952 case '"' : quote2 = !quote2 ; break ;
1953 }
1954 //if (quote1 || quote2) continue ;
1955 if (text[i] == '@') { // @ symbol not correctly interpreted when PostScript
1956 p = &text[i] ;
1957 if ( *(p+1) == '{' || *(p+1) == '}' || *(p+1) == '[' || *(p+1) == ']') {
1958 while (*p != 0) {
1959 *p = *(p+1) ; p++ ;
1960 }
1961 leng-- ;
1962 }
1963 }
1964 }
1965 text[leng] = 0 ;
1966
1967 if (fShow) {
1968 // paint the Latex sub-expression per sub-expression
1969 Double_t xx, yy;
1970 Rotate(gPad, spec.fAngle, x, y, xx, yy);
1971 if (fName.Length() > 0) gPad->PaintTextUrl(xx, yy, text, fName.Data());
1972 else gPad->PaintText(xx, yy, text);
1973 } else {
1975 Double_t width = w;
1976 UInt_t a,d;
1978 fs1.Set(width,a,d);
1979 }
1980
1981 result = fs1;
1982 }
1983
1984 delete[] text;
1985
1986 return result;
1987}
1988
1989////////////////////////////////////////////////////////////////////////////////
1990/// Make a copy of this object with the new parameters
1991/// And copy object attributes
1992
1994{
1995 TLatex *newtext = new TLatex(x, y, text);
1998 newtext->SetBit(kCanDelete);
1999 if (TestBit(kTextNDC)) newtext->SetNDC();
2000 newtext->AppendPad();
2001 return newtext;
2002}
2003
2004////////////////////////////////////////////////////////////////////////////////
2005/// Draw this TLatex with new coordinates in NDC.
2006
2008{
2010 newtext->SetNDC();
2011 return newtext;
2012}
2013
2014
2015////////////////////////////////////////////////////////////////////////////////
2016/// Draw a poly line in a Latex formula
2017/// Is scale_width parameter >=1, fill area will be drawn
2018/// Otherwise line width will be scaled proportional to current font size
2019/// If not specified - default line width will be used
2021{
2022 if (!gPad)
2023 return;
2024
2025 Rotate(gPad, spec.fAngle, npoints, xx, yy);
2026
2027 if (scale_width >= 1.) {
2028 TAttFill fill(spec.fColor, 1001);
2029 fill.Modify();
2030 gPad->PaintFillArea(npoints, xx, yy, "f");
2031 return;
2032 }
2033
2034 auto prevWidth = GetLineWidth();
2035 if (scale_width) {
2038 }
2039
2040 SetLineColor(spec.fColor);
2042
2043 gPad->PaintPolyLine(npoints, xx, yy);
2044 if (scale_width)
2046}
2047
2048
2049////////////////////////////////////////////////////////////////////////////////
2050/// Draw a line in a Latex formula
2051
2053{
2054 if (!gPad) return;
2055 Double_t xx[2] = { x1, x2 };
2056 Double_t yy[2] = { y1, y2 };
2057 Rotate(gPad, spec.fAngle, 2, xx, yy);
2058 SetLineColor(spec.fColor);
2060 gPad->PaintLine(xx[0], yy[0], xx[1], yy[1]);
2061}
2062
2063////////////////////////////////////////////////////////////////////////////////
2064/// Draw an arc of ellipse in a Latex formula (right or left parenthesis)
2065
2067{
2068 if (!gPad)
2069 return;
2070 if (r < 1)
2071 r = 1;
2072
2073 const Int_t np = 40;
2074 Double_t dphi = 2*kPI/np;
2075 Double_t x[np+3], y[np+3];
2076
2077 SetLineColor(spec.fColor);
2078 TAttLine::Modify(); //Change line attributes only if necessary
2079
2080 for (Int_t i = 0; i <= np; i++) {
2081 Double_t angle = i*dphi;
2082 x[i] = x1 + r*TMath::Cos(angle);
2083 y[i] = y1 + r*TMath::Sin(angle);
2084 }
2085 Rotate(gPad, spec.fAngle, np+1, x, y);
2086
2087 gPad->PaintPolyLine(np+1, x, y);
2088}
2089
2090////////////////////////////////////////////////////////////////////////////////
2091/// Draw an arc of ellipse in a Latex formula (right or left parenthesis)
2092
2095{
2096 if (!gPad)
2097 return;
2098 if (r1 < 1)
2099 r1 = 1;
2100 if (r2 < 1)
2101 r2 = 1;
2102
2103 const Int_t np = 40;
2104 Double_t dphi = (phimax-phimin)*kPI/(180*np);
2105 Double_t x[np+3], y[np+3];
2106
2107 SetLineColor(spec.fColor);
2108 TAttLine::Modify(); //Change line attributes only if necessary
2109
2110 for (Int_t i = 0; i <= np; i++) {
2111 Double_t angle = phimin*kPI/180 + i*dphi;
2112 x[i] = x1 + r1*TMath::Cos(angle);
2113 y[i] = y1 + r2*TMath::Sin(angle);
2114 }
2115
2116 Rotate(gPad, spec.fAngle, np+1, x, y);
2117
2118 gPad->PaintPolyLine(np+1,x,y);
2119}
2120
2121////////////////////////////////////////////////////////////////////////////////
2122/// Paint.
2123
2124void TLatex::Paint(Option_t *)
2125{
2126 if (!gPad) return ;
2127 Double_t xsave = fX;
2128 Double_t ysave = fY;
2129 if (TestBit(kTextNDC)) {
2130 fX = gPad->GetX1() + xsave*(gPad->GetX2() - gPad->GetX1());
2131 fY = gPad->GetY1() + ysave*(gPad->GetY2() - gPad->GetY1());
2133 } else {
2134 PaintLatex(gPad->XtoPad(fX),gPad->YtoPad(fY),GetTextAngle(),GetTextSize(),GetTitle());
2135 }
2136 fX = xsave;
2137 fY = ysave;
2138}
2139
2140////////////////////////////////////////////////////////////////////////////////
2141/// Main drawing function
2142///
2143/// Warning: Unlike most others "XYZ::PaintXYZ" methods, PaintLatex modifies
2144/// the TLatex data members.
2145
2147{
2148 if (size<=0 || strlen(text1) <= 0) return; // do not paint empty text or text with size <= 0
2149
2150 TAttText::Modify(); // Change text attributes only if necessary.
2151
2153
2154 if (gVirtualPS) {
2155 if (gVirtualPS->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 gVirtualPS->Text(x,y,t.Data());
2220 } else {
2221 Bool_t saveb = gPad->IsBatch();
2222 gPad->SetBatch(kTRUE);
2223 if (!PaintLatex1( x, y, angle, size, text1)) {
2224 if (saveps) gVirtualPS = saveps;
2225 return;
2226 }
2227 gPad->SetBatch(saveb);
2228 }
2229 gVirtualPS = nullptr;
2230 }
2231
2232 if (!gPad->IsBatch()) PaintLatex1( x, y, angle, size, text1);
2233 if (saveps) gVirtualPS = saveps;
2234}
2235
2236////////////////////////////////////////////////////////////////////////////////
2237/// Drawing function
2238
2240{
2241 if (!gPad)
2242 return 0;
2244 if(newText.Length() == 0)
2245 return 0;
2246 newText.ReplaceAll("#hbox","#mbox");
2247
2248 fError = nullptr;
2250 Error("PaintLatex1", "%s\n==> %s", fError, text1);
2251 return 0;
2252 }
2253 fError = nullptr;
2254
2255 // Do not use Latex if font is low precision.
2256 if (fTextFont % 10 < 2) {
2257 if (gVirtualX) gVirtualX->SetTextAngle(angle);
2259 gPad->PaintText(x,y,text1);
2260 return 1;
2261 }
2262
2263 Bool_t saveb = gPad->IsBatch();
2264 // Paint the text using TMathText if contains a "\"
2265 if (strstr(text1,"\\")) {
2266 TMathText tm;
2267 tm.SetTextAlign(GetTextAlign());
2268 tm.SetTextFont(GetTextFont());
2269 tm.SetTextColor(GetTextColor());
2270 tm.PaintMathText(x, y, angle, size, text1);
2271 // If PDF, paint using TLatex
2272 if (gVirtualPS) {
2273 if (gVirtualPS->InheritsFrom("TPDF") ||
2274 gVirtualPS->InheritsFrom("TSVG")) {
2275 newText.ReplaceAll("\\","#");
2276 gPad->SetBatch(kTRUE);
2277 } else {
2278 return 1;
2279 }
2280 } else {
2281 return 1;
2282 }
2283 }
2284
2287 if (fTextFont % 10 > 2) {
2289 SetTextFont(10*(saveFont/10) + 2);
2290 }
2291
2292 Int_t length = newText.Length();
2293 const Char_t *text = newText.Data();
2294
2295 Double_t xsave = fX;
2296 Double_t ysave = fY;
2297 fX = x;
2298 fY = y;
2299 gPad->XYtoAbsPixel(fX, fY, x, y);
2300 fShow = kFALSE;
2302
2303 fOriginSize = size;
2304
2305 // Get current line attributes.
2308
2310 spec.fAngle = angle;
2311 spec.fSize = size;
2312 spec.fColor = GetTextColor();
2313 spec.fFont = GetTextFont();
2317 if (fError) {
2318 Error("PaintLatex1", "%s\n==> %s", fError, text);
2319 } else {
2320 fShow = kTRUE;
2321 newSpec.fSize = size;
2322
2323 switch (valign) {
2324 case 0: y -= fs.Under(); break;
2325 case 1: break;
2326 case 2: y += fs.Height()*0.5-fs.Under() + 1.; break;
2327 case 3: y += fs.Over(); break;
2328 }
2329 switch (halign) {
2330 case 2: x -= fs.Width()/2; break;
2331 case 3: x -= fs.Width(); break;
2332 }
2334 }
2335
2336 gPad->SetBatch(saveb);
2340 SetTextColor(spec.fColor);
2344 fTabSize.clear();
2345 fX = xsave;
2346 fY = ysave;
2347 return fError ? 0 : 1;
2348}
2349
2350////////////////////////////////////////////////////////////////////////////////
2351/// Check if the Latex syntax is correct
2352
2354{
2355 const Char_t *kWord1[] = {"{}^{","{}_{","^{","_{","#scale{","#color{","#url{","#font{","#sqrt{","#[]{","#{}{","#||{",
2356 "#bar{","#vec{","#dot{","#hat{","#ddot{","#acute{","#grave{","#check{","#tilde{","#slash{","#bf{","#it{","#mbox{",
2357 "\\scale{","\\color{","\\font{","\\sqrt{","\\[]{","\\{}{","\\||{","#(){","\\(){",
2358 "\\bar{","\\vec{","\\dot{","\\hat{","\\ddot{","\\acute{","\\grave{","\\check{","\\bf{","\\it{","\\mbox{"}; // check for }
2359 const Char_t *kWord2[] = {"#scale[","#color[","#url[","#font[","#sqrt[","#kern[","#lower[","\\scale[","\\color[","\\font[","\\sqrt[","\\kern[","\\lower["}; // check for ]{ + }
2360 const Char_t *kWord3[] = {"#frac{","\\frac{","#splitline{","\\splitline{"}; // check for }{ then }
2361 const Char_t *kLeft1[] = {"#left[","\\left[","#left{","\\left{","#left|","\\left|","#left(","\\left("};
2362 const Char_t *kLeft2[] = {"#[]{","#[]{","#{}{","#{}{","#||{","#||{","#(){","#(){"};
2363 const Char_t *kRight[] = {"#right]","\\right]","#right}","\\right}","#right|","\\right|","#right)","\\right)"};
2364 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};
2365 const Int_t lkWord2[] = {7,7,5,6,6,6,7,7,7,6,6,6,7} ;
2366 const Int_t lkWord3[] = {6,6,11,11} ;
2367 Int_t nkWord1 = 45, nkWord2 = 13, nkWord3 = 4;
2368 Int_t i,k ;
2370 Int_t lLeft1 = 6 ;
2371 Int_t lLeft2 = 4 ;
2372 Int_t lRight = 7 ;
2373 nLeft1 = nRight = 8 ;
2374 nOfLeft = nOfRight = 0 ;
2375
2376 Char_t buf[11] ; for (i=0;i<11;i++) buf[i]=0;
2377 Bool_t opFound ;
2378 Int_t opFrac = 0;
2379 Int_t length = text.Length() ;
2380
2383 Int_t error = 0 ;
2385
2386 // first find and replace all occurrences of "kLeft1" keyword by "kLeft2" keyword,
2387 // and all occurrences of "kRight" keyword by "}".
2388 i = 0 ;
2389 while (i < length) {
2390 // The string in 'buf' does not need to be null terminated,
2391 // we will only check with strncmp.
2392 strncpy(buf,&text[i],TMath::Min(7,length-i));
2393 opFound = kFALSE ;
2394 for (k = 0 ; k < nLeft1 ; k++) {
2395 if (strncmp(buf,kLeft1[k],lLeft1)==0) {
2396 nOfLeft++ ;
2397 i+=lLeft1 ;
2398 opFound = kTRUE ;
2399 break ;
2400 }
2401 }
2402 if (opFound) continue ;
2403
2404 for(k=0;k<nRight;k++) {
2405 if (strncmp(buf,kRight[k],lRight)==0) {
2406 nOfRight++ ;
2407 i+=lRight ;
2408 opFound = kTRUE ;
2409 break ;
2410 }
2411 }
2412 if (!opFound) i++ ;
2413 }
2414 if (nOfLeft != nOfRight) {
2415 printf(" nOfLeft = %d, nOfRight = %d\n",nOfLeft,nOfRight) ;
2416 error = 1 ;
2417 fError = "Operators \"#left\" and \"#right\" don't match !" ;
2418 goto ERROR_END ;
2419 }
2420
2421 for (k = 0 ; k < nLeft1 ; k++) {
2422 text.ReplaceAll(kLeft1[k],lLeft1,kLeft2[k],lLeft2) ;
2423 }
2424 for (k = 0 ; k < nRight ; k++) {
2425 text.ReplaceAll(kRight[k],lRight,"}",1) ;
2426 }
2427 length = text.Length() ;
2428
2430 while (i< length){
2431 switch (text[i]) {
2432 case '"' : quote1 = !quote1 ; break ;
2433 case '\'': quote2 = !quote2 ; break ;
2434 }
2435 // The string in 'buf' does not need to be null terminated,
2436 // we will only check with strncmp
2437 strncpy(buf,&text[i],TMath::Min(11,length-i));
2438 opFound = kFALSE ;
2439
2440 for(k=0;k<nkWord1;k++) {
2441 if (strncmp(buf,kWord1[k],lkWord1[k])==0) {
2442 nOfKW1++ ;
2443 i+=lkWord1[k] ;
2444 opFound = kTRUE ;
2445 nOfCurlyBracket++ ;
2446 break ;
2447 }
2448 }
2449 if (opFound) continue ;
2450
2451 for(k=0;k<nkWord2;k++) {
2452 if (strncmp(buf,kWord2[k],lkWord2[k])==0) {
2453 nOfKW2++ ;
2454 i+=lkWord2[k] ;
2455 opFound = kTRUE ;
2457 break ;
2458 }
2459 }
2460 if (opFound) continue ;
2461
2462 for(k=0;k<nkWord3;k++) {
2463 if (strncmp(buf,kWord3[k],lkWord3[k])==0) {
2464 nOfKW3++ ;
2465 i+=lkWord3[k] ;
2466 opFound = kTRUE ;
2467 opFrac++ ;
2468 nOfCurlyBracket++ ;
2469 break ;
2470 }
2471 }
2472 if (opFound) continue ;
2473 if (strncmp(buf,"}{",2) == 0 && opFrac) {
2474 opFrac-- ;
2475 nOfCurlyCurly++ ;
2476 i+= 2;
2477 }
2478 else if (strncmp(buf,"]{",2) == 0 && nOfSquareBracket) {
2479 nOfSquareCurly++ ;
2480 i+= 2 ;
2481 nOfCurlyBracket++ ;
2483 }
2484 else if (strncmp(buf,"@{",2) == 0 || strncmp(buf,"@}",2) == 0) {
2485 i+= 2 ;
2486 }
2487 else if (strncmp(buf,"@[",2) == 0 || strncmp(buf,"@]",2) == 0) {
2488 i+= 2 ;
2489 }
2490 else if (text[i] == ']' ) { // not belonging to a key word, add @ in front
2491 text.Insert(i,"@") ;
2492 length++ ;
2493 i+=2 ;
2494 }
2495 else if (text[i] == '[' ) { // not belonging to a key word, add @ in front
2496 text.Insert(i,"@") ;
2497 length++ ;
2498 i+=2 ;
2499 }
2500 else if (text[i] == '{' ) { // not belonging to a key word, add @ in front
2501 text.Insert(i,"@") ;
2502 length++ ;
2503 i+=2 ;
2504 }
2505 else if (text[i] == '}' ) {
2506 if ( nOfCurlyBracket) {
2507 nOfCurlyBracket-- ;
2508 i++ ;
2509 } else { // extra }, add @ in front
2510 text.Insert(i,"@") ;
2511 length++ ;
2512 i+=2 ;
2513 }
2514 } else {
2515 i++ ;
2516 buf[1] = 0 ;
2517 }
2518 }
2519
2520 if (nOfKW2 != nOfSquareCurly) {
2521 error = 1 ;
2522 fError = "Invalid number of \"]{\"" ;
2523 }
2524 else if (nOfKW3 != nOfCurlyCurly) {
2525 error = 1 ;
2526 fError = "Error in syntax of \"#frac\"" ;
2527 }
2528 else if (nOfCurlyBracket < 0) {
2529 error = 1 ;
2530 fError = "Missing \"{\"" ;
2531 }
2532 else if (nOfCurlyBracket > 0) {
2533 error = 1 ;
2534 fError = "Missing \"}\"" ;
2535 }
2536 else if (nOfSquareBracket < 0) {
2537 error = 1 ;
2538 fError = "Missing \"[\"" ;
2539 }
2540 else if (nOfSquareBracket > 0) {
2541 error = 1 ;
2542 fError = "Missing \"]\"" ;
2543 }
2544
2545 ERROR_END:
2546 return error ;
2547}
2548
2549////////////////////////////////////////////////////////////////////////////////
2550/// First parsing of the analyse sequence
2551
2553{
2554 fTabSize.reserve(100); // ensure 100 entries before memory reallocation required
2555 fShow = kFALSE;
2556 fOriginSize = size;
2557
2558 //get current line attributes
2561
2563 spec.fAngle = angle;
2564 spec.fSize = GetTextSizePercent(size);
2565 spec.fColor = GetTextColor();
2566 spec.fFont = GetTextFont();
2569
2571
2574 SetTextFont(spec.fFont);
2575 SetTextColor(spec.fColor);
2579 return fs;
2580}
2581
2582////////////////////////////////////////////////////////////////////////////////
2583/// Return height of current pad in pixels
2584
2586{
2587 if (!gPad) return 0.;
2588 Double_t w = gPad->GetAbsWNDC()*Double_t(gPad->GetWw());
2589 Double_t h = gPad->GetAbsHNDC()*Double_t(gPad->GetWh());
2590 if (w < h)
2591 return w;
2592 else
2593 return h;
2594}
2595
2596////////////////////////////////////////////////////////////////////////////////
2597/// Return size of the formula along X in pad coordinates when the text precision
2598/// is smaller than 3.
2599
2601{
2602 if (!gPad) return 0.;
2604 if( newText.Length() == 0) return 0;
2605
2606 // The text is a TMathText.
2607 if ( newText.Contains("\\") ) {
2608 TMathText tm(0., 0., newText.Data());
2609 return tm.GetXsize();
2610 }
2611
2612 fError = nullptr;
2614 Error("GetXsize", "%s\n==> %s", fError, GetTitle());
2615 return 0;
2616 }
2617 fError = nullptr;
2618
2619 const Char_t *text = newText.Data() ;
2623 fTabSize.clear();
2624 return std::abs(gPad->AbsPixeltoX(fs.Width()) - gPad->AbsPixeltoX(0));
2625}
2626
2627////////////////////////////////////////////////////////////////////////////////
2628/// Return text size in pixels
2629
2631{
2632 if (!gPad) return;
2634 if( newText.Length() == 0) return;
2635
2636 // The text is a TMathText.
2637 if ( newText.Contains("\\") ) {
2638 TMathText tm(0., 0., newText.Data());
2639 tm.GetBoundingBox(w, h);
2640 return;
2641 }
2642
2643 fError = nullptr;
2645 Error("GetBoundingBox", "%s\n==> %s", fError, GetTitle());
2646 return;
2647 }
2648 fError = nullptr;
2649
2650 if (angle) {
2651 Int_t cBoxX[4], cBoxY[4];
2652 Int_t ptx, pty;
2653 if (TestBit(kTextNDC)) {
2654 ptx = gPad->UtoPixel(fX);
2655 pty = gPad->VtoPixel(fY);
2656 } else {
2657 ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX));
2658 pty = gPad->YtoAbsPixel(gPad->YtoPad(fY));
2659 }
2661 Int_t x1 = cBoxX[0];
2662 Int_t x2 = cBoxX[0];
2663 Int_t y1 = cBoxY[0];
2664 Int_t y2 = cBoxY[0];
2665 for (Int_t i=1; i<4; i++) {
2666 if (cBoxX[i] < x1) x1 = cBoxX[i];
2667 if (cBoxX[i] > x2) x2 = cBoxX[i];
2668 if (cBoxY[i] < y1) y1 = cBoxY[i];
2669 if (cBoxY[i] > y2) y2 = cBoxY[i];
2670 }
2671 w = x2-x1;
2672 h = y2-y1;
2673 } else {
2674 const Char_t *text = newText.Data() ;
2676 fTabSize.clear();
2677 w = (UInt_t)fs.Width();
2678 h = (UInt_t)fs.Height();
2679 }
2680}
2681
2682////////////////////////////////////////////////////////////////////////////////
2683/// Return size of the formula along Y in pad coordinates when the text precision
2684/// is smaller than 3.
2685
2687{
2688 if (!gPad) return 0.;
2690 if( newText.Length() == 0) return 0;
2691
2692 // The text is a TMathText.
2693 if ( newText.Contains("\\") ) {
2694 TMathText tm(0., 0., newText.Data());
2695 return tm.GetYsize();
2696 }
2697
2698 fError = nullptr;
2700 Error("GetYsize", "%s\n==> %s", fError, GetTitle());
2701 return 0;
2702 }
2703 fError = nullptr;
2704
2705 const Char_t *text = newText.Data();
2709 fTabSize.clear();
2710 return std::abs(gPad->AbsPixeltoY(fs.Height()) - gPad->AbsPixeltoY(0));
2711}
2712
2713////////////////////////////////////////////////////////////////////////////////
2714/// Read fs in fTabSize
2715
2717{
2718 if (fTabSize.empty()) {
2719 Error("Readfs", "No data in fTabSize stack");
2720 return TLatexFormSize(0,0,0);
2721 }
2722
2724 fTabSize.pop_back();
2725 return result;
2726}
2727
2728////////////////////////////////////////////////////////////////////////////////
2729/// Save fs values in array fTabSize
2730
2732{
2733 fTabSize.emplace_back(*fs);
2734}
2735
2736////////////////////////////////////////////////////////////////////////////////
2737/// Save primitive as a C++ statement(s) on output stream out
2738
2739void TLatex::SavePrimitive(std::ostream &out, Option_t *option)
2740{
2742 out, Class(), "tex",
2743 TString::Format("%g, %g, \"%s\"", fX, fY, TString(GetTitle()).ReplaceSpecialCppChars().Data()), kFALSE);
2744
2745 SaveTextAttributes(out, "tex", 11, 0, 1, 62, 0.05);
2746 SaveLineAttributes(out, "tex", 1, 1, 1);
2747
2748 if (TestBit(kTextNDC))
2749 out << " tex->SetNDC();\n";
2750
2751 SavePrimitiveDraw(out, "tex", option);
2752}
2753
2754////////////////////////////////////////////////////////////////////////////////
2755/// Set relative size of subscripts and superscripts
2756
2758{
2760}
2761
2762////////////////////////////////////////////////////////////////////////////////
2763/// Set limit for text resizing of subscripts and superscripts
2764
2766{
2768}
#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
R__EXTERN TVirtualPS * gVirtualPS
Definition TVirtualPS.h:84
#define gPad
#define gVirtualX
Definition TVirtualX.h:338
const char * tab3
const char * tab2
#define snprintf
Definition civetweb.c:1579
Fill Area Attributes class.
Definition TAttFill.h:20
Line Attributes class.
Definition TAttLine.h:20
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:35
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:37
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:274
virtual Float_t GetTextSize() const
Return the text size.
Definition TAttText.h:38
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:44
virtual Short_t GetTextAlign() const
Return the text alignment.
Definition TAttText.h:34
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:37
Float_t fTextAngle
Text angle.
Definition TAttText.h:23
virtual Color_t GetTextColor() const
Return the text color.
Definition TAttText.h:36
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:45
virtual Float_t GetTextAngle() const
Return the text angle.
Definition TAttText.h:35
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:46
Font_t fTextFont
Text font.
Definition TAttText.h:27
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:370
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:25
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:2763
Double_t GetXsize()
Return size of the formula along X in pad coordinates when the text precision is smaller than 3.
Definition TLatex.cxx:2598
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:505
Double_t GetHeight() const
Return height of current pad in pixels.
Definition TLatex.cxx:2583
void Copy(TObject &text) const override
Copy this TLatex object to another TLatex.
Definition TLatex.cxx:488
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:2050
TLatexFormSize Anal1(const TextSpec_t &spec, const Char_t *t, Int_t length)
Analyse function.
Definition TLatex.cxx:535
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:2091
static TClass * Class()
virtual void SetIndiceSize(Double_t factorSize)
Set relative size of subscripts and superscripts.
Definition TLatex.cxx:2755
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:2237
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:2684
TLatexFormSize FirstParse(Double_t angle, Double_t size, const Char_t *text)
First parsing of the analyse sequence.
Definition TLatex.cxx:2550
TLatexFormSize Readfs()
Read fs in fTabSize.
Definition TLatex.cxx:2714
void GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle=kFALSE) override
Return text size in pixels.
Definition TLatex.cxx:2628
@ 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:2005
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:2064
virtual void PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Main drawing function.
Definition TLatex.cxx:2144
TLatex()
Default constructor.
Definition TLatex.cxx:415
Bool_t fShow
! is true during the second pass (Painting)
Definition TLatex.h:68
~TLatex() override
Destructor.
Definition TLatex.cxx:446
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitive as a C++ statement(s) on output stream out.
Definition TLatex.cxx:2737
TLatex & operator=(const TLatex &)
assignment operator
Definition TLatex.cxx:468
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:2018
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:1991
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:2122
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:567
Int_t CheckLatexSyntax(TString &text)
Check if the Latex syntax is correct.
Definition TLatex.cxx:2351
void Savefs(TLatexFormSize *fs)
Save fs values in array fTabSize.
Definition TLatex.cxx:2729
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 Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:544
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1089
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:840
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:772
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:70
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
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition TVirtualPS.h:30
virtual void Text(Double_t x, Double_t y, const char *string)=0
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