00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "Riostream.h"
00013 #include "TROOT.h"
00014 #include "TVirtualPad.h"
00015 #include "TText.h"
00016 #include "TTF.h"
00017 #include "TVirtualX.h"
00018 #include "TMath.h"
00019 #include "TPoint.h"
00020 #include "TClass.h"
00021
00022 ClassImp(TText)
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 TText::TText(): TNamed(), TAttText()
00039 {
00040
00041
00042 fX = 0.;
00043 fY = 0.;
00044 }
00045
00046
00047
00048 TText::TText(Double_t x, Double_t y, const char *text) : TNamed("",text), TAttText()
00049 {
00050
00051
00052 fX = x;
00053 fY = y;
00054 }
00055
00056
00057
00058 TText::~TText()
00059 {
00060
00061 }
00062
00063
00064
00065 TText::TText(const TText &text) : TNamed(text), TAttText(text)
00066 {
00067
00068
00069 fX = 0.;
00070 fY = 0.;
00071 ((TText&)text).Copy(*this);
00072 }
00073
00074
00075
00076 void TText::Copy(TObject &obj) const
00077 {
00078
00079
00080 ((TText&)obj).fX = fX;
00081 ((TText&)obj).fY = fY;
00082 TNamed::Copy(obj);
00083 TAttText::Copy(((TText&)obj));
00084 }
00085
00086
00087
00088 Int_t TText::DistancetoPrimitive(Int_t px, Int_t py)
00089 {
00090
00091
00092
00093
00094 Int_t ptx, pty;
00095
00096 TAttText::Modify();
00097
00098 if (TestBit(kTextNDC)) {
00099 ptx = gPad->UtoPixel(fX);
00100 pty = gPad->VtoPixel(fY);
00101 } else {
00102 ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX));
00103 pty = gPad->YtoAbsPixel(gPad->YtoPad(fY));
00104 }
00105
00106
00107 Int_t cBoxX[5], cBoxY[5];
00108 GetControlBox(ptx, pty, -fTextAngle, cBoxX, cBoxY);
00109 cBoxY[4] = cBoxY[0];
00110 cBoxX[4] = cBoxX[0];
00111
00112
00113 if(TMath::IsInside(px, py, 5, cBoxX, cBoxY)){
00114 return 0;
00115 } else {
00116 return 9999;
00117 }
00118 }
00119
00120
00121
00122 TText *TText::DrawText(Double_t x, Double_t y, const char *text)
00123 {
00124
00125
00126 TText *newtext = new TText(x, y, text);
00127 TAttText::Copy(*newtext);
00128 newtext->SetBit(kCanDelete);
00129 if (TestBit(kTextNDC)) newtext->SetNDC();
00130 newtext->AppendPad();
00131 return newtext;
00132 }
00133
00134
00135
00136 TText *TText::DrawTextNDC(Double_t x, Double_t y, const char *text)
00137 {
00138
00139
00140 TText *newtext = DrawText(x, y, text);
00141 newtext->SetNDC();
00142 return newtext;
00143 }
00144
00145
00146
00147 void TText::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00148 {
00149
00150
00151
00152
00153
00154 static Int_t px1, py1, pxold, pyold, Size, height, width;
00155 static Bool_t resize,turn;
00156 Int_t dx, dy;
00157 const char *text = GetTitle();
00158 Int_t len = strlen(text);
00159 Double_t sizetowin = gPad->GetAbsHNDC()*Double_t(gPad->GetWh());
00160 Double_t fh = (fTextSize*sizetowin);
00161 Int_t h = Int_t(fh/2);
00162 Int_t w = h*len;
00163 Short_t halign = fTextAlign/10;
00164 Short_t valign = fTextAlign - 10*halign;
00165 Double_t co, si, dtheta, norm;
00166 static Bool_t right;
00167 static Double_t theta;
00168 Int_t ax, ay, bx, by, cx, cy;
00169 ax = ay = 0;
00170 Double_t lambda, x2,y2;
00171 Double_t dpx,dpy,xp1,yp1;
00172 Int_t cBoxX[4], cBoxY[4], part;
00173
00174 if (!gPad->IsEditable()) return;
00175 switch (event) {
00176
00177 case kButton1Down:
00178
00179
00180 case kMouseMotion:
00181 if (TestBit(kTextNDC)) {
00182 px1 = gPad->UtoPixel(fX);
00183 py1 = gPad->VtoPixel(fY);
00184 } else {
00185 px1 = gPad->XtoAbsPixel(gPad->XtoPad(fX));
00186 py1 = gPad->YtoAbsPixel(gPad->YtoPad(fY));
00187 }
00188 theta = fTextAngle;
00189 Size = 0;
00190 pxold = px;
00191 pyold = py;
00192 co = TMath::Cos(fTextAngle*0.017453293);
00193 si = TMath::Sin(fTextAngle*0.017453293);
00194 resize = kFALSE;
00195 turn = kFALSE;
00196 GetControlBox(px1, py1, -theta, cBoxX, cBoxY);
00197 part = (Int_t)(3*((px-cBoxX[0])*co-(py-cBoxY[0])*si)/
00198 ((cBoxX[3]-cBoxX[0])*co-(cBoxY[3]-cBoxY[0])*si));
00199 switch (part) {
00200 case 0:
00201 if (halign == 3) {
00202 turn = kTRUE;
00203 right = kTRUE;
00204 gPad->SetCursor(kRotate);
00205 } else {
00206 resize = kTRUE;
00207 height = valign;
00208 width = halign;
00209 gPad->SetCursor(kArrowVer);
00210 }
00211 break;
00212 case 1:
00213 gPad->SetCursor(kMove);
00214 break;
00215 case 2:
00216 if (halign == 3) {
00217 resize = kTRUE;
00218 height = valign;
00219 width = halign;
00220 gPad->SetCursor(kArrowVer);
00221 } else {
00222 turn = kTRUE;
00223 right = kFALSE;
00224 gPad->SetCursor(kRotate);
00225 }
00226 }
00227 break;
00228
00229 case kButton1Motion:
00230 PaintControlBox(px1, py1, -theta);
00231 if (turn) {
00232 norm = TMath::Sqrt(Double_t((py-py1)*(py-py1)+(px-px1)*(px-px1)));
00233 if (norm>0) {
00234 theta = TMath::ACos((px-px1)/norm);
00235 dtheta= TMath::ASin((py1-py)/norm);
00236 if (dtheta<0) theta = -theta;
00237 theta = theta/TMath::ACos(-1)*180;
00238 if (theta<0) theta += 360;
00239 if (right) {theta = theta+180; if (theta>=360) theta -= 360;}
00240 }
00241 }
00242 else if (resize) {
00243
00244 co = TMath::Cos(fTextAngle*0.017453293);
00245 si = TMath::Sin(fTextAngle*0.017453293);
00246 if (width == 1) {
00247 switch (valign) {
00248 case 1 : ax = px1; ay = py1; break;
00249 case 2 : ax = px1+Int_t(si*h/2); ay = py1+Int_t(co*h/2); break;
00250 case 3 : ax = px1+Int_t(si*h*3/2); ay = py1+Int_t(co*h*3/2); break;
00251 }
00252 }
00253 if (width == 2) {
00254 switch (valign) {
00255 case 1 : ax = px1-Int_t(co*w/2); ay = py1+Int_t(si*w/2); break;
00256 case 2 : ax = px1-Int_t(co*w/2+si*h/2); ay = py1+Int_t(si*w/2+co*h/2); break;
00257 case 3 : ax = px1-Int_t(co*w/2+si*h*3/2); ay = py1+Int_t(si*w/2+co*h*3/2); break;
00258 }
00259 }
00260 if (width == 3) {
00261 switch (valign) {
00262 case 1 : ax = px1-Int_t(co*w); ay = py1+Int_t(si*w); break;
00263 case 2 : ax = px1-Int_t(co*w+si*h/2); ay = py1+Int_t(si*w+co*h/2); break;
00264 case 3 : ax = px1-Int_t(co*w+si*h*3/2); ay = py1+Int_t(si*w+co*h*3/2); break;
00265 }
00266 }
00267 if (height == 3) {bx = ax-Int_t(si*h); by = ay-Int_t(co*h);}
00268 else {bx = ax; by = ay;}
00269 cx = bx+Int_t(co*w); cy = by-Int_t(si*w);
00270 lambda = Double_t(((px-bx)*(cx-bx)+(py-by)*(cy-by)))/Double_t(((cx-bx)*(cx-bx)+(cy-by)*(cy-by)));
00271 x2 = Double_t(px) - lambda*Double_t(cx-bx)-Double_t(bx);
00272 y2 = Double_t(py) - lambda*Double_t(cy-by)-Double_t(by);
00273 Size = Int_t(TMath::Sqrt(x2*x2+y2*y2)*2);
00274 if (Size<4) Size = 4;
00275
00276 SetTextSize(Size/sizetowin);
00277 TAttText::Modify();
00278 }
00279 else {
00280 dx = px - pxold; px1 += dx;
00281 dy = py - pyold; py1 += dy;
00282 }
00283 PaintControlBox(px1, py1, -theta);
00284 pxold = px; pyold = py;
00285 break;
00286
00287 case kButton1Up:
00288 if (TestBit(kTextNDC)) {
00289 dpx = gPad->GetX2() - gPad->GetX1();
00290 dpy = gPad->GetY2() - gPad->GetY1();
00291 xp1 = gPad->GetX1();
00292 yp1 = gPad->GetY1();
00293 fX = (gPad->AbsPixeltoX(px1)-xp1)/dpx;
00294 fY = (gPad->AbsPixeltoY(py1)-yp1)/dpy;
00295 } else {
00296 fX = gPad->PadtoX(gPad->AbsPixeltoX(px1));
00297 fY = gPad->PadtoY(gPad->AbsPixeltoY(py1));
00298 }
00299 fTextAngle = theta;
00300 gPad->Modified(kTRUE);
00301 break;
00302
00303 case kButton1Locate:
00304 ExecuteEvent(kButton1Down, px, py);
00305
00306 while (1) {
00307 px = py = 0;
00308 event = gVirtualX->RequestLocator(1, 1, px, py);
00309
00310 ExecuteEvent(kButton1Motion, px, py);
00311
00312 if (event != -1) {
00313 ExecuteEvent(kButton1Up, px, py);
00314 return;
00315 }
00316 }
00317 }
00318 }
00319
00320
00321
00322 void TText::GetControlBox(Int_t x, Int_t y, Double_t theta,
00323 Int_t cBoxX[4], Int_t cBoxY[4])
00324 {
00325
00326
00327
00328
00329 Short_t halign = fTextAlign/10;
00330 Short_t valign = fTextAlign - 10*halign;
00331 UInt_t cBoxW, cBoxH;
00332 UInt_t Dx = 0, Dy = 0;
00333
00334 GetBoundingBox(cBoxW, cBoxH);
00335
00336
00337 switch (halign) {
00338 case 1 : Dx = 0 ; break;
00339 case 2 : Dx = cBoxW/2; break;
00340 case 3 : Dx = cBoxW ; break;
00341 }
00342 switch (valign) {
00343 case 1 : Dy = 0 ; break;
00344 case 2 : Dy = cBoxH/2; break;
00345 case 3 : Dy = cBoxH ; break;
00346 }
00347
00348
00349 cBoxX[0] = x-Dx;
00350 cBoxY[0] = y+Dy;
00351 cBoxX[1] = x-Dx;
00352 cBoxY[1] = y-cBoxH+Dy;
00353 cBoxX[2] = x+cBoxW-Dx;
00354 cBoxY[2] = y-cBoxH+Dy;
00355 cBoxX[3] = x+cBoxW-Dx;
00356 cBoxY[3] = y+Dy;
00357
00358
00359 if (theta) {
00360 Double_t cosTheta = TMath::Cos(theta*0.017453293);
00361 Double_t sinTheta = TMath::Sin(theta*0.017453293);
00362 for (int i=0; i<4 ; i++) {
00363 Int_t hcBoxX = cBoxX[i];
00364 Int_t hcBoxY = cBoxY[i];
00365 cBoxX[i] = (Int_t)((hcBoxX-x)*cosTheta-(hcBoxY-y)*sinTheta+x);
00366 cBoxY[i] = (Int_t)((hcBoxX-x)*sinTheta+(hcBoxY-y)*cosTheta+y);
00367 }
00368 }
00369 }
00370
00371
00372
00373 void TText::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle)
00374 {
00375
00376
00377
00378
00379 if (angle) {
00380 Int_t cBoxX[4], cBoxY[4];
00381 Int_t ptx, pty;
00382 if (TestBit(kTextNDC)) {
00383 ptx = gPad->UtoPixel(fX);
00384 pty = gPad->VtoPixel(fY);
00385 } else {
00386 ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX));
00387 pty = gPad->YtoAbsPixel(gPad->YtoPad(fY));
00388 }
00389 GetControlBox(ptx, pty, fTextAngle, cBoxX, cBoxY);
00390 Int_t x1 = cBoxX[0];
00391 Int_t x2 = cBoxX[0];
00392 Int_t y1 = cBoxY[0];
00393 Int_t y2 = cBoxY[0];
00394 for (Int_t i=1; i<4; i++) {
00395 if (cBoxX[i] < x1) x1 = cBoxX[i];
00396 if (cBoxX[i] > x2) x2 = cBoxX[i];
00397 if (cBoxY[i] < y1) y1 = cBoxY[i];
00398 if (cBoxY[i] > y2) y2 = cBoxY[i];
00399 }
00400 w = x2-x1;
00401 h = y2-y1;
00402 } else {
00403 if ((gVirtualX->HasTTFonts() && TTF::IsInitialized()) || gPad->IsBatch()) {
00404 TTF::GetTextExtent(w, h, (char*)GetTitle());
00405 } else {
00406 gVirtualX->GetTextExtent(w, h, (char*)GetTitle());
00407 }
00408 }
00409 }
00410
00411
00412
00413 void TText::GetTextAscentDescent(UInt_t &a, UInt_t &d, const char *text) const
00414 {
00415
00416
00417
00418
00419 Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
00420 Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
00421 Double_t tsize;
00422 if (wh < hh) tsize = fTextSize*wh;
00423 else tsize = fTextSize*hh;
00424
00425 if (gVirtualX->HasTTFonts() || gPad->IsBatch()) {
00426 TTF::SetTextFont(fTextFont);
00427 TTF::SetTextSize(tsize);
00428 a = TTF::GetBox().yMax;
00429 d = TMath::Abs(TTF::GetBox().yMin);
00430 } else {
00431 gVirtualX->SetTextSize((int)tsize);
00432 a = gVirtualX->GetFontAscent();
00433 if (!a) {
00434 UInt_t w;
00435 gVirtualX->GetTextExtent(w, a, (char*)text);
00436 }
00437 d = gVirtualX->GetFontDescent();
00438 }
00439 }
00440
00441
00442
00443 void TText::GetTextExtent(UInt_t &w, UInt_t &h, const char *text) const
00444 {
00445
00446
00447
00448
00449 Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
00450 Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
00451 Double_t tsize;
00452 if (wh < hh) tsize = fTextSize*wh;
00453 else tsize = fTextSize*hh;
00454
00455 if (gVirtualX->HasTTFonts() || gPad->IsBatch()) {
00456 TTF::SetTextFont(fTextFont);
00457 TTF::SetTextSize(tsize);
00458 TTF::GetTextExtent(w, h, (char*)text);
00459 } else {
00460 gVirtualX->SetTextSize((int)tsize);
00461 gVirtualX->GetTextExtent(w, h, (char*)text);
00462 }
00463 }
00464
00465
00466
00467 void TText::GetTextAdvance(UInt_t &a, const char *text, const Bool_t kern) const
00468 {
00469
00470
00471
00472
00473 Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
00474 Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
00475 Double_t tsize;
00476 if (wh < hh) tsize = fTextSize*wh;
00477 else tsize = fTextSize*hh;
00478
00479 if (gVirtualX->HasTTFonts() || gPad->IsBatch()) {
00480 Bool_t kernsave = TTF::GetKerning();
00481 TTF::SetKerning(kern);
00482 TTF::SetTextFont(fTextFont);
00483 TTF::SetTextSize(tsize);
00484 TTF::GetTextAdvance(a, (char*)text);
00485 TTF::SetKerning(kernsave);
00486 } else {
00487 UInt_t h;
00488 gVirtualX->SetTextSize((int)tsize);
00489 gVirtualX->GetTextExtent(a, h, (char*)text);
00490 }
00491 }
00492
00493
00494
00495 void TText::ls(Option_t *) const
00496 {
00497
00498
00499 TROOT::IndentLevel();
00500 printf("Text X=%f Y=%f Text=%s\n",fX,fY,GetTitle());
00501 }
00502
00503
00504
00505 void TText::Paint(Option_t *)
00506 {
00507
00508
00509 TAttText::Modify();
00510 if (TestBit(kTextNDC)) gPad->PaintTextNDC(fX,fY,GetTitle());
00511 else gPad->PaintText(gPad->XtoPad(fX),gPad->YtoPad(fY),GetTitle());
00512 }
00513
00514
00515
00516 void TText::PaintControlBox(Int_t x, Int_t y, Double_t theta)
00517 {
00518
00519
00520
00521 Int_t cBoxX[4], cBoxY[4];
00522 Short_t halign = fTextAlign/10;
00523 Short_t valign = fTextAlign - 10*halign;
00524
00525 GetControlBox(x, y, theta, cBoxX, cBoxY);
00526
00527 gVirtualX->SetLineStyle((Style_t)1);
00528 gVirtualX->SetLineWidth(1);
00529 gVirtualX->SetLineColor(1);
00530 gVirtualX->DrawLine(cBoxX[0], cBoxY[0], cBoxX[1], cBoxY[1]);
00531 gVirtualX->DrawLine(cBoxX[1], cBoxY[1], cBoxX[2], cBoxY[2]);
00532 gVirtualX->DrawLine(cBoxX[2], cBoxY[2], cBoxX[3], cBoxY[3]);
00533 gVirtualX->DrawLine(cBoxX[3], cBoxY[3], cBoxX[0], cBoxY[0]);
00534
00535
00536 TPoint p;
00537 Int_t ix = 0, iy = 0;
00538 switch (halign) {
00539 case 1 :
00540 switch (valign) {
00541 case 1 : ix = 0 ; iy = 0 ; break;
00542 case 2 : ix = 0 ; iy = 1 ; break;
00543 case 3 : ix = 1 ; iy = 1 ; break;
00544 }
00545 break;
00546 case 2 :
00547 switch (valign) {
00548 case 1 : ix = 0 ; iy = 3 ; break;
00549 case 2 : ix = 0 ; iy = 2 ; break;
00550 case 3 : ix = 1 ; iy = 2 ; break;
00551 }
00552 break;
00553 case 3 :
00554 switch (valign) {
00555 case 1 : ix = 3 ; iy = 3 ; break;
00556 case 2 : ix = 2 ; iy = 3 ; break;
00557 case 3 : ix = 2 ; iy = 2 ; break;
00558 }
00559 break;
00560 }
00561 p.fX = (cBoxX[ix]+cBoxX[iy])/2;
00562 p.fY = (cBoxY[ix]+cBoxY[iy])/2;
00563 gVirtualX->SetMarkerColor(1);
00564 gVirtualX->SetMarkerStyle(24);
00565 gVirtualX->SetMarkerSize(0.7);
00566 gVirtualX->DrawPolyMarker(1, &p);
00567 }
00568
00569
00570
00571 void TText::PaintText(Double_t x, Double_t y, const char *text)
00572 {
00573
00574
00575 TAttText::Modify();
00576 gPad->PaintText(x,y,text);
00577 }
00578
00579
00580
00581 void TText::PaintTextNDC(Double_t u, Double_t v, const char *text)
00582 {
00583
00584
00585 TAttText::Modify();
00586 gPad->PaintTextNDC(u,v,text);
00587 }
00588
00589
00590
00591 void TText::Print(Option_t *) const
00592 {
00593
00594
00595 printf("Text X=%f Y=%f Text=%s Font=%d Size=%f",fX,fY,GetTitle(),GetTextFont(),GetTextSize());
00596 if (GetTextColor() != 1 ) printf(" Color=%d",GetTextColor());
00597 if (GetTextAlign() != 10) printf(" Align=%d",GetTextAlign());
00598 if (GetTextAngle() != 0 ) printf(" Angle=%f",GetTextAngle());
00599 printf("\n");
00600 }
00601
00602
00603
00604 void TText::SavePrimitive(ostream &out, Option_t * )
00605 {
00606
00607
00608 char quote = '"';
00609 if (gROOT->ClassSaved(TText::Class())) {
00610 out<<" ";
00611 } else {
00612 out<<" TText *";
00613 }
00614 TString s = GetTitle();
00615 s.ReplaceAll("\"","\\\"");
00616 out<<"text = new TText("<<fX<<","<<fY<<","<<quote<<s.Data()<<quote<<");"<<endl;
00617 if (TestBit(kTextNDC)) out<<" text->SetNDC();"<<endl;
00618
00619 SaveTextAttributes(out,"text",11,0,1,62,0.05);
00620
00621 out<<" text->Draw();"<<endl;
00622 }
00623
00624
00625
00626 void TText::SetNDC(Bool_t isNDC)
00627 {
00628
00629
00630 ResetBit(kTextNDC);
00631 if (isNDC) SetBit(kTextNDC);
00632 }
00633
00634
00635
00636 void TText::Streamer(TBuffer &R__b)
00637 {
00638
00639
00640 if (R__b.IsReading()) {
00641 UInt_t R__s, R__c;
00642 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
00643 if (R__v > 1) {
00644 R__b.ReadClassBuffer(TText::Class(), this, R__v, R__s, R__c);
00645 return;
00646 }
00647
00648 TNamed::Streamer(R__b);
00649 TAttText::Streamer(R__b);
00650 Float_t x,y;
00651 R__b >> x; fX = x;
00652 R__b >> y; fY = y;
00653
00654
00655 } else {
00656 R__b.WriteClassBuffer(TText::Class(),this);
00657 }
00658 }