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