#include "Riostream.h"
#include "TROOT.h"
#include "TClass.h"
#include "TLatex.h"
#include "TMath.h"
#include "TVirtualPad.h"
#include "TVirtualPS.h"
#ifdef R__SUNCCBUG
const Double_t kPI = 3.14159265358979323846;
#else
const Double_t kPI = TMath::Pi();
#endif
const Int_t kLatex = BIT(10);
const Int_t kPrintingPS = BIT(11);
ClassImp(TLatex)
TLatex::TLatex()
{
fFactorSize = 1.5;
fFactorPos = 0.6;
fLimitFactorSize = 3;
fError = 0;
fShow = kFALSE;
fPos=fTabMax = 0;
fOriginSize = 0.04;
fTabSize = 0;
SetLineWidth(2);
}
TLatex::TLatex(Double_t x, Double_t y, const char *text)
:TText(x,y,text)
{
fFactorSize = 1.5;
fFactorPos = 0.6;
fLimitFactorSize = 3;
fError = 0;
fShow = kFALSE;
fPos=fTabMax = 0;
fOriginSize = 0.04;
fTabSize = 0;
SetLineWidth(2);
}
TLatex::~TLatex()
{
}
TLatex::TLatex(const TLatex &text) : TText(text), TAttLine(text)
{
((TLatex&)text).Copy(*this);
}
TLatex& TLatex::operator=(const TLatex& lt)
{
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;
}
return *this;
}
void TLatex::Copy(TObject &obj) const
{
((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;
TText::Copy(obj);
TAttLine::Copy(((TAttLine&)obj));
}
TLatexFormSize TLatex::Anal1(TextSpec_t spec, const Char_t* t, Int_t length)
{
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)
{
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" };
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) {
if (nBlancDeb==length) return TLatexFormSize(0,0,0);
if (nBlancDeb==l_nBlancDeb && nBlancFin==l_nBlancFin) cont = kFALSE;
if (t[nBlancDeb]=='{' && t[length-nBlancFin-1]=='}') {
Int_t nBrackets = 0;
Bool_t sameBrackets = kTRUE;
for(i=nBlancDeb;i<length-nBlancFin;i++) {
if (t[i] == '{' && !(i>0 && t[i-1] == '@')) nBrackets++;
if (t[i] == '}' && t[i-1]!= '@') nBrackets--;
if (nBrackets==0 && i<length-nBlancFin-2) {
sameBrackets=kFALSE;
break;
}
}
if (sameBrackets) {
nBlancDeb++;
nBlancFin++;
if (nBlancDeb+nBlancFin==length) return TLatexFormSize(0,0,0);
cont = kTRUE;
}
}
l_nBlancDeb = nBlancDeb;
l_nBlancFin = nBlancFin;
}
length -= nBlancFin+nBlancDeb;
Char_t* text = new Char_t[length+1];
strncpy(text,t+nBlancDeb,length);
text[length] = 0;
Double_t indiceSize = spec.fSize/fFactorSize;
if(indiceSize<fOriginSize/TMath::Exp(fLimitFactorSize*TMath::Log(fFactorSize))-0.001f)
indiceSize = spec.fSize;
TextSpec_t specNewSize = spec;
specNewSize.fSize = indiceSize;
Int_t opPower = -1;
Int_t opUnder = -1;
Int_t opFrac = -1;
Int_t opSqrt = -1;
Int_t nBrackets = 0;
Int_t nCroch = 0;
Int_t opCurlyCurly = -1;
Int_t opSquareCurly = -1;
Int_t opCloseCurly = -2;
Int_t opColor = -1;
Int_t opFont = -1;
Int_t opScale = -1;
Int_t opGreek = -1;
Int_t opSpec = -1;
Int_t opAbove = -1;
Int_t opSquareBracket = 0 ;
Int_t opBigCurly = 0 ;
Int_t opAbs = 0 ;
Int_t opParen = 0 ;
Int_t abovePlace = 0 ;
Int_t opBox = 0 ;
Int_t opPerp = 0;
Int_t opOdot = 0;
Int_t opHbar = 0;
Int_t opParallel = 0;
Int_t opSplitLine = -1;
Bool_t opFound = kFALSE;
Bool_t quote1 = kFALSE, quote2 = kFALSE ;
for(i=0;i<length;i++) {
switch (text[i]) {
case '\'' : quote1 = !quote1 ; break ;
case '"' : quote2 = !quote2 ; break ;
}
switch (text[i]) {
case '{':
if (nCroch==0) {
if (!(i>0 && text[i-1] == '@')) nBrackets++;
}
break;
case '}':
if (nCroch==0) {
if (!(i>0 && text[i-1] == '@')) nBrackets--;
if (nBrackets==0) {
if (i<length-1) if (text[i+1]=='{' && opCurlyCurly==-1) opCurlyCurly=i;
if (i<length-2) {
if (text[i+1]!='{' && !(text[i+2]=='{' && (text[i+1]=='^' || text[i+1]=='_'))
&& opCloseCurly==-2) opCloseCurly=i;
}
else if (i<length-1) {
if (text[i+1]!='{' && opCloseCurly==-2) opCloseCurly=i;
}
else if (opCloseCurly==-2) opCloseCurly=i;
}
}
break;
case '[':
if (nBrackets==0) {
if (!(i>0 && text[i-1] == '@')) nCroch++;
}
break;
case ']':
if (nBrackets==0) {
if (!(i>0 && text[i-1] == '@')) nCroch--;
if (nCroch<0) {
fError = "Missing \"[\"";
return TLatexFormSize(0,0,0);
}
}
break;
}
if (length>i+1) {
Char_t buf[2];
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[4];
strncpy(buf1,&text[i-4],4);
if (strncmp(buf1,"#int",4)==0) abovePlace = 1;
if (strncmp(buf1,"#sum",4)==0) abovePlace = 2;
}
}
if (strncmp(buf,"_{",2)==0) {
if (opUnder==-1 && nBrackets==0 && nCroch==0) opUnder=i;
if (i>3) {
Char_t buf2[4];
strncpy(buf2,&text[i-4],4);
if (strncmp(buf2,"#int",4)==0) abovePlace = 1;
if (strncmp(buf2,"#sum",4)==0) abovePlace = 2;
}
}
if (strncmp(buf,"]{",2)==0)
if (opSquareCurly==-1 && nBrackets==0 && nCroch==0) opSquareCurly=i;
}
if (text[i]=='\\' || (text[i]=='#' && !opFound && nBrackets==0 && nCroch==0)) {
if (length>i+10 ) {
Char_t buf[10];
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+8 ) {
Char_t buf[8];
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[6];
strncpy(buf,&text[i+1],6);
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 (length>i+6) {
Char_t buf[6];
strncpy(buf,&text[i+1],6);
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[5];
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 (length>i+4 ) {
Char_t buf[4];
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 (length>i+3) {
Char_t buf[3];
strncpy(buf,&text[i+1],3);
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;
}
}
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<80;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;
if (opCloseCurly>-1 && opCloseCurly<length-1) {
if(!fShow) {
fs1 = Anal1(spec,text,opCloseCurly+1);
fs2 = Anal1(spec,text+opCloseCurly+1,length-opCloseCurly-1);
Savefs(&fs1);
} else {
fs1 = Readfs();
Analyse(x+fs1.Width(),y,spec,text+opCloseCurly+1,length-opCloseCurly-1);
Analyse(x,y,spec,text,opCloseCurly+1);
}
result = fs1+fs2;
}
else if (opPower>-1 && opUnder>-1) {
min = TMath::Min(opPower,opUnder);
max = TMath::Max(opPower,opUnder);
Double_t xfpos = 0. ;
Double_t prop=1, propU=1;
switch (abovePlace) {
case 1 :
prop = .8 ; propU = 1.75 ;
break;
case 2:
prop = .9 ; propU = 1.75 ;
break;
}
if (!fShow) {
Int_t ltext = min ;
if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) {
sprintf(&text[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<opUnder) {
addH1 = -fs1.Over()*(fFactorPos)-fs2.Under();
addH2 = fs1.Under()+fs3.Over()*(fFactorPos);
} else {
addH1 = fs1.Under()+fs2.Over()*(fFactorPos);
addH2 = -fs1.Over()*(fFactorPos)-fs3.Under();
}
Analyse(x+addW,y+addH2,specNewSize,text+max+1,length-max-1);
Analyse(x+addW,y+addH1,specNewSize,text+min+1,max-min-1);
} else {
Double_t addW1, addW2, addH1, addH2;
Double_t m = TMath::Max(fs1.Width(),TMath::Max(fs2.Width(),fs3.Width()));
pos = (m-fs1.Width())/2;
if (opPower<opUnder) {
addH1 = -fs1.Over()*propU-fs2.Under();
addW1 = (m-fs2.Width())/2;
addH2 = fs1.Under()*prop+fs3.Over();
addW2 = (m-fs3.Width())/2;
} else {
addH1 = fs1.Under()*prop+fs2.Over();
addW1 = (m-fs2.Width())/2;
addH2 = -fs1.Over()*propU-fs3.Under();
addW2 = (m-fs3.Width())/2;
}
Analyse(x+addW2,y+addH2,specNewSize,text+max+1,length-max-1);
Analyse(x+addW1,y+addH1,specNewSize,text+min+1,max-min-1);
}
if (min >= 2 && strncmp(&text[min-2],"{}",2)==0) {
sprintf(&text[min-2]," ") ;
Analyse(x+pos,y,spec,text,min-1);
} else {
Analyse(x+pos,y,spec,text,min);
}
}
if (!abovePlace) {
if (opPower<opUnder) {
result.Set(fs1.Width()+xfpos+TMath::Max(fs2.Width(),fs3.Width()),
fs1.Over()*fFactorPos+fs2.Height(),
fs1.Under()+fs3.Height()-fs3.Over()*(1-fFactorPos));
} else {
result.Set(fs1.Width()+xfpos+TMath::Max(fs2.Width(),fs3.Width()),
fs1.Over()*fFactorPos+fs3.Height(),
fs1.Under()+fs2.Height()-fs2.Over()*(1-fFactorPos));
}
} else {
if (opPower<opUnder) {
result.Set(TMath::Max(fs1.Width(),TMath::Max(fs2.Width(),fs3.Width())),
fs1.Over()*propU+fs2.Height(),fs1.Under()*prop+fs3.Height());
} else {
result.Set(TMath::Max(fs1.Width(),TMath::Max(fs2.Width(),fs3.Width())),
fs1.Over()*propU+fs3.Height(),fs1.Under()*prop+fs2.Height());
}
}
}
else if (opPower>-1) {
Double_t prop=1;
Double_t xfpos = 0. ;
switch (abovePlace) {
case 1 :
prop = 1.75 ; break ;
case 2 :
prop = 1.75; break ;
}
if (!fShow) {
Int_t ltext = opPower ;
if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) {
sprintf(&text[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) {
sprintf(&text[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) {
Double_t prop = .9;
Double_t xfpos = 0.;
Double_t fpos = fFactorPos ;
if(!fShow) {
Int_t ltext = opUnder ;
if (ltext >= 2 && strncmp(&text[ltext-2],"{}",2)==0) {
sprintf(&text[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) {
sprintf(&text[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(fTextColor);
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 (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 (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 = 122;
char letter = 97 + opGreek;
Double_t yoffset = 0.;
if (opGreek>25) letter -= 58;
if (opGreek == 52) letter = '\241';
if (opGreek == 53) letter = '\316';
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 = 122;
char letter = '\243' + opSpec;
if(opSpec == 75 || opSpec == 76) {
newSpec.fFont = GetTextFont();
if (opSpec == 75) letter = '\305';
if (opSpec == 76) letter = '\345';
}
Double_t props, propi;
props = 1.8 ;
propi = 2.3 ;
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:
Double_t ypos ;
ypos = y-fs1.Over()-sub ;
DrawLine(x,ypos,x+fs1.Width(),ypos,spec);
break;
case 1:
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:
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:
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:
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:
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:
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:
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:
x2 = x+fs1.Width()/2 ;
y2 = y -fs1.Over() ;
{
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(fTextColor);
tilde.SetTextSize(0.9*spec.fSize);
tilde.SetTextAlign(22);
tilde.SetTextAngle(fTextAngle);
tilde.PaintText(xx,yy,"~");
if (saveps) {
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 = saveps;
gVirtualPS->SetTextAlign(22);
gVirtualPS->Text(xx, yy, "~");
}
}
break;
case 9:
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) {
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) {
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.Set(fs1.Width()+3*l+2*dw,fs1.Over(),fs1.Under());
}
else if (opAbs) {
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) {
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);
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);
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);
DrawLine(x+l2,y2,x+l2+ltip,y2-ltip,spec);
DrawLine(x+l2,y2,x+l2+ltip,y2+ltip,spec);
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);
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);
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) {
if (opCurlyCurly==-1) {
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()<fs2.Width()) {
addW1 = (fs2.Width()-fs1.Width())/2;
addW2 = 0;
} else {
addW1 = 0;
addW2 = (fs1.Width()-fs2.Width())/2;
}
Analyse(x+addW2,y+fs2.Over()-height,spec,text+opCurlyCurly+2,length-opCurlyCurly-3);
Analyse(x+addW1,y-fs1.Under()-3*height,spec,text+opFrac+6,opCurlyCurly-opFrac-6);
DrawLine(x,y-2*height,x+TMath::Max(fs1.Width(),fs2.Width()),y-2*height,spec);
}
result.Set(TMath::Max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
}
else if (opSplitLine>-1) {
if (opCurlyCurly==-1) {
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);
Analyse(x,y-fs1.Under()-3*height,spec,text+opSplitLine+11,opCurlyCurly-opSplitLine-11);
}
result.Set(TMath::Max(fs1.Width(),fs2.Width()),fs1.Height()+3*height,fs2.Height()-height);
}
else if (opSqrt>-1) {
if (!fShow) {
if (opSquareCurly>-1) {
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);
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(x-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) {
if (opSquareCurly==-1) {
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;
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) {
if (opSquareCurly==-1) {
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;
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 (opScale>-1) {
if (opSquareCurly==-1) {
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;
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 {
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 ; i<leng ; i++) {
switch (text[i]) {
case '\'' : quote1 = !quote1 ; break ;
case '"' : quote2 = !quote2 ; break ;
}
if (text[i] == '@') {
p = &text[i] ;
if ( *(p+1) == '{' || *(p+1) == '}' || *(p+1) == '[' || *(p+1) == ']') {
while (*p != 0) {
*p = *(p+1) ; p++ ;
}
leng-- ;
}
}
}
text[leng] = 0 ;
if (fShow) {
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));
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)
{
TLatex *newtext = new TLatex(x, y, text);
TAttText::Copy(*newtext);
newtext->SetBit(kCanDelete);
if (TestBit(kTextNDC)) newtext->SetNDC();
newtext->AppendPad();
return newtext;
}
void TLatex::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2, TextSpec_t spec)
{
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 )
{
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();
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 )
{
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();
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 *)
{
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)
{
TAttText::Modify();
if (fTextFont%10 < 2) {
gPad->PaintText(x,y,text1);
return;
}
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);
}
if (gVirtualPS) gVirtualPS->SetBit(kLatex);
TString newText = text1;
if( newText.Length() == 0) return;
fError = 0 ;
if (CheckLatexSyntax(newText)) {
cout<<"\n*ERROR<TLatex>: "<<fError<<endl;
cout<<"==> "<<text1<<endl;
return ;
}
fError = 0 ;
Int_t length = newText.Length() ;
const Char_t *text = newText.Data() ;
fX=x;
fY=y;
x = gPad->XtoAbsPixel(x);
y = gPad->YtoAbsPixel(y);
fShow = kFALSE ;
TLatexFormSize fs = FirstParse(angle,size,text);
fOriginSize = size;
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) {
cout<<"*ERROR<TLatex>: "<<fError<<endl;
cout<<"==> "<<text<<endl;
} else {
fShow = kTRUE;
newSpec.fSize = size;
switch (valign) {
case 0: y -= fs.Under() ; break;
case 1: break;
case 2: y += fs.Height()*0.5-fs.Under(); y++; break;
case 3: y += fs.Over() ; break;
}
switch (halign) {
case 2: x -= fs.Width()/2 ; break;
case 3: x -= fs.Width() ; break;
}
Analyse(x,y,newSpec,text,length);
}
SetTextSize(saveSize);
SetTextAngle(angle);
SetTextFont(saveFont);
SetTextColor(spec.fColor);
SetTextAlign(valign+10*halign);
SetLineWidth(lineW);
SetLineColor(lineC);
delete[] fTabSize;
if (gVirtualPS) gVirtualPS->ResetBit(kLatex);
}
Int_t TLatex::CheckLatexSyntax(TString &text)
{
const Char_t *kWord1[] = {"{}^{","{}_{","^{","_{","#scale{","#color{","#font{","#sqrt{","#[]{","#{}{","#||{",
"#bar{","#vec{","#dot{","#hat{","#ddot{","#acute{","#grave{","#check{","#tilde{","#slash{",
"\\scale{","\\color{","\\font{","\\sqrt{","\\[]{","\\{}{","\\||{","#(){","\\(){",
"\\bar{","\\vec{","\\dot{","\\hat{","\\ddot{","\\acute{","\\grave{","\\check{"};
const Char_t *kWord2[] = {"#scale[","#color[","#font[","#sqrt[","\\scale[","\\color[","\\font[","\\sqrt["};
const Char_t *kWord3[] = {"#frac{","\\frac{","#splitline{","\\splitline{"} ;
const Char_t *kLeft1[] = {"#left[","\\left[","#left{","\\left{","#left|","\\left|","#left(","\\left("} ;
const Char_t *kLeft2[] = {"#[]{","#[]{","#{}{","#{}{","#||{","#||{","#(){","#(){"} ;
const Char_t *kRight[] = {"#right]","\\right]","#right}","\\right}","#right|","\\right|","#right)","\\right)"} ;
Int_t lkWord1[] = {4,4,2,2,7,7,6,6,4,4,4,
5,5,5,5,6,7,7,7,7,7,
7,7,6,6,4,4,4,4,4,
5,5,5,5,6,7,7,7} ;
Int_t lkWord2[] = {7,7,6,6,7,7,6,6} ;
Int_t lkWord3[] = {6,6,11,11} ;
Int_t nkWord1 = 36, nkWord2 = 6, nkWord3 = 4 ;
Int_t nLeft1 , nRight , nOfLeft, nOfRight;
Int_t lLeft1 = 6 ;
Int_t lLeft2 = 4 ;
Int_t lRight = 7 ;
nLeft1 = nRight = 8 ;
nOfLeft = nOfRight = 0 ;
Int_t i,k ;
Char_t buf[11] ; for (i=0;i<11;i++) buf[i]=0;
Bool_t opFound ;
Int_t opFrac = 0;
Int_t length = text.Length() ;
Int_t nOfCurlyBracket, nOfKW1, nOfKW2, nOfKW3, nOfSquareCurly, nOfCurlyCurly ;
Int_t nOfExtraCurly = 0 , nOfExtraSquare = 0;
Int_t nOfSquareBracket = 0 ;
Int_t error = 0 ;
Bool_t quote1 = kFALSE , quote2 = kFALSE;
i = 0 ;
while (i < length) {
strncpy(buf,&text[i],TMath::Min(7,length-i));
opFound = kFALSE ;
for (k = 0 ; k < nLeft1 ; k++) {
if (strncmp(buf,kLeft1[k],lLeft1)==0) {
nOfLeft++ ;
i+=lLeft1 ;
opFound = kTRUE ;
break ;
}
}
if (opFound) continue ;
for(k=0;k<nRight;k++) {
if (strncmp(buf,kRight[k],lRight)==0) {
nOfRight++ ;
i+=lRight ;
opFound = kTRUE ;
break ;
}
}
if (!opFound) i++ ;
}
if (nOfLeft != nOfRight) {
printf(" nOfLeft = %d, nOfRight = %d\n",nOfLeft,nOfRight) ;
error = 1 ;
fError = "Operators \"#left\" and \"#right\" don't match !" ;
goto ERROR_END ;
}
for (k = 0 ; k < nLeft1 ; k++) {
text.ReplaceAll(kLeft1[k],lLeft1,kLeft2[k],lLeft2) ;
}
for (k = 0 ; k < nRight ; k++) {
text.ReplaceAll(kRight[k],lRight,"}",1) ;
}
length = text.Length() ;
i = nOfCurlyBracket = nOfKW1 = nOfKW2 = nOfKW3 = nOfSquareCurly = nOfCurlyCurly =0 ;
while (i< length){
switch (text[i]) {
case '"' : quote1 = !quote1 ; break ;
case '\'': quote2 = !quote2 ; break ;
}
strncpy(buf,&text[i],TMath::Min(11,length-i));
opFound = kFALSE ;
for(k=0;k<nkWord1;k++) {
if (strncmp(buf,kWord1[k],lkWord1[k])==0) {
nOfKW1++ ;
i+=lkWord1[k] ;
opFound = kTRUE ;
nOfCurlyBracket++ ;
break ;
}
}
if (opFound) continue ;
for(k=0;k<nkWord2;k++) {
if (strncmp(buf,kWord2[k],lkWord2[k])==0) {
nOfKW2++ ;
i+=lkWord2[k] ;
opFound = kTRUE ;
nOfSquareBracket++;
break ;
}
}
if (opFound) continue ;
for(k=0;k<nkWord3;k++) {
if (strncmp(buf,kWord3[k],lkWord3[k])==0) {
nOfKW3++ ;
i+=lkWord3[k] ;
opFound = kTRUE ;
opFrac++ ;
nOfCurlyBracket++ ;
break ;
}
}
if (opFound) continue ;
if (strncmp(buf,"}{",2) == 0 && opFrac) {
opFrac-- ;
nOfCurlyCurly++ ;
i+= 2;
}
else if (strncmp(buf,"]{",2) == 0 && nOfSquareBracket) {
nOfSquareCurly++ ;
i+= 2 ;
nOfCurlyBracket++ ;
nOfSquareBracket-- ;
}
else if (strncmp(buf,"@{",2) == 0 || strncmp(buf,"@}",2) == 0) {
i+= 2 ;
}
else if (strncmp(buf,"@[",2) == 0 || strncmp(buf,"@]",2) == 0) {
i+= 2 ;
}
else if (text[i] == ']' ) {
text.Insert(i,"@") ;
length++ ;
i+=2 ;
nOfExtraSquare-- ;
}
else if (text[i] == '[' ) {
text.Insert(i,"@") ;
length++ ;
i+=2 ;
nOfExtraSquare++ ;
}
else if (text[i] == '{' ) {
text.Insert(i,"@") ;
length++ ;
i+=2 ;
nOfExtraCurly++ ;
}
else if (text[i] == '}' ) {
if ( nOfCurlyBracket) {
nOfCurlyBracket-- ;
i++ ;
} else {
text.Insert(i,"@") ;
length++ ;
i+=2 ;
nOfExtraCurly-- ;
}
} else {
i++ ;
buf[1] = 0 ;
}
}
if (nOfKW2 != nOfSquareCurly) {
error = 1 ;
fError = "Invalid number of \"]{\"" ;
}
else if (nOfKW3 != nOfCurlyCurly) {
error = 1 ;
fError = "Error in syntax of \"#frac\"" ;
}
else if (nOfCurlyBracket < 0) {
error = 1 ;
fError = "Missing \"{\"" ;
}
else if (nOfCurlyBracket > 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)
{
fError = 0;
fTabMax = 100;
fTabSize = new FormSize_t[fTabMax];
fPos = 0;
fShow = kFALSE;
fOriginSize = size;
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
{
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()
{
if (!gPad) return 0;
TString newText = GetTitle();
if( newText.Length() == 0) return 0;
fError = 0 ;
if (CheckLatexSyntax(newText)) {
cout<<"\n*ERROR<TLatex>: "<<fError<<endl;
cout<<"==> "<<GetTitle()<<endl;
return 0;
}
fError = 0 ;
const Char_t *text = newText.Data() ;
Double_t angle_old = GetTextAngle();
TLatexFormSize fs = FirstParse(0,GetTextSize(),text);
SetTextAngle(angle_old);
delete[] fTabSize;
return TMath::Abs(gPad->AbsPixeltoX(Int_t(fs.Width())) - gPad->AbsPixeltoX(0));
}
void TLatex::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle)
{
if (!gPad) return;
TString newText = GetTitle();
if( newText.Length() == 0) return;
fError = 0 ;
if (CheckLatexSyntax(newText)) {
cout<<"\n*ERROR<TLatex>: "<<fError<<endl;
cout<<"==> "<<GetTitle()<<endl;
return;
}
fError = 0 ;
if (angle) {
Int_t cBoxX[4], cBoxY[4];
Int_t ptx, pty;
if (TestBit(kTextNDC)) {
ptx = gPad->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()
{
if (!gPad) return 0;
TString newText = GetTitle();
if( newText.Length() == 0) return 0;
fError = 0 ;
if (CheckLatexSyntax(newText)) {
cout<<"\n*ERROR<TLatex>: "<<fError<<endl;
cout<<"==> "<<GetTitle()<<endl;
return 0;
}
fError = 0 ;
const Char_t *text = newText.Data() ;
TLatexFormSize fs = FirstParse(0,GetTextSize(),text);
delete[] fTabSize;
return TMath::Abs(gPad->AbsPixeltoY(Int_t(fs.Height())) - gPad->AbsPixeltoY(0));
}
TLatexFormSize TLatex::Readfs()
{
fPos--;
TLatexFormSize result(fTabSize[fPos].fWidth,fTabSize[fPos].fOver,fTabSize[fPos].fUnder);
return result;
}
void TLatex::Savefs(TLatexFormSize *fs)
{
fTabSize[fPos].fWidth = fs->Width();
fTabSize[fPos].fOver = fs->Over();
fTabSize[fPos].fUnder = fs->Under();
fPos++;
if (fPos>=fTabMax) {
FormSize_t *temp = new FormSize_t[fTabMax+100];
memcpy(temp,fTabSize,fTabMax*sizeof(FormSize_t));
fTabMax += 100;
delete [] fTabSize;
fTabSize = temp;
}
}
void TLatex::SavePrimitive(ostream &out, Option_t * )
{
char quote = '"';
if (gROOT->ClassSaved(TLatex::Class())) {
out<<" ";
} else {
out<<" TLatex *";
}
TString s = GetTitle();
s.ReplaceAll("\"","\\\"");
out<<" tex = new TLatex("<<fX<<","<<fY<<","<<quote<<s.Data()<<quote<<");"<<endl;
if (TestBit(kTextNDC)) out<<"tex->SetNDC();"<<endl;
SaveTextAttributes(out,"tex",11,0,1,62,0.05);
SaveLineAttributes(out,"tex",1,1,1);
out<<" tex->Draw();"<<endl;
}
void TLatex::SetIndiceSize(Double_t factorSize)
{
fFactorSize = factorSize;
}
void TLatex::SetLimitIndiceSize(Int_t limitFactorSize)
{
fLimitFactorSize = limitFactorSize;
}
Last change: Mon Dec 1 17:07:10 2008
Last generated: 2008-12-01 17:07
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.