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