// @(#)root/graf:$Id$ // Author: Nicolas Brun, Olivier Couet, Oleksandr Grebenyuk /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #include "Riostream.h" #include "TROOT.h" #include "TClass.h" #include "TLatex.h" #include "TMathText.h" #include "TMath.h" #include "TVirtualPad.h" #include "TVirtualPS.h" const Double_t kPI = TMath::Pi(); ClassImp(TLatex) //______________________________________________________________________________ /* Begin_Html

TLatex : to draw Mathematical Formula

TLatex's purpose is to write mathematical equations. The syntax is very similar to Latex's. It provides several functionalities: When the font precision (see TAttText) is low (0 or 1), TLatex is painted as a normal TText, the control characters are not interpreted.

Subscripts and Superscripts

Subscripts and superscripts are made with the _ and ^ commands. These commands can be combined to make complicated subscript and superscript expressions. You may adjust the display of subscripts and superscripts by using the two functions SetIndiceSize(Double_t), which set relative size of subscripts and superscripts, and SetLimitIndiceSize(Int_t), which set limits for text resizing of subscipts and superscripts.

Examples: End_Html x^{2y} : Begin_Latex x^{2y} End_Latex x_{2y} : Begin_Latex x_{2y} End_Latex x^{y^{2}} : Begin_Latex x^{y^{2}} End_Latex x^{y_{1}} : Begin_Latex x^{y_{1}} End_Latex x^{y}_{1} : Begin_Latex x^{y}_{1} End_Latex x_{1}^{y} : Begin_Latex x_{1}^{y} End_Latex Begin_Html The best way to put the subscipts and superscripts before the character and not after, is to use an empty character: End_Html {}^{40}_{20}Ca : Begin_Latex {}^{40}_{20}Ca End_Latex Begin_Html The subscripts and superscripts operators apply not only on one character but on all the "normal text" preceding them. In the following example the second E is lower than the first one because the operator _ is applied on /f which has a descending part, and not only on f which as no descending part. End_Html f_{E}/f_{E} : Begin_Latex f_{E}/f_{E} End_Latex Begin_Html To make sure the second operator _ applies only on f a dummy operator ^{} should be introduced to separate the f from the /. End_Html f_{E}/^{}f_{E} : Begin_Latex f_{E}/^{}f_{E} End_Latex Begin_Html

Fractions

Fractions denoted by the / symbol are made in the obvious way. The #frac command is used for large fractions in displayed formula; it has two arguments: the numerator and the denominator.

Examples: End_Html x = #frac{y+z/2}{y^{2}+1} : Begin_Latex x = #frac{y+z/2}{y^{2}+1} End_Latex Begin_Html

Splitting Lines

Text can be split in two lines via the command #splitline.

Examples: End_Html #splitline{21 April 2003}{14:02:30} : Begin_Latex #splitline{21 April 2003}{14:02:30} End_Latex Begin_Html

Roots

The #sqrt command produces the square root of its argument; it has an optional first argument for other roots.

Examples: End_Html #sqrt{10} : Begin_Latex #sqrt{10} End_Latex #sqrt[3]{10} : Begin_Latex #sqrt[3]{10} End_Latex Begin_Html

Mathematical Symbols

TLatex can display dozens of special mathematical symbols. A few of them, such as + and > , are produced by typing the corresponding keyboard character. Others are obtained with the commands in the following table: End_Html Begin_Macro(source) mathsymbols.C End_Macro Begin_Html

Delimiters

TLatex provides 4 kinds of proportional delimiters:
   #[]{....} or "a la" Latex #left[.....#right] : big square brackets
   #{}{....} or              #left{.....#right} : big curly brackets
   #||{....} or              #left|.....#right| : big absolute value symbols
   #(){....} or              #left(.....#right) : big parentheses

Greek Letters

The command to produce a lowercase Greek letter is obtained by adding a # to the name of the letter. For an uppercase Greek letter, just capitalize the first letter of the command name. Some letters have two representations. The name of the second one (the "variation") starts with "var". The following table gives the complete list: End_Html Begin_Macro(source) greekletters.C End_Macro Begin_Html

Accents

Several kind of accents are available: End_Html #hat = Begin_Latex #hat{a} End_Latex #check = Begin_Latex #check{a} End_Latex #acute = Begin_Latex #acute{a} End_Latex #grave = Begin_Latex #grave{a} End_Latex #dot = Begin_Latex #dot{a} End_Latex #ddot = Begin_Latex #ddot{a} End_Latex #tilde = Begin_Latex #tilde{a} End_Latex Begin_Html The special sign: #slash draws a slash on top of the text between brackets: End_Html #slash{E}_{T} : Begin_Latex #slash{E}_{T} End_Latex Begin_Html Bar and vectors sign are done the following way: End_Html #bar{a}: Begin_Latex #bar{a} End_Latex #vec{a}: Begin_Latex #vec{a} End_Latex Begin_Html

Changing Style

One can change the font, the text color, or the text size at any time using : #font[font-number]{...}, #color[color-number]{...} and #scale[scale-factor]{...}

Examples: End_Html #font[12]{Times Italic} and #font[22]{Times bold} : Begin_Latex #font[12]{Times Italic} and #font[22]{Times bold} End_Latex #color[2]{Red} and #color[4]{Blue} : Begin_Latex #color[2]{Red} and #color[4]{Blue} End_Latex #scale[1.2]{Bigger} and #scale[0.8]{Smaller} : Begin_Latex #scale[1.2]{Bigger} and #scale[0.8]{Smaller} End_Latex Begin_Html

Alignment Rules

The TText alignment rules apply to the TLatex objects with one exception concerning the vertical alignment: This is illustrated by the following example: End_Html Begin_Macro(source) { TCanvas Tlva("Tlva","Tlva",500,500); Tlva.SetGrid(); Tlva.DrawFrame(0,0,1,1); 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)"; TLatex latex; latex.SetTextSize(0.025); latex.SetTextAlign(13); //align at top latex.DrawLatex(.2,.9,"K_{S}"); latex.DrawLatex(.3,.9,"K^{*0}"); latex.DrawLatex(.2,.8,longstring); latex.SetTextAlign(12); //centered latex.DrawLatex(.2,.6,"K_{S}"); latex.DrawLatex(.3,.6,"K^{*0}"); latex.DrawLatex(.2,.5,longstring); latex.SetTextAlign(11); //default bottom alignment latex.DrawLatex(.2,.4,"K_{S}"); latex.DrawLatex(.3,.4,"K^{*0}"); latex.DrawLatex(.2,.3,longstring); latex.SetTextAlign(10); //special bottom alignment latex.DrawLatex(.2,.2,"K_{S}"); latex.DrawLatex(.3,.2,"K^{*0}"); latex.DrawLatex(.2,.1,longstring); latex.SetTextAlign(12); latex->SetTextFont(72); latex->DrawLatex(.1,.80,"13"); latex->DrawLatex(.1,.55,"12"); latex->DrawLatex(.1,.35,"11"); latex->DrawLatex(.1,.18,"10"); return Tlva; } End_Macro Begin_Html

Character Adjustement

The two commands #kern and #lower enable a better control over character placement. The command #kern[(Float_t)dx]{text} moves the output string horizontally by the fraction dx of its length. Similarly, #lower[(Float_t)dy]{text} shifts the text up or down by the fraction dy of its height.

Examples: End_Html 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}: Begin_Latex 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} End_Latex 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}: Begin_Latex 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} End_Latex 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: Begin_Latex 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 End_Latex Begin_Html

Italic and Boldface

Text can be turned italic or boldface using the commands #it and #bf.

Examples: End_Html #bf{bold}, #it{italic}, #bf{#it{bold italic}}, #bf{#bf{unbold}}}: Begin_Latex #bf{bold}, #it{italic}, #bf{#it{bold italic}}, #bf{#bf{unbold}} End_Latex abc#alpha#beta#gamma, #it{abc#alpha#beta#gamma}: Begin_Latex abc#alpha#beta#gamma, #it{abc#alpha#beta#gamma} End_Latex Begin_Html

Examples

End_Html Begin_Macro(source) { TCanvas ex1("ex1","Latex",500,600); TLatex Tl; Tl.SetTextAlign(12); Tl.SetTextSize(0.04); Tl.DrawLatex(0.1,0.8,"1) C(x) = d #sqrt{#frac{2}{#lambdaD}} #int^{x}_{0}cos(#frac{#pi}{2}t^{2})dt"); Tl.DrawLatex(0.1,0.6,"2) C(x) = d #sqrt{#frac{2}{#lambdaD}} #int^{x}cos(#frac{#pi}{2}t^{2})dt"); 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})"); Tl.DrawLatex(0.1,0.2,"4) F(t) = #sum_{i=-#infty}^{#infty}A(i)cos#[]{#frac{i}{t+i}}"); return ex1; } End_Macro Begin_Macro(source) { TCanvas ex2("ex2","Latex",500,300); TLatex Tl; Tl.SetTextAlign(23); Tl.SetTextSize(0.08); Tl.DrawLatex(0.5,0.95,"e^{+}e^{-}#rightarrowZ^{0}#rightarrowI#bar{I}, q#bar{q}"); Tl.DrawLatex(0.5,0.75,"|#vec{a}#bullet#vec{b}|=#Sigmaa^{i}_{jk}+b^{bj}_{i}"); Tl.DrawLatex(0.5,0.5,"i(#partial_{#mu}#bar{#psi}#gamma^{#mu}+m#bar{#psi}=0#Leftrightarrow(#Box+m^{2})#psi=0"); 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}"); return ex2; } End_Macro Begin_Macro(source) { TCanvas ex3("ex3","Latex",500,300); TPaveText pt(.1,.1,.9,.9); pt.AddText("#frac{2s}{#pi#alpha^{2}} #frac{d#sigma}{dcos#theta} (e^{+}e^{-} #rightarrow f#bar{f} ) = "); pt.AddText("#left| #frac{1}{1 - #Delta#alpha} #right|^{2} (1+cos^{2}#theta"); 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}"); pt.SetLabel("Born equation"); pt.Draw(); return ex3; } End_Macro Begin_Html

