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