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