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