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