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