Interface to TMathText

The class TMathText is a TeX math formulae interpreter. It uses plain TeX syntax and uses "\" as control instead of "#". If a piece of text containing "\" is given to TLatex then TMathText is automatically invoked. Therefore, as histograms' titles, axis titles, labels etc ... are drawn using TLatex, the TMathText syntax can be used for them also. End_Html */ //______________________________________________________________________________ TLatex::TLatex() { // Default constructor. fFactorSize = 1.5; fFactorPos = 0.6; fError = 0; fShow = kFALSE; fPos = 0; fTabMax = 0; fOriginSize = 0.04; fTabSize = 0; fItalic = kFALSE; fLimitFactorSize = 3; SetLineWidth(2); } //______________________________________________________________________________ TLatex::TLatex(Double_t x, Double_t y, const char *text) :TText(x,y,text) { // Normal constructor. fFactorSize = 1.5; fFactorPos = 0.6; fError = 0; fShow = kFALSE; fPos = 0; fTabMax = 0; fOriginSize = 0.04; fTabSize = 0; fItalic = kFALSE; fLimitFactorSize = 3; SetLineWidth(2); } //______________________________________________________________________________ TLatex::~TLatex() { // Destructor. } //______________________________________________________________________________ TLatex::TLatex(const TLatex &text) : TText(text), TAttLine(text) { // Copy constructor. fFactorSize = 1.5; fFactorPos = 0.6; fError = 0; fShow = kFALSE; fPos = 0; fTabMax = 0; fOriginSize = 0.04; fTabSize = 0; fItalic = kFALSE; fLimitFactorSize = 3; ((TLatex&)text).Copy(*this); } //______________________________________________________________________________ TLatex& TLatex::operator=(const TLatex& lt) { //assignment operator if(this!=<) { TText::operator=(lt); TAttLine::operator=(lt); fFactorSize=lt.fFactorSize; fFactorPos=lt.fFactorPos; fLimitFactorSize=lt.fLimitFactorSize; fError=lt.fError; fShow=lt.fShow; fTabSize=lt.fTabSize; fOriginSize=lt.fOriginSize; fTabSize=lt.fTabSize; fTabSize=lt.fTabSize; fItalic=lt.fItalic; } return *this; } //______________________________________________________________________________ void TLatex::Copy(TObject &obj) const { // Copy this TLatex object to another TLatex. ((TLatex&)obj).fFactorSize = fFactorSize; ((TLatex&)obj).fFactorPos = fFactorPos; ((TLatex&)obj).fLimitFactorSize = fLimitFactorSize; ((TLatex&)obj).fError = fError; ((TLatex&)obj).fShow = fShow; ((TLatex&)obj).fTabSize = 0; ((TLatex&)obj).fOriginSize = fOriginSize; ((TLatex&)obj).fTabMax = fTabMax; ((TLatex&)obj).fPos = fPos; ((TLatex&)obj).fItalic = fItalic; TText::Copy(obj); TAttLine::Copy(((TAttLine&)obj)); } //______________________________________________________________________________ TLatexFormSize TLatex::Anal1(TextSpec_t spec, const Char_t* t, Int_t length) { // Analyse function. return Analyse(0,0,spec,t,length); } //______________________________________________________________________________ TLatexFormSize TLatex::Analyse(Double_t x, Double_t y, TextSpec_t spec, const Char_t* t, Int_t length) { // Analyse and paint the TLatex formula // // It is called twice : first for calculating the size of // each portion of the formula, then to paint the formula. // When analyse finds an operator or separator, it calls // itself recursively to analyse the arguments of the operator. // when the argument is an atom (normal text), it calculates // the size of it and return it as the result. // for example : if the operator #frac{arg1}{arg2} is found : // Analyse(arg1) return the size of arg1 (width, up, down) // Analyse(arg2) return the size of arg2 // now, we know the size of #frac{arg1}{arg2} : // width = max(width_arg1, width_arg2) // up = up_arg1 + down_arg1 // down = up_arg2 + down_arg2 // so, when the user wants to paint a fraction at position (x,y), // the rect used for the formula is : (x,y-up,x+width,y+down) // // return size of zone occupied by the text/formula // t : chain to be analyzed // length : number of chars in t. const char *tab[] = { "alpha","beta","chi","delta","varepsilon","phi","gamma","eta","iota","varphi","kappa","lambda", "mu","nu","omicron","pi","theta","rho","sigma","tau","upsilon","varomega","omega","xi","psi","zeta", "Alpha","Beta","Chi","Delta","Epsilon","Phi","Gamma","Eta","Iota","vartheta", "Kappa","Lambda","Mu","Nu","Omicron","Pi","Theta","Rho","Sigma","Tau", "Upsilon","varsigma","Omega","Xi","Psi","Zeta","varUpsilon","epsilon"}; const char *tab2[] = { "leq","/","infty","voidb","club","diamond","heart", "spade","leftrightarrow","leftarrow","uparrow","rightarrow", "downarrow","circ","pm","doublequote","geq","times","propto", "partial","bullet","divide","neq","equiv","approx","3dots", "cbar","topbar","downleftarrow","aleph","Jgothic","Rgothic","voidn", "otimes","oplus","oslash","cap","cup","supset","supseteq", "notsubset","subset","subseteq","in","notin","angle","nabla", "oright","ocopyright","trademark","prod","surd","upoint","corner","wedge", "vee","Leftrightarrow","Leftarrow","Uparrow","Rightarrow", "Downarrow","diamond","LT","void1","copyright","void3","sum", "arctop","lbar","arcbottom","topbar","void8", "bottombar","arcbar", "ltbar","AA","aa","void06","GT","int","forall","exists" }; const char *tab3[] = { "bar","vec","dot","hat","ddot","acute","grave","check","tilde","slash"}; if (fError != 0) return TLatexFormSize(0,0,0); Int_t nBlancDeb=0,nBlancFin=0,l_nBlancDeb=0,l_nBlancFin=0; Int_t i,k; Int_t min=0, max=0; Bool_t cont = kTRUE; while(cont) { // count leading blanks //while(nBlancDeb+nBlancFin0 && t[i-1] == '@')) nBrackets++; if (t[i] == '}' && t[i-1]!= '@') nBrackets--; if (nBrackets==0 && i0 && text[i-1] == '@')) nBrackets++; } break; case '}': if (nCroch==0) { if (!(i>0 && text[i-1] == '@')) nBrackets--; if (nBrackets==0) { if (i0 && text[i-1] == '@')) nCroch++; } break; case ']': if (nBrackets==0) { if (!(i>0 && text[i-1] == '@')) nCroch--; if (nCroch<0) { // more "]" than "[" fError = "Missing \"[\""; delete [] text; return TLatexFormSize(0,0,0); } } break; } if (length>i+1) { Char_t buf[3]; strncpy(buf,&text[i],2); if (strncmp(buf,"^{",2)==0) { if (opPower==-1 && nBrackets==0 && nCroch==0) opPower=i; if (i>3) { Char_t buf1[5]; strncpy(buf1,&text[i-4],4); if (strncmp(buf1,"#int",4)==0) { abovePlace = 1; if (i>4 && opCloseCurly==-2) opCloseCurly=i-5; } if (strncmp(buf1,"#sum",4)==0) { abovePlace = 2; if (i>4 && opCloseCurly==-2) opCloseCurly=i-5; } } } if (strncmp(buf,"_{",2)==0) { if (opUnder==-1 && nBrackets==0 && nCroch==0) opUnder=i; if (i>3) { Char_t buf2[5]; strncpy(buf2,&text[i-4],4); if (strncmp(buf2,"#int",4)==0) { abovePlace = 1; if (i>4 && opCloseCurly==-2) opCloseCurly=i-5; } if (strncmp(buf2,"#sum",4)==0) { abovePlace = 2; if (i>4 && opCloseCurly==-2) opCloseCurly=i-5; } } } if (strncmp(buf,"]{",2)==0) if (opSquareCurly==-1 && nBrackets==0 && nCroch==0) opSquareCurly=i; } // detect other operators if (text[i]=='\\' || (text[i]=='#' && !opFound && nBrackets==0 && nCroch==0)) { if (length>i+10) { Char_t buf[11]; strncpy(buf,&text[i+1],10); if (strncmp(buf,"splitline{",10)==0) { opSplitLine=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } } if (length>i+9) { Char_t buf[10]; strncpy(buf,&text[i+1],9); if (!opBackslash && strncmp(buf,"backslash",9)==0) { opBackslash=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } } if (length>i+8) { Char_t buf[9]; strncpy(buf,&text[i+1],8); if (!opParallel && strncmp(buf,"parallel",8)==0) { opParallel=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } } if (length>i+6) { Char_t buf[7]; strncpy(buf,&text[i+1],6); if (strncmp(buf,"lower[",6)==0 || strncmp(buf,"lower{",6)==0) { opLower=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue ; } if (strncmp(buf,"scale[",6)==0 || strncmp(buf,"scale{",6)==0) { opScale=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue ; } if (strncmp(buf,"color[",6)==0 || strncmp(buf,"color{",6)==0) { opColor=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue ; } } if (length>i+5) { Char_t buf[6]; strncpy(buf,&text[i+1],5); if (strncmp(buf,"frac{",5)==0) { opFrac=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (strncmp(buf,"sqrt{",5)==0 || strncmp(buf,"sqrt[",5)==0) { opSqrt=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (strncmp(buf,"font{",5)==0 || strncmp(buf,"font[",5)==0) { opFont=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (strncmp(buf,"kern[",5)==0 || strncmp(buf,"kern{",5)==0) { opKern=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue ; } if (!opMinus && strncmp(buf,"minus",5)==0) { opMinus=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (strncmp(buf,"mbox[",5)==0 || strncmp(buf,"mbox{",5)==0) { opMbox=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue ; } } if (length>i+4) { Char_t buf[5]; strncpy(buf,&text[i+1],4); if (!opOdot && strncmp(buf,"odot",4)==0) { opOdot=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (!opHbar && strncmp(buf,"hbar",4)==0) { opHbar=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (!opPerp && strncmp(buf,"perp",4)==0) { opPerp=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (!opPlus && strncmp(buf,"plus",4)==0) { opPlus=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } } if (length>i+3) { Char_t buf[4]; strncpy(buf,&text[i+1],3); buf[3] = 0; if (strncmp(buf,"[]{",3)==0) { opSquareBracket=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (strncmp(buf,"{}{",3)==0 ) { opBigCurly=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (strncmp(buf,"||{",3)==0) { opAbs=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (strncmp(buf,"(){",3)==0) { opParen=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (!opBox && strncmp(buf,"Box",3)==0) { opBox=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } if (strncmp(buf,"bf[",3)==0 || strncmp(buf,"bf{",3)==0) { opBf=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue ; } if (strncmp(buf,"it[",3)==0 || strncmp(buf,"it{",3)==0) { opIt=i; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue ; } } if (length>i+2) { Char_t buf[3]; strncpy(buf,&text[i+1],2); if (!opMp && strncmp(buf,"mp",2)==0) { opMp=1; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; continue; } } for(k=0;k<54;k++) { if (!opFound && UInt_t(length)>i+strlen(tab[k])) { if (strncmp(&text[i+1],tab[k],strlen(tab[k]))==0) { opGreek=k; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; } } } for(k=0;k<10;k++) { if (!opFound && UInt_t(length)>i+strlen(tab3[k])) { if (strncmp(&text[i+1],tab3[k],strlen(tab3[k]))==0) { opAbove=k; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; } } } UInt_t lastsize = 0; if (!opFound) for(k=0;k<82;k++) { if ((opSpec==-1 || strlen(tab2[k])>lastsize) && UInt_t(length)>i+strlen(tab2[k])) { if (strncmp(&text[i+1],tab2[k],strlen(tab2[k]))==0) { lastsize = strlen(tab2[k]); opSpec=k; opFound = kTRUE; if (i>0 && opCloseCurly==-2) opCloseCurly=i-1; } } } } } TLatexFormSize fs1; TLatexFormSize fs2; TLatexFormSize fs3; TLatexFormSize result; // analysis of operators found if (opCloseCurly>-1 && opCloseCurly-1 && opUnder>-1) { // ^ and _ found min = TMath::Min(opPower,opUnder); max = TMath::Max(opPower,opUnder); Double_t xfpos = 0. ; //GetHeight()*spec.fSize/5.; Double_t prop=1, propU=1; // scale factor for #sum & #int switch (abovePlace) { case 1 : prop = .8 ; propU = 1.75 ; // Int break; case 2: prop = .9 ; propU = 1.75 ; // Sum break; } // propU acts on upper number // when increasing propU value, the upper indice position is higher // when increasing prop values, the lower indice position is lower if (!fShow) { Int_t ltext = min ; if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) { // upper and lower indice before the character // like with chemical element snprintf(&text[ltext-2],length-(ltext-2),"I ") ; ltext-- ; } fs1 = Anal1(spec,text,ltext); fs2 = Anal1(specNewSize,text+min+1,max-min-1); fs3 = Anal1(specNewSize,text+max+1,length-max-1); Savefs(&fs1); Savefs(&fs2); Savefs(&fs3); } else { fs3 = Readfs(); fs2 = Readfs(); fs1 = Readfs(); Double_t pos = 0; if (!abovePlace) { Double_t addW = fs1.Width()+xfpos, addH1, addH2; if (opPower= 2 && strncmp(&text[min-2],"{}",2)==0) { snprintf(&text[min-2],length-(min-2)," ") ; Analyse(x+pos,y,spec,text,min-1); } else { Analyse(x+pos,y,spec,text,min); } } if (!abovePlace) { if (opPower-1) { // ^ found Double_t prop=1; Double_t xfpos = 0. ; //GetHeight()*spec.fSize/5. ; switch (abovePlace) { case 1 : //int prop = 1.75 ; break ; case 2 : // sum prop = 1.75; break ; } // When increasing prop, the upper indice position is higher if (!fShow) { Int_t ltext = opPower ; if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) { // upper and lower indice before the character // like with chemical element snprintf(&text[ltext-2],length-(ltext-2),"I ") ; ltext-- ; } fs1 = Anal1(spec,text,ltext); fs2 = Anal1(specNewSize,text+opPower+1,length-opPower-1); Savefs(&fs1); Savefs(&fs2); } else { fs2 = Readfs(); fs1 = Readfs(); Int_t pos = 0; if (!abovePlace){ Double_t over = fs1.Over(); if (over <= 0) over = 1.5*fs2.Over(); Analyse(x+fs1.Width()+xfpos,y-over*fFactorPos-fs2.Under(),specNewSize,text+opPower+1,length-opPower-1); } else { Int_t pos2=0; if (fs2.Width()>fs1.Width()) pos=Int_t((fs2.Width()-fs1.Width())/2); else pos2=Int_t((fs1.Width()-fs2.Width())/2); Analyse(x+pos2,y-fs1.Over()*prop-fs2.Under(),specNewSize,text+opPower+1,length-opPower-1); } if (opPower >= 2 && strncmp(&text[opPower-2],"{}",2)==0) { snprintf(&text[opPower-2],length-(opPower-2)," ") ; Analyse(x+pos,y,spec,text,opPower-1); } else { Analyse(x+pos,y,spec,text,opPower); } } if (!abovePlace) result.Set(fs1.Width()+xfpos+fs2.Width(), fs1.Over()*fFactorPos+fs2.Over(),fs1.Under()); else result.Set(TMath::Max(fs1.Width(),fs2.Width()),fs1.Over()*prop+fs2.Height(),fs1.Under()); } else if (opUnder>-1) { // _ found Double_t prop = .9; // scale factor for #sum & #frac Double_t xfpos = 0.;//GetHeight()*spec.fSize/5. ; Double_t fpos = fFactorPos ; // When increasing prop, the lower indice position is lower if(!fShow) { Int_t ltext = opUnder ; if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) { // upper and lower indice before the character // like with chemical element snprintf(&text[ltext-2],length-(ltext-2),"I ") ; ltext-- ; } fs1 = Anal1(spec,text,ltext); fs2 = Anal1(specNewSize,text+opUnder+1,length-opUnder-1); Savefs(&fs1); Savefs(&fs2); } else { fs2 = Readfs(); fs1 = Readfs(); Int_t pos = 0; if (!abovePlace) Analyse(x+fs1.Width()+xfpos,y+fs1.Under()+fs2.Over()*fpos,specNewSize,text+opUnder+1,length-opUnder-1); else { Int_t pos2=0; if (fs2.Width()>fs1.Width()) pos=Int_t((fs2.Width()-fs1.Width())/2); else pos2=Int_t((fs1.Width()-fs2.Width())/2); Analyse(x+pos2,y+fs1.Under()*prop+fs2.Over(),specNewSize,text+opUnder+1,length-opUnder-1); } if (opUnder >= 2 && strncmp(&text[opUnder-2],"{}",2)==0) { snprintf(&text[opUnder-2],length-(opUnder-2)," ") ; Analyse(x+pos,y,spec,text,opUnder-1); } else { Analyse(x+pos,y,spec,text,opUnder); } } if (!abovePlace) result.Set(fs1.Width()+xfpos+fs2.Width(),fs1.Over(), fs1.Under()+fs2.Under()+fs2.Over()*fpos); else result.Set(TMath::Max(fs1.Width(),fs2.Width()),fs1.Over(),fs1.Under()*prop+fs2.Height()); } else if (opBox) { Double_t square = GetHeight()*spec.fSize/2; if (!fShow) { fs1 = Anal1(spec,text+4,length-4); } else { fs1 = Analyse(x+square,y,spec,text+4,length-4); Double_t adjust = GetHeight()*spec.fSize/20; Double_t x1 = x+adjust ; Double_t x2 = x-adjust+square ; Double_t y1 = y; Double_t y2 = y-square+adjust; DrawLine(x1,y1,x2,y1,spec); DrawLine(x2,y1,x2,y2,spec); DrawLine(x2,y2,x1,y2,spec); DrawLine(x1,y2,x1,y1,spec); } result = fs1 + TLatexFormSize(square,square,0); } else if (opOdot) { Double_t square = GetHeight()*spec.fSize/2; if (!fShow) { fs1 = Anal1(spec,text+5,length-5); } else { fs1 = Analyse(x+1.3*square,y,spec,text+5,length-5); Double_t adjust = GetHeight()*spec.fSize/20; Double_t r1 = 0.62*square; Double_t y1 = y-0.3*square-adjust; DrawCircle(x+0.6*square,y1,r1,spec) ; DrawCircle(x+0.6*square,y1,r1/100,spec) ; } result = fs1 + TLatexFormSize(square,square,0); } else if (opHbar) { Double_t square = GetHeight()*spec.fSize/2; if (!fShow) { fs1 = Anal1(spec,text+5,length-5); } else { fs1 = Analyse(x+square,y,spec,text+5,length-5); TText hbar; hbar.SetTextFont(12); hbar.SetTextColor(spec.fColor); hbar.SetTextSize(spec.fSize); hbar.SetTextAngle(fTextAngle); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); Double_t angle = kPI*spec.fAngle/180.; Double_t xx = gPad->AbsPixeltoX(Int_t((x-xOrigin)*TMath::Cos(angle)+(y-yOrigin)*TMath::Sin(angle)+xOrigin)); Double_t yy = gPad->AbsPixeltoY(Int_t((x-xOrigin)*TMath::Sin(-angle)+(y-yOrigin)*TMath::Cos(angle)+yOrigin)); hbar.PaintText(xx,yy,"h"); DrawLine(x,y-0.8*square,x+0.75*square,y-square,spec); } result = fs1 + TLatexFormSize(square,square,0); } else if (opMinus) { Double_t square = GetHeight()*spec.fSize/2; if (!fShow) { fs1 = Anal1(spec,text+6,length-6); } else { fs1 = Analyse(x+square,y,spec,text+6,length-6); TText minus; minus.SetTextFont(122); minus.SetTextColor(spec.fColor); minus.SetTextSize(spec.fSize); minus.SetTextAngle(fTextAngle); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); Double_t angle = kPI*spec.fAngle/180.; Double_t xx = gPad->AbsPixeltoX(Int_t((x-xOrigin)*TMath::Cos(angle)+(y-yOrigin)*TMath::Sin(angle)+xOrigin)); Double_t yy = gPad->AbsPixeltoY(Int_t((x-xOrigin)*TMath::Sin(-angle)+(y-yOrigin)*TMath::Cos(angle)+yOrigin)); minus.PaintText(xx,yy,"-"); } result = fs1 + TLatexFormSize(square,square,0); } else if (opPlus) { Double_t square = GetHeight()*spec.fSize/2; if (!fShow) { fs1 = Anal1(spec,text+5,length-5); } else { fs1 = Analyse(x+square,y,spec,text+5,length-5); TText plus; plus.SetTextFont(122); plus.SetTextColor(spec.fColor); plus.SetTextSize(spec.fSize); plus.SetTextAngle(fTextAngle); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); Double_t angle = kPI*spec.fAngle/180.; Double_t xx = gPad->AbsPixeltoX(Int_t((x-xOrigin)*TMath::Cos(angle)+(y-yOrigin)*TMath::Sin(angle)+xOrigin)); Double_t yy = gPad->AbsPixeltoY(Int_t((x-xOrigin)*TMath::Sin(-angle)+(y-yOrigin)*TMath::Cos(angle)+yOrigin)); plus.PaintText(xx,yy,"+"); } result = fs1 + TLatexFormSize(square,square,0); } else if (opMp) { Double_t square = GetHeight()*spec.fSize/2; if (!fShow) { fs1 = Anal1(spec,text+3,length-3); } else { fs1 = Analyse(x+square,y,spec,text+3,length-3); TText mp; mp.SetTextFont(122); mp.SetTextColor(spec.fColor); mp.SetTextSize(spec.fSize); mp.SetTextAngle(fTextAngle+180); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); Double_t angle = kPI*spec.fAngle/180.; Double_t xx = gPad->AbsPixeltoX(Int_t((x+square-xOrigin)*TMath::Cos(angle)+(y-1.25*square-yOrigin)*TMath::Sin(angle)+xOrigin)); Double_t yy = gPad->AbsPixeltoY(Int_t((x+square-xOrigin)*TMath::Sin(-angle)+(y-1.25*square-yOrigin)*TMath::Cos(angle)+yOrigin)); mp.PaintText(xx,yy,"\261"); } result = fs1 + TLatexFormSize(square,square,0); } else if (opPerp) { Double_t square = GetHeight()*spec.fSize/1.4; if (!fShow) { fs1 = Anal1(spec,text+5,length-5); } else { fs1 = Analyse(x+0.5*square,y,spec,text+5,length-5); Double_t x0 = x + 0.50*square; Double_t x1 = x0 - 0.48*square; Double_t x2 = x0 + 0.48*square; Double_t y1 = y + 0.6*square; Double_t y2 = y1 - 1.3*square; DrawLine(x1,y1,x2,y1,spec); DrawLine(x0,y1,x0,y2,spec); } result = fs1; } else if (opBackslash) { Double_t square = GetHeight()*spec.fSize/2; if (!fShow) { fs1 = Anal1(spec,text+10,length-10); } else { fs1 = Analyse(x+square,y,spec,text+10,length-10); TText bs; bs.SetTextFont(GetTextFont()); bs.SetTextColor(spec.fColor); bs.SetTextSize(spec.fSize); bs.SetTextAngle(fTextAngle); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); Double_t angle = kPI*spec.fAngle/180.; Double_t xx = gPad->AbsPixeltoX(Int_t((x-xOrigin)*TMath::Cos(angle)+(y-yOrigin)*TMath::Sin(angle)+xOrigin)); Double_t yy = gPad->AbsPixeltoY(Int_t((x-xOrigin)*TMath::Sin(-angle)+(y-yOrigin)*TMath::Cos(angle)+yOrigin)); bs.PaintText(xx,yy,"\\"); } result = fs1 + TLatexFormSize(square,square,0); } else if (opParallel) { Double_t square = GetHeight()*spec.fSize/1.4; if (!fShow) { fs1 = Anal1(spec,text+9,length-9); } else { fs1 = Analyse(x+0.5*square,y,spec,text+9,length-9); Double_t x1 = x + 0.15*square; Double_t x2 = x + 0.45*square; Double_t y1 = y + 0.3*square; Double_t y2 = y1- 1.3*square; DrawLine(x1,y1,x1,y2,spec); DrawLine(x2,y1,x2,y2,spec); } result = fs1 + TLatexFormSize(square,square,0); } else if (opGreek>-1) { TextSpec_t newSpec = spec; newSpec.fFont = fItalic ? 152 : 122; char letter = 97 + opGreek; Double_t yoffset = 0.; // Greek letter too low if (opGreek>25) letter -= 58; if (opGreek == 52) letter = '\241'; //varUpsilon if (opGreek == 53) letter = '\316'; //epsilon if (!fShow) { fs1 = Anal1(newSpec,&letter,1); fs2 = Anal1(spec,text+strlen(tab[opGreek])+1,length-strlen(tab[opGreek])-1); Savefs(&fs1); } else { fs1 = Readfs(); Analyse(x+fs1.Width(),y,spec,text+strlen(tab[opGreek])+1,length-strlen(tab[opGreek])-1); Analyse(x,y-yoffset,newSpec,&letter,1); } fs1.AddOver(TLatexFormSize(0,yoffset,0)) ; result = fs1+fs2; } else if (opSpec>-1) { TextSpec_t newSpec = spec; newSpec.fFont = fItalic ? 152 : 122; char letter = '\243' + opSpec; if(opSpec == 75 || opSpec == 76) { newSpec.fFont = GetTextFont(); if (opSpec == 75) letter = '\305'; // AA Angstroem if (opSpec == 76) letter = '\345'; // aa Angstroem } if(opSpec == 80 || opSpec == 81) { if (opSpec == 80) letter = '\042'; // #forall if (opSpec == 81) letter = '\044'; // #exists } Double_t props, propi; props = 1.8 ; // scale factor for #sum(66) propi = 2.3 ; // scale factor for #int(79) if (opSpec==66 ) { newSpec.fSize = spec.fSize*props; } else if (opSpec==79) { newSpec.fSize = spec.fSize*propi; } if (!fShow) { fs1 = Anal1(newSpec,&letter,1); if (opSpec == 79 || opSpec == 66) fs1.Set(fs1.Width(),fs1.Over()*0.45,fs1.Over()*0.45); fs2 = Anal1(spec,text+strlen(tab2[opSpec])+1,length-strlen(tab2[opSpec])-1); Savefs(&fs1); } else { fs1 = Readfs(); Analyse(x+fs1.Width(),y,spec,text+strlen(tab2[opSpec])+1,length-strlen(tab2[opSpec])-1); if (opSpec!=66 && opSpec!=79) Analyse(x,y,newSpec,&letter,1); else { Analyse(x,y+fs1.Under()/2.,newSpec,&letter,1); } } result = fs1+fs2; } else if (opAbove>-1) { if (!fShow) { fs1 = Anal1(spec,text+strlen(tab3[opAbove])+1,length-strlen(tab3[opAbove])-1); Savefs(&fs1); } else { fs1 = Readfs(); Analyse(x,y,spec,text+strlen(tab3[opAbove])+1,length-strlen(tab3[opAbove])-1); Double_t sub = GetHeight()*spec.fSize/14; Double_t x1 , y1 , x2, y2, x3, x4; switch(opAbove) { case 0: // bar Double_t ypos ; ypos = y-fs1.Over()-sub ;//-GetHeight()*spec.fSize/4. ; DrawLine(x,ypos,x+fs1.Width(),ypos,spec); break; case 1: // vec Double_t y0 ; y0 = y-sub-fs1.Over() ; y1 = y0-GetHeight()*spec.fSize/8 ; x1 = x+fs1.Width() ; DrawLine(x,y1,x1,y1,spec); DrawLine(x1,y1,x1-GetHeight()*spec.fSize/4,y0-GetHeight()*spec.fSize/4,spec); DrawLine(x1,y1,x1-GetHeight()*spec.fSize/4,y0,spec); break; case 2: // dot x1 = x+fs1.Width()/2-3*sub/4 ; x2 = x+fs1.Width()/2+3*sub/4 ; y1 = y-sub-fs1.Over() ; DrawLine(x1,y1,x2,y1,spec); break; case 3: // hat x2 = x+fs1.Width()/2 ; y1 = y -9*sub; y2 = y1-2*sub; x1 = x2-fs1.Width()/3 ; x3 = x2+fs1.Width()/3 ; DrawLine(x1,y1,x2,y2,spec); DrawLine(x2,y2,x3,y1,spec); break; case 4: // ddot x1 = x+fs1.Width()/2-9*sub/4 ; x2 = x+fs1.Width()/2-3*sub/4 ; x3 = x+fs1.Width()/2+9*sub/4 ; x4 = x+fs1.Width()/2+3*sub/4 ; y1 = y-sub-fs1.Over() ; DrawLine(x1,y1,x2,y1,spec); DrawLine(x3,y1,x4,y1,spec); break; case 5: // acute x1 = x+fs1.Width()/2; y1 = y +sub -fs1.Over() ; x2 = x1 +3*sub; y2 = y1 -2.5*sub; DrawLine(x1,y1,x2,y2,spec); break; case 6: // grave x1 = x+fs1.Width()/2-sub; y1 = y-sub-fs1.Over() ; x2 = x1 +2*sub; y2 = y1 +2*sub; DrawLine(x1,y1,x2,y2,spec); break; case 7: // check x1 = x+fs1.Width()/2 ; x2 = x1 -2*sub ; x3 = x1 +2*sub ; y1 = y-sub-fs1.Over() ; DrawLine(x2,y-3*sub-fs1.Over(),x1,y1,spec); DrawLine(x3,y-3*sub-fs1.Over(),x1,y1,spec); break; case 8: // tilde x2 = x+fs1.Width()/2 ; y2 = y -fs1.Over() ; { // tilde must be drawn separately on screen and on PostScript // because an adjustment is required along Y for PostScript. TVirtualPS *saveps = gVirtualPS; if (gVirtualPS) gVirtualPS = 0; Double_t sinang = TMath::Sin(spec.fAngle/180*kPI); Double_t cosang = TMath::Cos(spec.fAngle/180*kPI); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); Double_t xx = gPad->AbsPixeltoX(Int_t((x2-xOrigin)*cosang+(y2-yOrigin)*sinang+xOrigin)); Double_t yy = gPad->AbsPixeltoY(Int_t((x2-xOrigin)*-sinang+(y2-yOrigin)*cosang+yOrigin)); TText tilde; tilde.SetTextFont(fTextFont); tilde.SetTextColor(spec.fColor); tilde.SetTextSize(0.9*spec.fSize); tilde.SetTextAlign(22); tilde.SetTextAngle(fTextAngle); tilde.PaintText(xx,yy,"~"); if (saveps) { gVirtualPS = saveps; if (!strstr(gVirtualPS->GetTitle(),"IMG")) y2 -= 4*sub; xx = gPad->AbsPixeltoX(Int_t((x2-xOrigin)*cosang+(y2-yOrigin)*sinang+xOrigin)); yy = gPad->AbsPixeltoY(Int_t((x2-xOrigin)*-sinang+(y2-yOrigin)*cosang+yOrigin)); gVirtualPS->SetTextAlign(22); gVirtualPS->Text(xx, yy, "~"); } } break; case 9: // slash x1 = x + 0.8*fs1.Width(); y1 = y -fs1.Over() ; x2 = x + 0.3*fs1.Width(); y2 = y1 + 1.2*fs1.Height(); DrawLine(x1,y1,x2,y2,spec); break; } } Double_t div = 3; if (opAbove==1) div=4; result.Set(fs1.Width(),fs1.Over()+GetHeight()*spec.fSize/div,fs1.Under()); } else if (opSquareBracket) { // operator #[]{arg} Double_t l = GetHeight()*spec.fSize/4; Double_t l2 = l/2 ; if (!fShow) { fs1 = Anal1(spec,text+3,length-3); Savefs(&fs1); } else { fs1 = Readfs(); Analyse(x+l2+l,y,spec,text+3,length-3); DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec); DrawLine(x+l2,y-fs1.Over(),x+l2+l,y-fs1.Over(),spec); DrawLine(x+l2,y+fs1.Under(),x+l2+l,y+fs1.Under(),spec); DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec); DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+l,y-fs1.Over(),spec); DrawLine(x+l2+fs1.Width()+2*l,y+fs1.Under(),x+l2+fs1.Width()+l,y+fs1.Under(),spec); } result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under()); } else if (opParen) { // operator #(){arg} Double_t l = GetHeight()*spec.fSize/4; Double_t radius2,radius1 , dw, l2 = l/2 ; Double_t angle = 35 ; if (!fShow) { fs1 = Anal1(spec,text+3,length-3); Savefs(&fs1); radius2 = fs1.Height() ; radius1 = radius2 * 2 / 3; dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ; } else { fs1 = Readfs(); radius2 = fs1.Height(); radius1 = radius2 * 2 / 3; dw = radius1*(1 - TMath::Cos(kPI*angle/180)) ; Double_t x1 = x+l2+radius1 ; Double_t x2 = x+5*l2+2*dw+fs1.Width()-radius1 ; Double_t y1 = y - (fs1.Over() - fs1.Under())/2. ; DrawParenthesis(x1,y1,radius1,radius2,180-angle,180+angle,spec) ; DrawParenthesis(x2,y1,radius1,radius2,360-angle,360+angle,spec) ; Analyse(x+3*l2+dw,y,spec,text+3,length-3); } // result = TLatexFormSize(fs1.Width()+3*l,fs1.Over(),fs1.Under()); result.Set(fs1.Width()+3*l+2*dw,fs1.Over(),fs1.Under()); } else if (opAbs) { // operator #||{arg} Double_t l = GetHeight()*spec.fSize/4; Double_t l2 = l/2 ; if (!fShow) { fs1 = Anal1(spec,text+3,length-3); Savefs(&fs1); } else { fs1 = Readfs(); Analyse(x+l2+l,y,spec,text+3,length-3); DrawLine(x+l2,y-fs1.Over(),x+l2,y+fs1.Under(),spec); DrawLine(x+l2+fs1.Width()+2*l,y-fs1.Over(),x+l2+fs1.Width()+2*l,y+fs1.Under(),spec); } result.Set(fs1.Width()+3*l,fs1.Over(),fs1.Under()); } else if (opBigCurly) { // big curly bracket #{}{arg} Double_t l = GetHeight()*spec.fSize/4; Double_t l2 = l/2 ; Double_t l8 , ltip; if (!fShow) { fs1 = Anal1(spec,text+3,length-3); l8 = fs1.Height()/8 ; ltip = TMath::Min(l8,l) ; l = ltip ; Savefs(&fs1); } else { fs1 = Readfs(); Double_t y2 = y + (fs1.Under()-fs1.Over())/2 ; l8 = fs1.Height()/8 ; ltip = TMath::Min(l8,l) ; l = ltip ; Analyse(x+l+ltip+l2,y,spec,text+3,length-3); // Draw open curly bracket // Vertical lines DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip,y2-ltip,spec); DrawLine(x+l2+ltip,y2+ltip,x+l2+ltip,y+fs1.Under(),spec); // top and bottom lines DrawLine(x+l2+ltip,y-fs1.Over(),x+l2+ltip+l,y-fs1.Over(),spec); DrawLine(x+l2+ltip,y+fs1.Under(),x+l2+ltip+l,y+fs1.Under(),spec); // < sign DrawLine(x+l2,y2,x+l2+ltip,y2-ltip,spec); DrawLine(x+l2,y2,x+l2+ltip,y2+ltip,spec); // Draw close curly bracket // vertical lines DrawLine(x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y2-ltip,spec); DrawLine(x+l2+ltip+fs1.Width()+2*l,y2+ltip,x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec); // Top and bottom lines DrawLine(x+l2+fs1.Width()+l+ltip,y-fs1.Over(),x+l2+ltip+fs1.Width()+2*l,y-fs1.Over(),spec); DrawLine(x+l2+fs1.Width()+l+ltip,y+fs1.Under(),x+l2+ltip+fs1.Width()+2*l,y+fs1.Under(),spec); // > sign DrawLine(x+l2+ltip+2*l+fs1.Width(),y2-ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec); DrawLine(x+l2+ltip+2*l+fs1.Width(),y2+ltip,x+l2+2*l+2*ltip+fs1.Width(),y2,spec); } result.Set(fs1.Width()+3*l+2*ltip,fs1.Over(),fs1.Under()) ;; } else if (opFrac>-1) { // \frac found if (opCurlyCurly==-1) { // }{ not found // arguments missing for \frac fError = "Missing denominator for #frac"; return TLatexFormSize(0,0,0); } Double_t height = GetHeight()*spec.fSize/8; if (!fShow) { fs1 = Anal1(spec,text+opFrac+6,opCurlyCurly-opFrac-6); fs2 = Anal1(spec,text+opCurlyCurly+2,length-opCurlyCurly-3); Savefs(&fs1); Savefs(&fs2); } else { fs2 = Readfs(); fs1 = Readfs(); Double_t addW1,addW2; if (fs1.Width()-1) { // \splitline found if (opCurlyCurly==-1) { // }{ not found // arguments missing for \splitline fError = "Missing second line for #splitline"; return TLatexFormSize(0,0,0); } Double_t height = GetHeight()*spec.fSize/8; if (!fShow) { fs1 = Anal1(spec,text+opSplitLine+11,opCurlyCurly-opSplitLine-11); fs2 = Anal1(spec,text+opCurlyCurly+2,length-opCurlyCurly-3); Savefs(&fs1); Savefs(&fs2); } else { fs2 = Readfs(); fs1 = Readfs(); Analyse(x,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3); // second line Analyse(x,y-fs1.Under()-3*height,spec,text+opSplitLine+11,opCurlyCurly-opSplitLine-11); //first line } result.Set(TMath::Max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height); } else if (opSqrt>-1) { // \sqrt found if (!fShow) { if (opSquareCurly>-1) { // power nth #sqrt[n]{arg} fs1 = Anal1(specNewSize,text+opSqrt+6,opSquareCurly-opSqrt-6); fs2 = Anal1(spec,text+opSquareCurly+1,length-opSquareCurly-1); Savefs(&fs1); Savefs(&fs2); result.Set(fs2.Width()+ GetHeight()*spec.fSize/10+TMath::Max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width()), fs2.Over()+fs1.Height()+GetHeight()*spec.fSize/4,fs2.Under()); } else { fs1 = Anal1(spec,text+opSqrt+5,length-opSqrt-5); Savefs(&fs1); result.Set(fs1.Width()+GetHeight()*spec.fSize/2,fs1.Over()+GetHeight()*spec.fSize/4,fs1.Under()); } } else { if (opSquareCurly>-1) { // ]{ fs2 = Readfs(); fs1 = Readfs(); Double_t pas = TMath::Max(GetHeight()*spec.fSize/2,(Double_t)fs1.Width()); Double_t pas2 = pas + GetHeight()*spec.fSize/10; Double_t y1 = y-fs2.Over() ; Double_t y2 = y+fs2.Under() ; Double_t y3 = y1-GetHeight()*spec.fSize/4; Analyse(x+pas2,y,spec,text+opSquareCurly+1,length-opSquareCurly-1); Analyse(x,y-fs2.Over()-fs1.Under(),specNewSize,text+opSqrt+6,opSquareCurly-opSqrt-6); // indice DrawLine(x,y1,x+pas,y2,spec); DrawLine(x+pas,y2,x+pas,y3,spec); DrawLine(x+pas,y3,x+pas2+fs2.Width(),y3,spec); } else { fs1 = Readfs(); Double_t x1 = x+GetHeight()*spec.fSize*2/5 ; Double_t x2 = x+GetHeight()*spec.fSize/2+fs1.Width() ; Double_t y1 = y-fs1.Over() ; Double_t y2 = y+fs1.Under() ; Double_t y3 = y1-GetHeight()*spec.fSize/4; Analyse(x+GetHeight()*spec.fSize/2,y,spec,text+opSqrt+6,length-opSqrt-7); Short_t lineW = GetLineWidth(); Double_t dx = (y2-y3)/8; SetLineWidth(TMath::Max(2,(Int_t)(dx/2))); DrawLine(x1-2*dx,y1,x1-dx,y2,spec); SetLineWidth((Int_t)(dx/4)); DrawLine(x1-dx,y2,x1,y3,spec); DrawLine(x1,y3,x2,y3,spec); SetLineWidth(lineW); } } } else if (opColor>-1) { // \color found if (opSquareCurly==-1) { // color number is not specified fError = "Missing color number. Syntax is #color[(Int_t)nb]{ ... }"; return TLatexFormSize(0,0,0); } TextSpec_t newSpec = spec; Char_t *nb = new Char_t[opSquareCurly-opColor-6]; strncpy(nb,text+opColor+7,opSquareCurly-opColor-7); nb[opSquareCurly-opColor-7] = 0; if (sscanf(nb,"%d",&newSpec.fColor) < 1) { delete[] nb; // color number is invalid fError = "Invalid color number. Syntax is #color[(Int_t)nb]{ ... }"; return TLatexFormSize(0,0,0); } delete[] nb; if (!fShow) { result = Anal1(newSpec,text+opSquareCurly+1,length-opSquareCurly-1); } else { Analyse(x,y,newSpec,text+opSquareCurly+1,length-opSquareCurly-1); } } else if (opFont>-1) { // \font found if (opSquareCurly==-1) { // font number is not specified fError = "Missing font number. Syntax is #font[nb]{ ... }"; return TLatexFormSize(0,0,0); } TextSpec_t newSpec = spec; Char_t *nb = new Char_t[opSquareCurly-opFont-5]; strncpy(nb,text+opFont+6,opSquareCurly-opFont-6); nb[opSquareCurly-opFont-6] = 0; if (sscanf(nb,"%d",&newSpec.fFont) < 1) { delete[] nb; // font number is invalid fError = "Invalid font number. Syntax is #font[(Int_t)nb]{ ... }"; return TLatexFormSize(0,0,0); } delete[] nb; if (!fShow) { result = Anal1(newSpec,text+opSquareCurly+1,length-opSquareCurly-1); } else { Analyse(x,y,newSpec,text+opSquareCurly+1,length-opSquareCurly-1); } } else if (opKern>-1) { // #kern found if (opSquareCurly==-1) { // horizontal shift is not specified fError = "Missing horizontal shift number. Syntax is #kern[dx]{ ... }"; return TLatexFormSize(0,0,0); } Char_t *dxc = new Char_t[opSquareCurly-opKern-5]; strncpy(dxc,text+opKern+6,opSquareCurly-opKern-6); dxc[opSquareCurly-opKern-6] = 0; Float_t dx = 0; if (sscanf(dxc,"%f",&dx) < 1) { delete[] dxc; // horizontal shift number is invalid fError = "Invalid horizontal shift number. Syntax is #kern[(Float_t)dx]{ ... }"; return TLatexFormSize(0,0,0); } delete[] dxc; if (!fShow) { fs1 = Anal1(spec,text+opSquareCurly+1,length-opSquareCurly-1); Savefs(&fs1); Double_t ddx = dx * fs1.Width(); result = TLatexFormSize(fs1.Width() + ddx, fs1.Over(), fs1.Under()); } else { fs1 = Readfs(); Double_t ddx = dx * fs1.Width(); Analyse(x + ddx,y,spec,text+opSquareCurly+1,length-opSquareCurly-1); } } else if (opLower>-1) { // #lower found if (opSquareCurly==-1) { // vertical shift is not specified fError = "Missing vertical shift number. Syntax is #lower[dy]{ ... }"; return TLatexFormSize(0,0,0); } Char_t *dyc = new Char_t[opSquareCurly-opLower-6]; strncpy(dyc,text+opLower+7,opSquareCurly-opLower-7); dyc[opSquareCurly-opLower-7] = 0; Float_t dy = 0; if (sscanf(dyc,"%f",&dy) < 1) { delete[] dyc; // vertical shift number is invalid fError = "Invalid vertical shift number. Syntax is #lower[(Float_t)dy]{ ... }"; return TLatexFormSize(0,0,0); } delete[] dyc; if (!fShow) { fs1 = Anal1(spec,text+opSquareCurly+1,length-opSquareCurly-1); Savefs(&fs1); Double_t ddy = dy * (fs1.Over() + fs1.Under()); result = TLatexFormSize(fs1.Width(), fs1.Over() + ddy, fs1.Under() + ddy); } else { fs1 = Readfs(); Double_t ddy = dy * (fs1.Over() + fs1.Under()); Analyse(x,y + ddy,spec,text+opSquareCurly+1,length-opSquareCurly-1); } } else if (opScale>-1) { // \scale found if (opSquareCurly==-1) { // scale factor is not specified fError = "Missing scale factor. Syntax is #scale[(Double_t)nb]{ ... }"; return TLatexFormSize(0,0,0); } TextSpec_t newSpec = spec; Char_t *nb = new Char_t[opSquareCurly-opScale-6]; strncpy(nb,text+opScale+7,opSquareCurly-opScale-7); nb[opSquareCurly-opScale-7] = 0; if (sscanf(nb,"%lf",&newSpec.fSize) < 1) { delete[] nb; // scale factor is invalid fError = "Invalid scale factor. Syntax is #factor[(Double_t)nb]{ ... }"; return TLatexFormSize(0,0,0); } newSpec.fSize *= spec.fSize; delete[] nb; if (!fShow) { result = Anal1(newSpec,text+opSquareCurly+1,length-opSquareCurly-1); } else { Analyse(x,y,newSpec,text+opSquareCurly+1,length-opSquareCurly-1); } } else if (opBf>-1) { // operator #bf{arg} TextSpec_t newSpec = spec; Int_t lut[] = {3, 13, 1, 6, 7, 4, 5, 10, 11, 8, 9, 12, 2, 14, 15}; Int_t fontId = (newSpec.fFont/10); if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1]; newSpec.fFont = fontId*10 + newSpec.fFont%10; if (!fShow) { fs1 = Anal1(newSpec,text+3,length-3); Savefs(&fs1); } else { fs1 = Readfs(); Analyse(x,y,newSpec,text+3,length-3); } result = fs1; } else if (opMbox>-1) { // dummy operator #mbox{arg} TextSpec_t newSpec = spec; if (!fShow) { fs1 = Anal1(newSpec,text+5,length-5); Savefs(&fs1); } else { fs1 = Readfs(); Analyse(x,y,newSpec,text+5,length-5); } result = fs1; } else if (opIt>-1) { // operator #it{arg} TextSpec_t newSpec = spec; Int_t lut[] = {13, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 15, 1, 14, 12}; Int_t fontId = (newSpec.fFont/10); if ((fontId >= 1) && (fontId <= (Int_t)(sizeof(lut)/sizeof(lut[0])))) fontId = lut[fontId-1]; newSpec.fFont = fontId*10 + newSpec.fFont%10; fItalic = !fItalic; if (!fShow) { fs1 = Anal1(newSpec,text+3,length-3); Savefs(&fs1); } else { fs1 = Readfs(); Analyse(x,y,newSpec,text+3,length-3); } fItalic = !fItalic; result = fs1; } else { // no operators found, it is a character string SetTextSize(spec.fSize); SetTextAngle(spec.fAngle); SetTextColor(spec.fColor); SetTextFont(spec.fFont); SetTextAlign(11); TAttText::Modify(); UInt_t w=0,h=0; Int_t leng = strlen(text) ; quote1 = quote2 = kFALSE ; Char_t *p ; for (i=0 ; iXtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); Double_t angle = kPI*spec.fAngle/180.; Double_t xx = gPad->AbsPixeltoX(Int_t((x-xOrigin)*TMath::Cos(angle)+(y-yOrigin)*TMath::Sin(angle)+xOrigin)); Double_t yy = gPad->AbsPixeltoY(Int_t((x-xOrigin)*TMath::Sin(-angle)+(y-yOrigin)*TMath::Cos(angle)+yOrigin)); gPad->PaintText(xx,yy,text); } else { GetTextExtent(w,h,text); Double_t width = w; UInt_t a,d; GetTextAscentDescent(a, d, text); fs1.Set(width,a,d); } result = fs1; } delete[] text; return result; } //______________________________________________________________________________ TLatex *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 TLatex *newtext = new TLatex(x, y, text); TAttText::Copy(*newtext); newtext->SetBit(kCanDelete); if (TestBit(kTextNDC)) newtext->SetNDC(); newtext->AppendPad(); return newtext; } //______________________________________________________________________________ TLatex *TLatex::DrawLatexNDC(Double_t x, Double_t y, const char *text) { // Draw this TLatex with new coordinates in NDC. TLatex *newtext = DrawLatex(x, y, text); newtext->SetNDC(); return newtext; } //______________________________________________________________________________ void TLatex::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2, TextSpec_t spec) { // Draw a line in a Latex formula Double_t sinang = TMath::Sin(spec.fAngle/180*kPI); Double_t cosang = TMath::Cos(spec.fAngle/180*kPI); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); Double_t xx = gPad->AbsPixeltoX(Int_t((x1-xOrigin)*cosang+(y1-yOrigin)*sinang+xOrigin)); Double_t yy = gPad->AbsPixeltoY(Int_t((x1-xOrigin)*-sinang+(y1-yOrigin)*cosang+yOrigin)); Double_t xx2 = gPad->AbsPixeltoX(Int_t((x2-xOrigin)*cosang+(y2-yOrigin)*sinang+xOrigin)); Double_t yy2 = gPad->AbsPixeltoY(Int_t((x2-xOrigin)*-sinang+(y2-yOrigin)*cosang+yOrigin)); SetLineColor(spec.fColor); TAttLine::Modify(); gPad->PaintLine(xx,yy,xx2,yy2); } //______________________________________________________________________________ void TLatex::DrawCircle(Double_t x1, Double_t y1, Double_t r, TextSpec_t spec ) { // Draw an arc of ellipse in a Latex formula (right or left parenthesis) if (r < 1) r = 1; Double_t sinang = TMath::Sin(spec.fAngle/180*kPI); Double_t cosang = TMath::Cos(spec.fAngle/180*kPI); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); const Int_t np = 40; Double_t dphi = 2*kPI/np; Double_t x[np+3], y[np+3]; Double_t angle,dx,dy; SetLineColor(spec.fColor); TAttLine::Modify(); //Change line attributes only if necessary for (Int_t i=0;i<=np;i++) { angle = Double_t(i)*dphi; dx = r*TMath::Cos(angle) +x1 -xOrigin; dy = r*TMath::Sin(angle) +y1 -yOrigin; x[i] = gPad->AbsPixeltoX(Int_t( dx*cosang+ dy*sinang +xOrigin)); y[i] = gPad->AbsPixeltoY(Int_t(-dx*sinang+ dy*cosang +yOrigin)); } gPad->PaintPolyLine(np+1,x,y); } //______________________________________________________________________________ void TLatex::DrawParenthesis(Double_t x1, Double_t y1, Double_t r1, Double_t r2, Double_t phimin, Double_t phimax, TextSpec_t spec ) { // Draw an arc of ellipse in a Latex formula (right or left parenthesis) if (r1 < 1) r1 = 1; if (r2 < 1) r2 = 1; Double_t sinang = TMath::Sin(spec.fAngle/180*kPI); Double_t cosang = TMath::Cos(spec.fAngle/180*kPI); Double_t xOrigin = (Double_t)gPad->XtoAbsPixel(fX); Double_t yOrigin = (Double_t)gPad->YtoAbsPixel(fY); const Int_t np = 40; Double_t dphi = (phimax-phimin)*kPI/(180*np); Double_t x[np+3], y[np+3]; Double_t angle,dx,dy ; SetLineColor(spec.fColor); TAttLine::Modify(); //Change line attributes only if necessary for (Int_t i=0;i<=np;i++) { angle = phimin*kPI/180 + Double_t(i)*dphi; dx = r1*TMath::Cos(angle) +x1 -xOrigin; dy = r2*TMath::Sin(angle) +y1 -yOrigin; x[i] = gPad->AbsPixeltoX(Int_t( dx*cosang+dy*sinang +xOrigin)); y[i] = gPad->AbsPixeltoY(Int_t(-dx*sinang+dy*cosang +yOrigin)); } gPad->PaintPolyLine(np+1,x,y); } //______________________________________________________________________________ void TLatex::Paint(Option_t *) { // Paint. Double_t xsave = fX; Double_t ysave = fY; if (TestBit(kTextNDC)) { fX = gPad->GetX1() + xsave*(gPad->GetX2() - gPad->GetX1()); fY = gPad->GetY1() + ysave*(gPad->GetY2() - gPad->GetY1()); PaintLatex(fX,fY,GetTextAngle(),GetTextSize(),GetTitle()); } else { PaintLatex(gPad->XtoPad(fX),gPad->YtoPad(fY),GetTextAngle(),GetTextSize(),GetTitle()); } fX = xsave; fY = ysave; } //______________________________________________________________________________ void TLatex::PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const Char_t *text1) { // Main drawing function // // Warning: Unlike most others "XYZ::PaintXYZ" methods, PaintLatex modifies // the TLatex data members. TAttText::Modify(); // Change text attributes only if necessary. TVirtualPS *saveps = gVirtualPS; if (gVirtualPS) { if (gVirtualPS->InheritsFrom("TTeXDump")) { gVirtualPS->SetTextAngle(angle); TString t(text1); if (t.Index("#")>=0 || t.Index("^")>=0 || t.Index("\\")>=0) { t.ReplaceAll("#LT","\\langle"); t.ReplaceAll("#GT","\\rangle"); t.ReplaceAll("#club","\\clubsuit"); t.ReplaceAll("#spade","\\spadesuit"); t.ReplaceAll("#heart","\\heartsuit"); t.ReplaceAll("#diamond","\\diamondsuit"); t.ReplaceAll("#voidn","\\wp"); t.ReplaceAll("#voidb","f"); t.ReplaceAll("#ocopyright","\\copyright"); t.ReplaceAll("#trademark","TM"); t.ReplaceAll("#void3","TM"); t.ReplaceAll("#oright","R"); t.ReplaceAll("#void1","R"); t.ReplaceAll("#3dots","\\ldots"); t.ReplaceAll("#lbar","\\mid"); t.ReplaceAll("#void8","\\mid"); t.ReplaceAll("#divide","\\div"); t.ReplaceAll("#Jgothic","\\Im"); t.ReplaceAll("#Rgothic","\\Re"); t.ReplaceAll("#doublequote","\""); t.ReplaceAll("#plus","+"); t.ReplaceAll("#minus","-"); t.ReplaceAll("#/","/"); t.ReplaceAll("#upoint","."); t.ReplaceAll("#aa","\\mbox{\\aa}"); t.ReplaceAll("#AA","\\mbox{\\AA}"); t.ReplaceAll("#omicron","o"); t.ReplaceAll("#Alpha","A"); t.ReplaceAll("#Beta","B"); t.ReplaceAll("#Epsilon","E"); t.ReplaceAll("#Zeta","Z"); t.ReplaceAll("#Eta","H"); t.ReplaceAll("#Iota","I"); t.ReplaceAll("#Kappa","K"); t.ReplaceAll("#Mu","M"); t.ReplaceAll("#Nu","N"); t.ReplaceAll("#Omicron","O"); t.ReplaceAll("#Rho","P"); t.ReplaceAll("#Tau","T"); t.ReplaceAll("#Chi","X"); t.ReplaceAll("#varomega","\\varpi"); t.ReplaceAll("#varUpsilon","?"); t.ReplaceAll("#corner","?"); t.ReplaceAll("#ltbar","?"); t.ReplaceAll("#bottombar","?"); t.ReplaceAll("#notsubset","?"); t.ReplaceAll("#arcbottom","?"); t.ReplaceAll("#cbar","?"); t.ReplaceAll("#arctop","?"); t.ReplaceAll("#topbar","?"); t.ReplaceAll("#arcbar","?"); t.ReplaceAll("#downleftarrow","?"); t.ReplaceAll("#","\\"); t.ReplaceAll("%","\\%"); } gVirtualPS->Text(x,y,t.Data()); gVirtualPS = 0; } } // Do not use Latex if font is low precision. if (fTextFont%10 < 2) { if (gVirtualX) gVirtualX->SetTextAngle(angle); if (gVirtualPS) gVirtualPS->SetTextAngle(angle); gPad->PaintText(x,y,text1); if (saveps) gVirtualPS = saveps; return; } // Paint the text using TMathText if contains a "\" if (strstr(text1,"\\")) { TMathText tm; tm.SetTextAlign(GetTextAlign()); tm.PaintMathText(x, y, angle, size, text1); if (saveps) gVirtualPS = saveps; return; } TString newText = text1; if( newText.Length() == 0) return; newText.ReplaceAll("#hbox","#mbox"); Double_t saveSize = size; Int_t saveFont = fTextFont; if (fTextFont%10 > 2) { UInt_t w = TMath::Abs(gPad->XtoAbsPixel(gPad->GetX2()) - gPad->XtoAbsPixel(gPad->GetX1())); UInt_t h = TMath::Abs(gPad->YtoAbsPixel(gPad->GetY2()) - gPad->YtoAbsPixel(gPad->GetY1())); if (w < h) size = size/w; else size = size/h; SetTextFont(10*(saveFont/10) + 2); } fError = 0 ; if (CheckLatexSyntax(newText)) { std::cout<<"\n*ERROR: "< "<XtoAbsPixel(x); y = gPad->YtoAbsPixel(y); fShow = kFALSE ; TLatexFormSize fs = FirstParse(angle,size,text); fOriginSize = size; // Get current line attributes. Short_t lineW = GetLineWidth(); Int_t lineC = GetLineColor(); TextSpec_t spec; spec.fAngle = angle; spec.fSize = size; spec.fColor = GetTextColor(); spec.fFont = GetTextFont(); Short_t halign = fTextAlign/10; Short_t valign = fTextAlign - 10*halign; TextSpec_t newSpec = spec; if (fError != 0) { std::cout<<"*ERROR: "< "< 0) { error = 1 ; fError = "Missing \"}\"" ; } else if (nOfSquareBracket < 0) { error = 1 ; fError = "Missing \"[\"" ; } else if (nOfSquareBracket > 0) { error = 1 ; fError = "Missing \"]\"" ; } ERROR_END: return error ; } //______________________________________________________________________________ TLatexFormSize TLatex::FirstParse(Double_t angle, Double_t size, const Char_t *text) { // First parsing of the analyse sequence fError = 0; fTabMax = 100; fTabSize = new FormSize_t[fTabMax]; // we assume less than 100 parts in one formula // we will reallocate if necessary. fPos = 0; fShow = kFALSE; fOriginSize = size; //get current line attributes Short_t lineW = GetLineWidth(); Int_t lineC = GetLineColor(); TextSpec_t spec; spec.fAngle = angle; if (fTextFont%10 == 3) { Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()), (Double_t)gPad->YtoPixel(gPad->GetY1())); spec.fSize = size/hw; } else { spec.fSize = size; } spec.fColor = GetTextColor(); spec.fFont = GetTextFont(); Short_t halign = fTextAlign/10; Short_t valign = fTextAlign - 10*halign; TLatexFormSize fs = Anal1(spec,text,strlen(text)); SetTextSize(size); SetTextAngle(angle); SetTextFont(spec.fFont); SetTextColor(spec.fColor); SetTextAlign(valign+10*halign); SetLineWidth(lineW); SetLineColor(lineC); return fs; } //______________________________________________________________________________ Double_t TLatex::GetHeight() const { // Return height of current pad in pixels Double_t w = gPad->GetAbsWNDC()*Double_t(gPad->GetWw()); Double_t h = gPad->GetAbsHNDC()*Double_t(gPad->GetWh()); if (w < h) return w; else return h; } //______________________________________________________________________________ Double_t TLatex::GetXsize() { // Return size of the formula along X in pad coordinates if (!gPad) return 0; TString newText = GetTitle(); if( newText.Length() == 0) return 0; fError = 0 ; if (CheckLatexSyntax(newText)) { std::cout<<"\n*ERROR: "< "<AbsPixeltoX(Int_t(fs.Width())) - gPad->AbsPixeltoX(0)); } //______________________________________________________________________________ void TLatex::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle) { // Return text size in pixels if (!gPad) return; TString newText = GetTitle(); if( newText.Length() == 0) return; fError = 0 ; if (CheckLatexSyntax(newText)) { std::cout<<"\n*ERROR: "< "<UtoPixel(fX); pty = gPad->VtoPixel(fY); } else { ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX)); pty = gPad->YtoAbsPixel(gPad->YtoPad(fY)); } GetControlBox(ptx, pty, fTextAngle, cBoxX, cBoxY); Int_t x1 = cBoxX[0]; Int_t x2 = cBoxX[0]; Int_t y1 = cBoxY[0]; Int_t y2 = cBoxY[0]; for (Int_t i=1; i<4; i++) { if (cBoxX[i] < x1) x1 = cBoxX[i]; if (cBoxX[i] > x2) x2 = cBoxX[i]; if (cBoxY[i] < y1) y1 = cBoxY[i]; if (cBoxY[i] > y2) y2 = cBoxY[i]; } w = x2-x1; h = y2-y1; } else { const Char_t *text = newText.Data() ; TLatexFormSize fs = FirstParse(GetTextAngle(),GetTextSize(),text); delete[] fTabSize; w = (UInt_t)fs.Width(); h = (UInt_t)fs.Height(); } } //______________________________________________________________________________ Double_t TLatex::GetYsize() { // Return size of the formula along Y in pad coordinates if (!gPad) return 0; TString newText = GetTitle(); if( newText.Length() == 0) return 0; fError = 0 ; if (CheckLatexSyntax(newText)) { std::cout<<"\n*ERROR: "< "<AbsPixeltoY(Int_t(fs.Height())) - gPad->AbsPixeltoY(0)); } //______________________________________________________________________________ TLatexFormSize TLatex::Readfs() { // Read fs in fTabSize fPos--; TLatexFormSize result(fTabSize[fPos].fWidth,fTabSize[fPos].fOver,fTabSize[fPos].fUnder); return result; } //______________________________________________________________________________ void TLatex::Savefs(TLatexFormSize *fs) { // Save fs values in array fTabSize fTabSize[fPos].fWidth = fs->Width(); fTabSize[fPos].fOver = fs->Over(); fTabSize[fPos].fUnder = fs->Under(); fPos++; if (fPos>=fTabMax) { // allocate more memory FormSize_t *temp = new FormSize_t[fTabMax+100]; // copy array memcpy(temp,fTabSize,fTabMax*sizeof(FormSize_t)); fTabMax += 100; // free previous array delete [] fTabSize; // swap pointers fTabSize = temp; } } //______________________________________________________________________________ void TLatex::SavePrimitive(std::ostream &out, Option_t * /*= ""*/) { // Save primitive as a C++ statement(s) on output stream out char quote = '"'; if (gROOT->ClassSaved(TLatex::Class())) { out<<" "; } else { out<<" TLatex *"; } TString s = GetTitle(); s.ReplaceAll("\\","\\\\"); s.ReplaceAll("\"","\\\""); out<<" tex = new TLatex("<SetNDC();"<Draw();"<