17 # include <ft2build.h>
18 # include FT_FREETYPE_H
60 TText::TText(Double_t x, Double_t y,
const char *text) : TNamed(
"",text), TAttText(), fWcsTitle(nullptr)
69 TText::TText(Double_t x, Double_t y,
const wchar_t *text) : TNamed(), TAttText()
73 fWcsTitle =
new std::wstring(text);
83 if (fWcsTitle)
delete reinterpret_cast<std::wstring *
>(fWcsTitle);
89 TText::TText(
const TText &text) : TNamed(text), TAttText(text), TAttBBox2D(text), fWcsTitle(nullptr)
91 text.TText::Copy(*
this);
97 TText &TText::operator=(
const TText &src)
99 src.TText::Copy(*
this);
106 void TText::Copy(TObject &obj)
const
108 ((TText&)obj).fX = fX;
109 ((TText&)obj).fY = fY;
111 TAttText::Copy(((TText&)obj));
112 if (((TText&)obj).fWcsTitle != NULL) {
113 if (fWcsTitle != NULL) {
114 *
reinterpret_cast<std::wstring*
>(&((TText&)obj).fWcsTitle) = *reinterpret_cast<const std::wstring*>(&fWcsTitle);
116 delete reinterpret_cast<std::wstring*
>(&((TText&)obj).fWcsTitle);
117 ((TText&)obj).fWcsTitle = NULL;
120 if (fWcsTitle != NULL) {
121 ((TText&)(obj)).fWcsTitle =
new std::wstring(*reinterpret_cast<const std::wstring*>(fWcsTitle));
129 const void *TText::GetWcsTitle(
void)
const
131 if (fWcsTitle != NULL) {
132 return reinterpret_cast<std::wstring *
>(fWcsTitle)->c_str();
143 Int_t TText::DistancetoPrimitive(Int_t px, Int_t py)
149 if (TestBit(kTextNDC)) {
150 ptx = gPad->UtoPixel(fX);
151 pty = gPad->VtoPixel(fY);
153 ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX));
154 pty = gPad->YtoAbsPixel(gPad->YtoPad(fY));
158 Int_t cBoxX[5], cBoxY[5];
159 GetControlBox(ptx, pty, -fTextAngle, cBoxX, cBoxY);
164 if (TMath::IsInside(px, py, 5, cBoxX, cBoxY)){
174 TText *TText::DrawText(Double_t x, Double_t y,
const char *text)
176 TText *newtext =
new TText(x, y, text);
177 TAttText::Copy(*newtext);
178 newtext->SetBit(kCanDelete);
179 if (TestBit(kTextNDC)) newtext->SetNDC();
180 newtext->AppendPad();
187 TText *TText::DrawText(Double_t x, Double_t y,
const wchar_t *text)
189 TText *newtext =
new TText(x, y, text);
190 TAttText::Copy(*newtext);
191 newtext->SetBit(kCanDelete);
192 if (TestBit(kTextNDC)) newtext->SetNDC();
193 newtext->AppendPad();
200 TText *TText::DrawTextNDC(Double_t x, Double_t y,
const char *text)
202 TText *newtext = DrawText(x, y, text);
210 TText *TText::DrawTextNDC(Double_t x, Double_t y,
const wchar_t *text)
212 TText *newtext = DrawText(x, y, text);
223 void TText::ExecuteEvent(Int_t event, Int_t px, Int_t py)
227 static Int_t px1, py1, pxold, pyold, Size, height, width;
228 static Bool_t resize,turn;
230 const char *text = GetTitle();
231 Int_t len = strlen(text);
232 Double_t sizetowin = gPad->GetAbsHNDC()*Double_t(gPad->GetWh());
233 Double_t fh = (fTextSize*sizetowin);
234 Int_t h = Int_t(fh/2);
236 Short_t halign = fTextAlign/10;
237 Short_t valign = fTextAlign - 10*halign;
238 Double_t co, si, dtheta, norm;
239 static Bool_t right, ndcsav;
240 static Double_t theta;
241 Int_t ax, ay, bx, by, cx, cy;
243 Double_t lambda, x2,y2;
244 Double_t dpx,dpy,xp1,yp1;
245 Int_t cBoxX[4], cBoxY[4], part;
247 Bool_t opaque = gPad->OpaqueMoving();
249 if (!gPad->IsEditable())
return;
254 ndcsav = TestBit(kTextNDC);
258 if (TestBit(kTextNDC)) {
259 px1 = gPad->UtoPixel(fX);
260 py1 = gPad->VtoPixel(fY);
262 px1 = gPad->XtoAbsPixel(gPad->XtoPad(fX));
263 py1 = gPad->YtoAbsPixel(gPad->YtoPad(fY));
269 co = TMath::Cos(fTextAngle*0.017453293);
270 si = TMath::Sin(fTextAngle*0.017453293);
273 GetControlBox(px1, py1, -theta, cBoxX, cBoxY);
274 div = ((cBoxX[3]-cBoxX[0])*co-(cBoxY[3]-cBoxY[0])*si);
275 if (TMath::Abs(div) > 1e-8) part = (Int_t)(3*((px-cBoxX[0])*co-(py-cBoxY[0])*si)/ div);
282 gPad->SetCursor(kRotate);
287 gPad->SetCursor(kArrowVer);
291 gPad->SetCursor(kMove);
298 gPad->SetCursor(kArrowVer);
302 gPad->SetCursor(kRotate);
307 case kArrowKeyRelease:
309 if (!opaque) PaintControlBox(px1, py1, -theta);
311 norm = TMath::Sqrt(Double_t((py-py1)*(py-py1)+(px-px1)*(px-px1)));
313 theta = TMath::ACos((px-px1)/norm);
314 dtheta= TMath::ASin((py1-py)/norm);
315 if (dtheta<0) theta = -theta;
316 theta = theta/TMath::ACos(-1)*180;
317 if (theta<0) theta += 360;
318 if (right) {theta = theta+180;
if (theta>=360) theta -= 360;}
322 co = TMath::Cos(fTextAngle*0.017453293);
323 si = TMath::Sin(fTextAngle*0.017453293);
326 case 1 : ax = px1; ay = py1;
break;
327 case 2 : ax = px1+Int_t(si*h/2); ay = py1+Int_t(co*h/2);
break;
328 case 3 : ax = px1+Int_t(si*h*3/2); ay = py1+Int_t(co*h*3/2);
break;
333 case 1 : ax = px1-Int_t(co*w/2); ay = py1+Int_t(si*w/2);
break;
334 case 2 : ax = px1-Int_t(co*w/2+si*h/2); ay = py1+Int_t(si*w/2+co*h/2);
break;
335 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;
340 case 1 : ax = px1-Int_t(co*w); ay = py1+Int_t(si*w);
break;
341 case 2 : ax = px1-Int_t(co*w+si*h/2); ay = py1+Int_t(si*w+co*h/2);
break;
342 case 3 : ax = px1-Int_t(co*w+si*h*3/2); ay = py1+Int_t(si*w+co*h*3/2);
break;
345 if (height == 3) {bx = ax-Int_t(si*h); by = ay-Int_t(co*h);}
346 else {bx = ax; by = ay;}
347 cx = bx+Int_t(co*w); cy = by-Int_t(si*w);
348 lambda = Double_t(((px-bx)*(cx-bx)+(py-by)*(cy-by)))/Double_t(((cx-bx)*(cx-bx)+(cy-by)*(cy-by)));
349 x2 = Double_t(px) - lambda*Double_t(cx-bx)-Double_t(bx);
350 y2 = Double_t(py) - lambda*Double_t(cy-by)-Double_t(by);
351 Size = Int_t(TMath::Sqrt(x2*x2+y2*y2)*2);
352 if (Size<4) Size = 4;
354 SetTextSize(Size/sizetowin);
357 dx = px - pxold; px1 += dx;
358 dy = py - pyold; py1 += dy;
361 if (ndcsav) this->SetNDC(kFALSE);
362 this->SetX(gPad->PadtoX(gPad->AbsPixeltoX(px1)));
363 this->SetY(gPad->PadtoY(gPad->AbsPixeltoY(py1)));
364 if (resize) gPad->ShowGuidelines(
this, event,
't',
false);
365 if ((!resize)&&(!turn)) gPad->ShowGuidelines(
this, event,
'i',
true);
366 gPad->ShowGuidelines(
this, event, !resize&!turn);
367 this->SetTextAngle(theta);
368 gPad->Modified(kTRUE);
371 if (!opaque) PaintControlBox(px1, py1, -theta);
372 pxold = px; pyold = py;
377 if (ndcsav && !this->TestBit(kTextNDC)) {
378 this->SetX((fX - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1()));
379 this->SetY((fY - gPad->GetY1())/(gPad->GetY2()-gPad->GetY1()));
382 gPad->ShowGuidelines(
this, event, !resize&!turn);
384 if (TestBit(kTextNDC)) {
385 dpx = gPad->GetX2() - gPad->GetX1();
386 dpy = gPad->GetY2() - gPad->GetY1();
389 fX = (gPad->AbsPixeltoX(px1)-xp1)/dpx;
390 fY = (gPad->AbsPixeltoY(py1)-yp1)/dpy;
392 fX = gPad->PadtoX(gPad->AbsPixeltoX(px1));
393 fY = gPad->PadtoY(gPad->AbsPixeltoY(py1));
397 gPad->Modified(kTRUE);
401 ExecuteEvent(kButton1Down, px, py);
405 event = gVirtualX->RequestLocator(1, 1, px, py);
407 ExecuteEvent(kButton1Motion, px, py);
410 ExecuteEvent(kButton1Up, px, py);
422 void TText::GetControlBox(Int_t x, Int_t y, Double_t theta,
423 Int_t cBoxX[4], Int_t cBoxY[4])
425 Short_t halign = fTextAlign/10;
426 Short_t valign = fTextAlign - 10*halign;
428 UInt_t Dx = 0, Dy = 0;
430 GetBoundingBox(cBoxW, cBoxH);
434 case 1 : Dx = 0 ;
break;
435 case 2 : Dx = cBoxW/2;
break;
436 case 3 : Dx = cBoxW ;
break;
439 case 1 : Dy = 0 ;
break;
440 case 2 : Dy = cBoxH/2;
break;
441 case 3 : Dy = cBoxH ;
break;
448 cBoxY[1] = y-cBoxH+Dy;
449 cBoxX[2] = x+cBoxW-Dx;
450 cBoxY[2] = y-cBoxH+Dy;
451 cBoxX[3] = x+cBoxW-Dx;
456 Double_t cosTheta = TMath::Cos(theta*0.017453293);
457 Double_t sinTheta = TMath::Sin(theta*0.017453293);
458 for (
int i=0; i<4 ; i++) {
459 Int_t hcBoxX = cBoxX[i];
460 Int_t hcBoxY = cBoxY[i];
461 cBoxX[i] = (Int_t)((hcBoxX-x)*cosTheta-(hcBoxY-y)*sinTheta+x);
462 cBoxY[i] = (Int_t)((hcBoxX-x)*sinTheta+(hcBoxY-y)*cosTheta+y);
472 void TText::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle)
474 const char *text = GetTitle();
481 Int_t cBoxX[4], cBoxY[4];
483 if (TestBit(kTextNDC)) {
484 ptx = gPad->UtoPixel(fX);
485 pty = gPad->VtoPixel(fY);
487 ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX));
488 pty = gPad->YtoAbsPixel(gPad->YtoPad(fY));
490 GetControlBox(ptx, pty, fTextAngle, cBoxX, cBoxY);
495 for (Int_t i=1; i<4; i++) {
496 if (cBoxX[i] < x1) x1 = cBoxX[i];
497 if (cBoxX[i] > x2) x2 = cBoxX[i];
498 if (cBoxY[i] < y1) y1 = cBoxY[i];
499 if (cBoxY[i] > y2) y2 = cBoxY[i];
504 if ((gVirtualX->HasTTFonts() && TTF::IsInitialized()) || gPad->IsBatch()) {
505 TTF::GetTextExtent(w, h, (
char*)GetTitle());
507 const Font_t oldFont = gVirtualX->GetTextFont();
508 if (gVirtualX->InheritsFrom(
"TGCocoa"))
509 gVirtualX->SetTextFont(fTextFont);
510 gVirtualX->GetTextExtent(w, h, (
char*)GetTitle());
511 if (gVirtualX->InheritsFrom(
"TGCocoa"))
512 gVirtualX->SetTextFont(oldFont);
522 void TText::GetTextAscentDescent(UInt_t &a, UInt_t &d,
const char *text)
const
524 Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
525 Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
527 if (wh < hh) tsize = fTextSize*wh;
528 else tsize = fTextSize*hh;
530 if (gVirtualX->HasTTFonts() || gPad->IsBatch()) {
531 TTF::SetTextFont(fTextFont);
532 TTF::SetTextSize(tsize);
533 a = TTF::GetBox().yMax;
534 d = TMath::Abs(TTF::GetBox().yMin);
536 const Font_t oldFont = gVirtualX->GetTextFont();
537 if (gVirtualX->InheritsFrom(
"TGCocoa"))
538 gVirtualX->SetTextFont(fTextFont);
539 gVirtualX->SetTextSize(tsize);
540 a = gVirtualX->GetFontAscent(text);
543 gVirtualX->GetTextExtent(w, a, (
char*)text);
545 d = gVirtualX->GetFontDescent(text);
546 if (gVirtualX->InheritsFrom(
"TGCocoa"))
547 gVirtualX->SetTextFont(oldFont);
557 void TText::GetTextAscentDescent(UInt_t &a, UInt_t &d,
const wchar_t *text)
const
559 Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
560 Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
562 if (wh < hh) tsize = fTextSize*wh;
563 else tsize = fTextSize*hh;
565 if (gVirtualX->HasTTFonts() || gPad->IsBatch() || gVirtualX->InheritsFrom(
"TGCocoa")) {
566 TTF::SetTextFont(fTextFont);
567 TTF::SetTextSize(tsize);
568 a = TTF::GetBox().yMax;
569 d = TMath::Abs(TTF::GetBox().yMin);
571 gVirtualX->SetTextSize(tsize);
572 a = gVirtualX->GetFontAscent();
575 gVirtualX->GetTextExtent(w, a, (
wchar_t*)text);
577 d = gVirtualX->GetFontDescent();
586 void TText::GetTextExtent(UInt_t &w, UInt_t &h,
const char *text)
const
588 Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
589 Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
591 if (wh < hh) tsize = fTextSize*wh;
592 else tsize = fTextSize*hh;
594 if (gVirtualX->HasTTFonts() || gPad->IsBatch()) {
595 TTF::SetTextFont(fTextFont);
596 TTF::SetTextSize(tsize);
597 TTF::GetTextExtent(w, h, (
char*)text);
599 const Font_t oldFont = gVirtualX->GetTextFont();
600 if (gVirtualX->InheritsFrom(
"TGCocoa"))
601 gVirtualX->SetTextFont(fTextFont);
602 gVirtualX->SetTextSize(tsize);
603 gVirtualX->GetTextExtent(w, h, (
char*)text);
604 if (gVirtualX->InheritsFrom(
"TGCocoa"))
605 gVirtualX->SetTextFont(oldFont);
614 void TText::GetTextAdvance(UInt_t &a,
const char *text,
const Bool_t kern)
const
616 Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
617 Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
619 if (wh < hh) tsize = fTextSize*wh;
620 else tsize = fTextSize*hh;
622 if (gVirtualX->HasTTFonts() || gPad->IsBatch()) {
623 Bool_t kernsave = TTF::GetKerning();
624 TTF::SetKerning(kern);
625 TTF::SetTextFont(fTextFont);
626 TTF::SetTextSize(tsize);
627 TTF::GetTextAdvance(a, (
char*)text);
628 TTF::SetKerning(kernsave);
631 const Font_t oldFont = gVirtualX->GetTextFont();
633 if (gVirtualX->InheritsFrom(
"TGCocoa"))
634 gVirtualX->SetTextFont(fTextFont);
636 gVirtualX->SetTextSize(tsize);
637 gVirtualX->GetTextExtent(a, h, (
char*)text);
639 if (gVirtualX->InheritsFrom(
"TGCocoa"))
640 gVirtualX->SetTextFont(oldFont);
649 void TText::GetTextExtent(UInt_t &w, UInt_t &h,
const wchar_t *text)
const
651 Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2());
652 Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1());
654 if (wh < hh) tsize = fTextSize*wh;
655 else tsize = fTextSize*hh;
657 if (gVirtualX->HasTTFonts() || gPad->IsBatch() || gVirtualX->InheritsFrom(
"TGCocoa")) {
658 TTF::SetTextFont(fTextFont);
659 TTF::SetTextSize(tsize);
660 TTF::GetTextExtent(w, h, (
wchar_t*)text);
662 gVirtualX->SetTextSize(tsize);
663 gVirtualX->GetTextExtent(w, h, (
wchar_t*)text);
670 void TText::ls(Option_t *)
const
672 TROOT::IndentLevel();
673 printf(
"Text X=%f Y=%f Text=%s\n",fX,fY,GetTitle());
679 void TText::Paint(Option_t *)
682 if (TestBit(kTextNDC)) gPad->PaintTextNDC(fX,fY,GetTitle());
683 else gPad->PaintText(gPad->XtoPad(fX),gPad->YtoPad(fY),GetTitle());
690 void TText::PaintControlBox(Int_t x, Int_t y, Double_t theta)
692 Int_t cBoxX[4], cBoxY[4];
693 Short_t halign = fTextAlign/10;
694 Short_t valign = fTextAlign - 10*halign;
696 GetControlBox(x, y, theta, cBoxX, cBoxY);
698 gVirtualX->SetLineStyle((Style_t)1);
699 gVirtualX->SetLineWidth(1);
700 gVirtualX->SetLineColor(1);
701 gVirtualX->DrawLine(cBoxX[0], cBoxY[0], cBoxX[1], cBoxY[1]);
702 gVirtualX->DrawLine(cBoxX[1], cBoxY[1], cBoxX[2], cBoxY[2]);
703 gVirtualX->DrawLine(cBoxX[2], cBoxY[2], cBoxX[3], cBoxY[3]);
704 gVirtualX->DrawLine(cBoxX[3], cBoxY[3], cBoxX[0], cBoxY[0]);
708 Int_t ix = 0, iy = 0;
712 case 1 : ix = 0 ; iy = 0 ;
break;
713 case 2 : ix = 0 ; iy = 1 ;
break;
714 case 3 : ix = 1 ; iy = 1 ;
break;
719 case 1 : ix = 0 ; iy = 3 ;
break;
720 case 2 : ix = 0 ; iy = 2 ;
break;
721 case 3 : ix = 1 ; iy = 2 ;
break;
726 case 1 : ix = 3 ; iy = 3 ;
break;
727 case 2 : ix = 2 ; iy = 3 ;
break;
728 case 3 : ix = 2 ; iy = 2 ;
break;
732 p.fX = (cBoxX[ix]+cBoxX[iy])/2;
733 p.fY = (cBoxY[ix]+cBoxY[iy])/2;
734 gVirtualX->SetMarkerColor(1);
735 gVirtualX->SetMarkerStyle(24);
736 gVirtualX->SetMarkerSize(0.7);
737 gVirtualX->DrawPolyMarker(1, &p);
743 void TText::PaintText(Double_t x, Double_t y,
const char *text)
746 gPad->PaintText(x,y,text);
752 void TText::PaintText(Double_t x, Double_t y,
const wchar_t *text)
755 gPad->PaintText(x,y,text);
761 void TText::PaintTextNDC(Double_t u, Double_t v,
const char *text)
764 gPad->PaintTextNDC(u,v,text);
770 void TText::PaintTextNDC(Double_t u, Double_t v,
const wchar_t *text)
773 gPad->PaintTextNDC(u,v,text);
779 void TText::Print(Option_t *)
const
781 printf(
"Text X=%f Y=%f Text=%s Font=%d Size=%f",fX,fY,GetTitle(),GetTextFont(),GetTextSize());
782 if (GetTextColor() != 1 ) printf(
" Color=%d",GetTextColor());
783 if (GetTextAlign() != 10) printf(
" Align=%d",GetTextAlign());
784 if (GetTextAngle() != 0 ) printf(
" Angle=%f",GetTextAngle());
791 void TText::SavePrimitive(std::ostream &out, Option_t * )
794 if (gROOT->ClassSaved(TText::Class())) {
799 TString s = GetTitle();
800 s.ReplaceAll(
"\"",
"\\\"");
801 out<<
"text = new TText("<<fX<<
","<<fY<<
","<<quote<<s.Data()<<quote<<
");"<<std::endl;
802 if (TestBit(kTextNDC)) out<<
" text->SetNDC();"<<std::endl;
804 SaveTextAttributes(out,
"text",11,0,1,62,0.05);
806 out<<
" text->Draw();"<<std::endl;
812 void TText::SetNDC(Bool_t isNDC)
815 if (isNDC) SetBit(kTextNDC);
821 void TText::SetMbTitle(
const wchar_t *title)
823 char *mb_title =
new char[MB_CUR_MAX * wcslen(title) + 1]();
825 size_t length = wcslen(title);
826 for (
size_t i = 0; i < length; i++) {
827 const int n = wctomb(p, title[i]);
832 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
838 void TText::Streamer(TBuffer &R__b)
840 if (R__b.IsReading()) {
842 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
844 R__b.ReadClassBuffer(TText::Class(),
this, R__v, R__s, R__c);
848 TNamed::Streamer(R__b);
849 TAttText::Streamer(R__b);
856 R__b.WriteClassBuffer(TText::Class(),
this);
862 Rectangle_t TText::GetBBox()
867 GetBoundingBox(w, h,
false);
869 Short_t halign = fTextAlign/10;
870 Short_t valign = fTextAlign - 10*halign;
873 case 1 : Dx = 0 ;
break;
874 case 2 : Dx = w/2 ;
break;
875 case 3 : Dx = w ;
break;
878 case 1 : Dy = h ;
break;
879 case 2 : Dy = h/2 ;
break;
880 case 3 : Dy = 0 ;
break;
884 BBox.fX = gPad->XtoPixel(fX)-Dx;
885 BBox.fY = gPad->YtoPixel(fY)-Dy;
894 TPoint TText::GetBBoxCenter()
897 p.SetX(gPad->XtoPixel(fX));
898 p.SetY(gPad->YtoPixel(fY));
905 void TText::SetBBoxCenter(
const TPoint &p)
907 this->SetX(gPad->PixeltoX(p.GetX()));
908 this->SetY(gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0)));
914 void TText::SetBBoxCenterX(
const Int_t x)
916 this->SetX(gPad->PixeltoX(x));
922 void TText::SetBBoxCenterY(
const Int_t y)
924 this->SetY(gPad->PixeltoY(y - gPad->VtoPixel(0)));
931 void TText::SetBBoxX1(
const Int_t )
940 void TText::SetBBoxX2(
const Int_t )
948 void TText::SetBBoxY1(
const Int_t )
957 void TText::SetBBoxY2(
const Int_t )