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