Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGLPadPainter.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Timur Pocheptsov 06/05/2009
3
4/*************************************************************************
5 * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <stdexcept>
13#include <cassert>
14#include <limits>
15#include <memory>
16#include <vector>
17
18#include "TAttMarker.h"
19#include "TVirtualX.h"
20#include "TError.h"
21#include "TImage.h"
22#include "TROOT.h"
23#include "TPad.h"
24#include "TCanvas.h"
25
26#include "TColorGradient.h"
27#include "TGLPadPainter.h"
28#include "TGLIncludes.h"
29#include "TGLUtil.h"
30#include "TMath.h"
31
32#include <glad/gl.h>
33
34namespace {
35
36////////////////////////////////////////////////////////////////////////////////
37///Not a bad idea to assert on gVirtualX != nullptr
38
40{
41 return dynamic_cast<TColorGradient *>(gROOT->GetColor(fillColorIndex));
42}
43
44}
45
46/** \class TGLPadPainter
47\ingroup opengl
48"Delegating" part of TGLPadPainter. Line/fill/etc. attributes can be
49set inside TPad, but not only there:
50many of them are set by base sub-objects of 2d primitives
51(2d primitives usually inherit TAttLine or TAttFill etc.). And these sub-objects
52call gVirtualX->SetLineWidth ... etc. So, if I save some attributes in my painter,
53it will be mess - at any moment I do not know, where to take line attribute - from
54gVirtualX or from my own member. So! All attributed, _ALL_ go to/from gVirtualX.
55*/
56
57
58////////////////////////////////////////////////////////////////////////////////
59
61 : fIsHollowArea(kFALSE),
62 fLocked(kTRUE)
63{
64 fVp[0] = fVp[1] = fVp[2] = fVp[3] = 0;
65 fWinContext = 0;
66}
67
68
69////////////////////////////////////////////////////////////////////////////////
70///Delegate to gVirtualX.
71
73{
74 // does not work this way
75 gVirtualX->SetOpacityW(fWinContext, percent);
76}
77
78////////////////////////////////////////////////////////////////////////////////
79///Delegate to gVirtualX.
80
82{
83 return gVirtualX->GetTextMagnitude();
84}
85
86////////////////////////////////////////////////////////////////////////////////
87/// Select pad where current painting will be performed
88
90{
91 // GL painter does not use proper id for sub-pads (see CreateDrawable)
92 // so one always use canvas ID to execute TVirtualX-specific commands
93 if (!fWinContext)
94 fWinContext = gVirtualX->GetWindowContext(pad->GetCanvasID());
95}
96
97////////////////////////////////////////////////////////////////////////////////
98/// Set fill attributes
99
101{
103
105
106 // TODO: dismiss in the future, gVirtualX attributes not needed in GL
107 if (fWinContext && gVirtualX)
108 gVirtualX->SetAttFill(fWinContext, att);
109}
110
111////////////////////////////////////////////////////////////////////////////////
112/// Set line attributes
113
115{
117
118 // TODO: dismiss in the future, gVirtualX attributes not needed in GL
119 if (fWinContext && gVirtualX)
120 gVirtualX->SetAttLine(fWinContext, att);
121}
122
123////////////////////////////////////////////////////////////////////////////////
124/// Set marker attributes
125
127{
129
130 // TODO: dismiss in the future, gVirtualX attributes not needed in GL
131 if (fWinContext && gVirtualX)
132 gVirtualX->SetAttMarker(fWinContext, att);
133}
134
135/*
136"Pixmap" part of TGLPadPainter.
137*/
138
139////////////////////////////////////////////////////////////////////////////////
140///Not required at the moment.
141
143{
144 // return gVirtualX->OpenPixmap(Int_t(w), Int_t(h));
145 return 0;
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Resize a gVirtualX Pixmap.
150
152{
153 return gVirtualX->ResizePixmap(device, w, h);
154}
155
156////////////////////////////////////////////////////////////////////////////////
157/// Do nothing, sub-pads not cleared in GL
158
162
163////////////////////////////////////////////////////////////////////////////////
164/// Clear specified window - calling gVirtualX->ClearWindowW
165
167{
168 auto ctxt = gVirtualX->GetWindowContext(device);
169 if (ctxt)
170 gVirtualX->ClearWindowW(ctxt);
171}
172
173////////////////////////////////////////////////////////////////////////////////
174/// Returns true when cocoa backend is used
175
177{
178 return gVirtualX->InheritsFrom("TGCocoa");
179}
180
181////////////////////////////////////////////////////////////////////////////////
182///Not required at the moment.
183
184void TGLPadPainter::CopyDrawable(Int_t /* device */, Int_t /* px */, Int_t /* py */)
185{
186 // gVirtualX->CopyPixmapW(fWinContext, device, px, py);
187}
188
189////////////////////////////////////////////////////////////////////////////////
190///Not required at the moment.
191
193{
194 // gVirtualX->SelectWindow(device);
195 // gVirtualX->ClosePixmap();
196 fWinContext = 0;
197}
198
199////////////////////////////////////////////////////////////////////////////////
200///For gVirtualX this means select pixmap (or window)
201///and all subsequent drawings will go into
202///this pixmap. For OpenGL this means the change of
203///coordinate system and viewport.
204
206{
207 auto pad = dynamic_cast<TPad *>(gPad);
208 if (!fWinContext && pad)
209 fWinContext = gVirtualX->GetWindowContext(pad->GetCanvasID());
210
211 if (fLocked)
212 return;
213
214 if (pad) {
215 // GL painter does not use proper id for sub-pads (see CreateDrawable)
216 // so one always use canvas ID to execute TVirtualX-specific commands
217 Int_t px = 0, py = 0;
218
219 pad->XYtoAbsPixel(pad->GetX1(), pad->GetY1(), px, py);
220
221 py = gPad->GetWh() - py;
222 //
225
226 glViewport(GLint(px * scale), GLint(py * scale),
227 GLsizei(gPad->GetWw() * pad->GetAbsWNDC() * scale),
228 GLsizei(gPad->GetWh() * pad->GetAbsHNDC() * scale));
229
232 glOrtho(pad->GetX1(), pad->GetX2(), pad->GetY1(), pad->GetY2(), -10., 10.);
233
236 glTranslated(0., 0., -1.);
237 } else {
238 ::Error("TGLPadPainter::SelectDrawable",
239 "function was called not from TPad or TCanvas code\n");
240 throw std::runtime_error("");
241 }
242}
243
244////////////////////////////////////////////////////////////////////////////////
245/// Call low-level update of selected drawable, redirect to gVirtualX.
246
248{
249 if (fWinContext)
250 gVirtualX->UpdateWindowW(fWinContext, mode);
251}
252
253
254////////////////////////////////////////////////////////////////////////////////
255/// Set drawing mode for specified device
256
258{
259 auto ctxt = fWinContext;
260 if (device)
261 ctxt = gVirtualX->GetWindowContext(device);
262 if (ctxt)
263 gVirtualX->SetDrawModeW(ctxt, (TVirtualX::EDrawMode) mode);
264}
265
266////////////////////////////////////////////////////////////////////////////////
267///Init gl-pad painter:
268///1. 2D painter does not use depth test, should not modify
269/// depth-buffer content (except initial cleanup).
270///2. Disable cull face.
271///3. Disable lighting.
272///4. Set viewport (to the whole canvas area).
273///5. Set camera.
274///6. Unlock painter.
275
277{
278 static bool gl_init = false;
279 if (!gl_init) {
281 if (version == 0)
282 Warning("TGLPadPainter::InitPainter", "GL initalization failed.");
283 else if (gDebug > 0)
284 Info("TGLPadPainter::InitPainter", "GL initalization successful.");
285 gl_init = true;
286 }
290
291 //Clear the buffer
292 glViewport(0, 0, GLsizei(gPad->GetWw()), GLsizei(gPad->GetWh()));
293
295 glClearColor(1.,1.,1.,1.);
298
301
302 glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
303
306 glTranslated(0., 0., -1.);
307
308 fLocked = kFALSE;
309}
310
311////////////////////////////////////////////////////////////////////////////////
312///When TPad::Range for gPad is called, projection
313///must be changed in OpenGL.
314
316{
317 if (fLocked) return;
318
321
322 glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
323
325}
326
327////////////////////////////////////////////////////////////////////////////////
328///Locked state of painter means, that
329///GL context can be invalid, so no GL calls
330///can be executed.
331
333{
334 if (fLocked) return;
335
336 glFinish();
337 fLocked = kTRUE;
338}
339
340/*
3412D primitives.
342*/
343
345
346////////////////////////////////////////////////////////////////////////////////
347///Draw line segment.
348
350{
351 if (fLocked) {
352 //GL pad painter can be called in non-standard situation:
353 //not from TPad::Paint, but
354 //from TView3D::ExecuteRotateView. This means in fact,
355 //that TView3D wants to draw itself in a XOR mode, via
356 //gVirtualX.
357 // TODO: only here set line attributes to virtual x
358 if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) {
359 gVirtualX->DrawLineW(fWinContext,
360 gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1),
361 gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2));
362 }
363
364 return;
365 }
366
368
369 glBegin(GL_LINES);
370 glVertex2d(x1, y1);
371 glVertex2d(x2, y2);
372 glEnd();
373
375 Double_t pointSize = GetAttLine().GetLineWidth();
381 glBegin(GL_POINTS);
382
383 glVertex2d(x1, y1);
384 glVertex2d(x2, y2);
385
386 glEnd();
387 glPointSize(1.f);
388 }
389
390}
391
392////////////////////////////////////////////////////////////////////////////////
393///Draw line segment in NDC coordinates.
394
396{
397 if (fLocked) {
398 // this code used when crosshair cursor is drawn
399 if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) {
400 // TODO: only here set line attributes to virtual x
401 gVirtualX->DrawLineW(fWinContext,
402 gPad->UtoAbsPixel(u1), gPad->VtoAbsPixel(v1),
403 gPad->UtoAbsPixel(u2), gPad->VtoAbsPixel(v2));
404 }
405 return;
406 }
407
409 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
410 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
411
412 glBegin(GL_LINES);
413 glVertex2d(gPad->GetX1() + u1 * xRange, gPad->GetY1() + v1 * yRange);
414 glVertex2d(gPad->GetX1() + u2 * xRange, gPad->GetY1() + v2 * yRange);
415 glEnd();
416}
417
418////////////////////////////////////////////////////////////////////////////////
419///Draw filled or hollow box.
420
422{
423 if (fLocked) {
424 //GL pad painter can be called in non-standard situation:
425 //not from TPad::Paint, but
426 //from TView3D::ExecuteRotateView. This means in fact,
427 //that TView3D wants to draw itself in a XOR mode, via
428 //gVirtualX.
429 // TODO: only here set line attributes to virtual x
430 if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) {
431 gVirtualX->DrawBoxW(fWinContext,
432 gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1),
433 gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2),
435 }
436 return;
437 }
438
440 Double_t xs[] = {x1, x2, x2, x1};
441 Double_t ys[] = {y1, y1, y2, y2};
443 return;
444 }
445
446 if (mode == kHollow) {
448 //
450 glRectd(x1, y1, x2, y2);
452 glLineWidth(1.f);
453 } else {
454 const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE, &fGlFillAtt);//Set filling parameters.
455 glRectd(x1, y1, x2, y2);
456 }
457}
458
459////////////////////////////////////////////////////////////////////////////////
460///Draw tesselated polygon (probably, outline only).
461
463{
464 assert(x != nullptr && "DrawFillArea, parameter 'x' is null");
465 assert(y != nullptr && "DrawFillArea, parameter 'y' is null");
466
467 if (fLocked)
468 return;
469
470 if (n < 3) {
471 ::Error("TGLPadPainter::DrawFillArea",
472 "invalid number of points in a polygon");
473 return;
474 }
475
477 return DrawPolygonWithGradient(n, x, y);
478
479 if (fFullyTransparent) {
481 return DrawPolyLine(n, x, y);
482 }
483
485 DrawTesselation(n, x, y);
486}
487
488////////////////////////////////////////////////////////////////////////////////
489///Draw tesselated polygon (never called, probably, since TPad::PaintFillArea for floats
490///is deprecated).
491
493{
494 if (fLocked) return;
495
496 if (fFullyTransparent) {
498 return DrawPolyLine(n, x, y);
499 }
500
501 fVs.resize(n * 3);
502
503 for (Int_t i = 0; i < n; ++i) {
504 fVs[i * 3] = x[i];
505 fVs[i * 3 + 1] = y[i];
506 }
507
509
513
514 for (Int_t i = 0; i < n; ++i)
515 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
516
517
518 gluEndPolygon(t);
519}
520
521////////////////////////////////////////////////////////////////////////////////
522///Draw poly-line in user coordinates.
523
525{
526 if (fLocked) return;
527
529
530 glBegin(GL_LINE_STRIP);
531
532 for (Int_t i = 0; i < n; ++i)
533 glVertex2d(x[i], y[i]);
534
535 if (fIsHollowArea) {
536 glVertex2d(x[0], y[0]);
538 }
539 glEnd();
540
542 Double_t pointSize = GetAttLine().GetLineWidth();
548 glBegin(GL_POINTS);
549
550 for (Int_t i = 0; i < n; ++i)
551 glVertex2d(x[i], y[i]);
552
553 glEnd();
554 glPointSize(1.f);
555 }
556}
557
558////////////////////////////////////////////////////////////////////////////////
559///Never called?
560
562{
563 if (fLocked) return;
564
566
567 glBegin(GL_LINE_STRIP);
568
569 for (Int_t i = 0; i < n; ++i)
570 glVertex2f(x[i], y[i]);
571
572 if (fIsHollowArea) {
573 glVertex2f(x[0], y[0]);
575 }
576
577 glEnd();
578}
579
580////////////////////////////////////////////////////////////////////////////////
581///Poly line in NDC.
582
584{
585 if (fLocked) return;
586
588 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
589 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
590 const Double_t x1 = gPad->GetX1(), y1 = gPad->GetY1();
591
592 glBegin(GL_LINE_STRIP);
593
594 for (Int_t i = 0; i < n; ++i)
595 glVertex2d(x1 + u[i] * xRange, y1 + v[i] * yRange);
596
597 glEnd();
598}
599
600namespace {
601
602//Aux. function.
603template<class ValueType>
604void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector<TPoint> & dst);
605
606}
607
608////////////////////////////////////////////////////////////////////////////////
609///Poly-marker.
610
612{
613 if (fLocked) return;
614
617}
618
619////////////////////////////////////////////////////////////////////////////////
620///Poly-marker.
621
623{
624 if (fLocked) return;
625
628}
629
630////////////////////////////////////////////////////////////////////////////////
631///Poly-marker.
632
634{
635 if (fLocked) return;
636
639 //
640 glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
641 //
643 //
645
646 Float_t rgba[4] = {};
650
651
654
655 fMarker.SetMarkerSizeWidth(GetAttMarker().GetMarkerSize(), w);
656
657 const TPoint *xy = &fPoly[0];
659 const UInt_t n = UInt_t(fPoly.size());
660 switch (markerStyle) {
661 case kDot:
663 break;
664 case kPlus:
666 break;
667 case kStar:
668 case 31:
670 break;
671 case kCircle:
672 case kOpenCircle:
674 break;
675 case kMultiply:
676 fMarker.DrawX(n, xy);
677 break;
678 case kFullDotSmall://"Full dot small"
680 break;
681 case kFullDotMedium:
683 break;
684 case kFullDotLarge:
685 case kFullCircle:
687 break;
688 case kFullSquare:
690 break;
691 case kFullTriangleUp:
693 break;
696 break;
697 case kOpenSquare:
701 break;
702 case kOpenTriangleUp:
706 break;
707 case kOpenDiamond:
709 break;
710 case kOpenCross:
712 break;
713 case kFullStar:
715 break;
716 case kOpenStar:
718 break;
721 break;
722 case kFullDiamond:
724 break;
725 case kFullCross:
727 break;
730 break;
733 break;
736 break;
737 case kOctagonCross:
739 break;
742 break;
745 break;
748 break;
751 break;
754 break;
757 break;
760 break;
761 case kOpenCrossX:
763 break;
764 case kFullCrossX:
766 break;
767 case kFourSquaresX:
769 break;
770 case kFourSquaresPlus:
772 break;
773 }
774
777 glLineWidth(1.f);
778}
779
780////////////////////////////////////////////////////////////////////////////////
781/// Select specified font/size
782
784{
785 //10 is the first valid font index.
786 //20 is FreeSerifBold, as in TTF.cxx and in TGLFontManager.cxx.
787 //shift - is the shift to access "extended" fonts.
789
790 Int_t fontIndex = TMath::Max(Font_t(10), font);
791 if (fontIndex / 10 + shift > TGLFontManager::GetFontFileArray()->GetEntries())
792 fontIndex = 20 + shift * 10;
793 else
794 fontIndex += shift * 10;
795
796 Int_t textSize = TMath::Max(Int_t(tsize) - 1, 10);
797
799
801}
802
803////////////////////////////////////////////////////////////////////////////////
804/// Helper function to draw text
805
806template<class Char>
808{
810
812 //
813 glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
814 //
816
817 Float_t rgba[4] = {};
820
821 SelectGLFont(GetAttText().GetTextFont(), GetAttText().GetTextSizePixels(*gPad));
822
824
825 fF.PreRender();
826
827 const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
828 fF.Render(text, gPad->XtoPixel(x), padH - gPad->YtoPixel(y), GetTextAngle(), GetTextMagnitude());
829
830 fF.PostRender();
832
834}
835
836////////////////////////////////////////////////////////////////////////////////
837/// Helper function to get text extent
838
839template<class Char_t>
841{
842 SelectGLFont(font, size);
843
844 Float_t llx, lly, llz, urx, ury, urz;
845 fF.BBox(text, llx, lly, llz, urx, ury, urz);
846 urx -= llx;
847 ury -= lly;
848 w = (UInt_t) (urx > 0. ? urx : 0.);
849 h = (UInt_t) (ury > 0. ? ury : 0.);
850 (void) llz;
851 (void) urz;
852}
853
854////////////////////////////////////////////////////////////////////////////////
855/// Helper function to get text ascent / descent
856
857template<class Char_t>
859{
860 SelectGLFont(font, size);
861
862 Float_t llx, lly, llz, urx, ury, urz;
863 fF.BBox(text, llx, lly, llz, urx, ury, urz);
864 a = (UInt_t) (ury > 0. ? ury : 0.);
865 d = (UInt_t) (lly < 0. ? -lly : 0.);
866 (void) llx;
867 (void) llz;
868 (void) urx;
869 (void) urz;
870}
871
872////////////////////////////////////////////////////////////////////////////////
873///Draw text. This operation is especially
874///dangerous if in locked state -
875///ftgl will assert on zero texture size
876///(which is result of bad GL context).
877
879{
880 if (fLocked) return;
881
882 if (GetAttText().GetTextSize() > 0)
884}
885
886////////////////////////////////////////////////////////////////////////////////
887///Draw text. This operation is especially
888///dangerous if in locked state -
889///ftgl will assert on zero texture size
890///(which is result of bad GL context).
891
893{
894 if (fLocked) return;
895
896 if (GetAttText().GetTextSize() > 0)
898}
899
900////////////////////////////////////////////////////////////////////////////////
901///Draw text in NDC. This operation is especially
902///dangerous if in locked state -
903///ftgl will assert on zero texture size
904///(which is result of bad GL context).
905
907{
908 if (fLocked) return;
909
910 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
911 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
912 DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
913}
914
915////////////////////////////////////////////////////////////////////////////////
916/// Get text extent
917
919{
920 TextExtentHelper(font, size, w, h, text);
921}
922
923////////////////////////////////////////////////////////////////////////////////
924/// Get text extent
925
927{
928 TextExtentHelper(font, size, w, h, text);
929}
930
931////////////////////////////////////////////////////////////////////////////////
932/// Get text extent
933
938
939////////////////////////////////////////////////////////////////////////////////
940/// Get text extent
941
946
947////////////////////////////////////////////////////////////////////////////////
948/// Get text advance
949
951{
952 SelectGLFont(font, size);
953
954 auto advance = fF.Advance(text);
955
956 return (UInt_t) (advance > 0. ? advance : 0.);
957}
958
959////////////////////////////////////////////////////////////////////////////////
960///Draw text in NDC. This operation is especially
961///dangerous if in locked state -
962///ftgl will assert on zero texture size
963///(which is result of bad GL context).
964
966{
967 if (fLocked) return;
968
969 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
970 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
971 DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
972}
973
974////////////////////////////////////////////////////////////////////////////////
975///Save the projection matrix.
976///Attention! GL_PROJECTION will become the current matrix
977///after this call!
978
984
985////////////////////////////////////////////////////////////////////////////////
986///Restore the projection matrix.
987///Attention! GL_PROJECTION will become the current matrix
988///after this call!
989
995
996////////////////////////////////////////////////////////////////////////////////
997///Save the modelview matrix.
998///Attention! GL_MODELVIEW will become the current matrix
999///after this call!
1000
1006
1007////////////////////////////////////////////////////////////////////////////////
1008///Restore the modelview matrix.
1009///Attention! GL_MODELVIEW will become the current matrix
1010///after this call!
1011
1017
1018////////////////////////////////////////////////////////////////////////////////
1019///Extract and save the current viewport.
1020
1025
1026////////////////////////////////////////////////////////////////////////////////
1027///Restore the saved viewport.
1028
1030{
1031 glViewport(fVp[0], fVp[1], fVp[2], fVp[3]);
1032}
1033
1034////////////////////////////////////////////////////////////////////////////////
1035/// Using TImage save frame-buffer contents as a picture.
1036
1037void TGLPadPainter::SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const
1038{
1039 auto canvas = pad->GetCanvas();
1040 if (!canvas)
1041 return;
1042
1043 canvas->Flush();
1044
1045 std::vector<unsigned> buff(canvas->GetWw() * canvas->GetWh());
1048 //In case GL_BGRA is not in gl.h (old windows' gl) - comment/uncomment lines.
1049 //glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_BGRA, GL_UNSIGNED_BYTE, (char *)&buff[0]);
1050 glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_RGBA, GL_UNSIGNED_BYTE, (char *)&buff[0]);
1051
1052 std::unique_ptr<TImage> image(TImage::Create());
1053 if (!image.get()) {
1054 ::Error("TGLPadPainter::SaveImage", "TImage creation failed");
1055 return;
1056 }
1057
1058 image->DrawRectangle(0, 0, canvas->GetWw(), canvas->GetWh());
1059 UInt_t *argb = image->GetArgbArray();
1060
1061 if (!argb) {
1062 ::Error("TGLPadPainter::SaveImage", "null argb array in TImage object");
1063 return;
1064 }
1065
1066 const Int_t nLines = canvas->GetWh();
1067 const Int_t nPixels = canvas->GetWw();
1068
1069 for (Int_t i = 0; i < nLines; ++i) {
1070 Int_t base = (nLines - 1 - i) * nPixels;
1071 for (Int_t j = 0; j < nPixels; ++j, ++base) {
1072 //Uncomment/comment if you don't have GL_BGRA.
1073
1074 const UInt_t pix = buff[base];
1075 const UInt_t bgra = ((pix & 0xff) << 16) | (pix & 0xff00) |
1076 ((pix & 0xff0000) >> 16) | (pix & 0xff000000);
1077
1078 //argb[i * nPixels + j] = buff[base];
1079 argb[i * nPixels + j] = bgra;
1080 }
1081 }
1082
1083 image->WriteImage(fileName, (TImage::EImageFileTypes)type);
1084}
1085
1086////////////////////////////////////////////////////////////////////////////////
1087
1090{
1091 if (fLocked)
1092 return;
1093
1094 if (!pixelData) {
1095 //I'd prefer an assert.
1096 ::Error("TGLPadPainter::DrawPixels", "pixel data is null");
1097 return;
1098 }
1099
1100 if (std::numeric_limits<UInt_t>::digits >= 32) {
1101 //TASImage uses bit 31 as ...
1102 //alpha channel flag! FUUUUUUUUUUUUU ..... !!!
1103 CLRBIT(width, 31);
1104 CLRBIT(height, 31);
1105 }
1106
1107 if (!width) {
1108 //Assert is better.
1109 ::Error("TGLPadPainter::DrawPixels", "invalid width");
1110 return;
1111 }
1112
1113 if (!height) {
1114 //Assert is better.
1115 ::Error("TGLPadPainter::DrawPixels", "invalid height");
1116 return;
1117 }
1118
1119 if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
1120 //TASImage passes pixel coordinates in pad's pixmap coordinate space.
1121 //While glRasterPosX said to work with 'window' coordinates,
1122 //that's a lie :) it does not :)
1123
1124 const Double_t rasterX = Double_t(dstX) / (pad->GetAbsWNDC() * pad->GetWw()) *
1125 (pad->GetX2() - pad->GetX1()) + pad->GetX1();
1126
1127 const Double_t yRange = pad->GetY2() - pad->GetY1();
1128 const Double_t rasterY = yRange - Double_t(dstY + height) / (pad->GetAbsHNDC() * pad->GetWh()) * yRange +
1129 pad->GetY1();
1130
1131 GLdouble oldPos[4] = {};
1132 //Save the previous raster pos.
1134
1136 //Stupid asimage provides us upside-down image.
1137 std::vector<unsigned char> upsideDownImage(4 * width * height);
1138 const unsigned char *srcLine = pixelData + 4 * width * (height - 1);
1139 unsigned char *dstLine = &upsideDownImage[0];
1140 for (UInt_t i = 0; i < height; ++i, srcLine -= 4 * width, dstLine += 4 * width)
1141 std::copy(srcLine, srcLine + 4 * width, dstLine);
1142
1143 if (enableBlending) {
1146 }
1147
1149
1150 if (enableBlending)
1152
1153 //Restore raster pos.
1154 glRasterPos2d(oldPos[0], oldPos[1]);
1155 } else
1156 ::Error("TGLPadPainter::DrawPixels", "no pad found to draw");
1157}
1158
1159//Aux. functions - gradient and solid fill of arbitrary area.
1160
1161////////////////////////////////////////////////////////////////////////////////
1162///At the moment I assume both linear and radial gradients will work the same way -
1163///using a stencil buffer and some big rectangle(s) to fill with a gradient.
1164///Thus I have a 'common' part - the part responsible for a stencil test.
1165
1167{
1168 assert(n > 2 && "DrawPolygonWithGradient, invalid number of points");
1169 assert(x != nullptr && "DrawPolygonWithGradient, parameter 'x' is null");
1170 assert(y != nullptr && "DrawPolygonWithGradient, parameter 'y' is null");
1171
1172 auto grad = dynamic_cast<TColorGradient *>(gROOT->GetColor(fGlFillAtt.GetFillColor()));
1173 assert(grad != nullptr && "DrawPolygonWithGradient, the current fill color is not a gradient fill");
1174
1175 if (fLocked)
1176 return;
1177
1178 //Now, some magic!
1180
1181 //TODO: check that the state is restored back correctly after
1182 // we done with a gradient.
1183 //TODO: make sure that we have glDepthMask set to false in general!
1185
1186 glStencilFunc(GL_NEVER, 1, 0xFF);
1187 glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);// draw 1s on test fail (always)
1188 //Draw stencil pattern
1189 glStencilMask(0xFF);
1191
1192 //Draw our polygon into the stencil buffer:
1193 DrawTesselation(n, x, y);
1194
1196 glStencilMask(0x00);
1197 //Draw where stencil's value is 0
1198 glStencilFunc(GL_EQUAL, 0, 0xFF);
1199 //Draw only where stencil's value is 1
1200 glStencilFunc(GL_EQUAL, 1, 0xFF);
1201
1202 //At the moment radial gradient is derived from linear - it was convenient
1203 //at some point, but in fact it was a bad idea. And now I have to
1204 //first check radial gradient.
1205 //TODO: TRadialGradient must inherit TColorGradient directly.
1206 const TRadialGradient * const rGrad = dynamic_cast<const TRadialGradient *>(grad);
1207 if (rGrad)
1208 DrawGradient(rGrad, n, x, y);
1209 else {
1210 const TLinearGradient * const lGrad = dynamic_cast<const TLinearGradient *>(grad);
1211 assert(lGrad != nullptr && "DrawPolygonWithGradient, unknown gradient type");
1212 DrawGradient(lGrad, n, x, y);
1213 }
1214}
1215
1216////////////////////////////////////////////////////////////////////////////////
1217
1219 const Double_t *xs, const Double_t *ys)
1220{
1221 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1222 assert(nPoints > 2 && "DrawGradient, invalid number of points");
1223 assert(xs != nullptr && "DrawGradient, parameter 'xs' is null");
1224 assert(ys != nullptr && "DrawGradient, parameter 'ys' is null");
1225
1227 ::Warning("TGLPadPainter::DrawGradient",
1228 "extended radial gradient is not supported");//yet?
1229 return;
1230 }
1231
1232 //TODO: check the polygon's bbox!
1233 const auto &bbox = Rgl::Pad::FindBoundingRect(nPoints, xs, ys);
1234 //
1235 auto center = grad->GetCenter();
1236 auto radius = grad->GetRadius();
1237 //Adjust the center and radius depending on coordinate mode.
1239 radius *= TMath::Max(bbox.fWidth, bbox.fHeight);
1240 center.fX = bbox.fWidth * center.fX + bbox.fXMin;
1241 center.fY = bbox.fHeight * center.fY + bbox.fYMin;
1242 } else {
1243 const auto w = gPad->GetX2() - gPad->GetX1();
1244 const auto h = gPad->GetY2() - gPad->GetY1();
1245
1246 radius *= TMath::Max(w, h);
1247 center.fX *= w;
1248 center.fY *= h;
1249 }
1250 //Now for the gradient fill we switch into pixel coordinates:
1251 const auto pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1252 const auto pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1253 //
1256 //A new ortho projection:
1259 //
1260 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1261 //
1263 center.fX = gPad->XtoPixel(center.fX);
1264 center.fY = pixelH - gPad->YtoPixel(center.fY);
1265
1266 Double_t maxR = 0.;
1267 {
1268 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1269 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1270 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1271 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1272 //Get the longest distance from the center to the bounding box vertices
1273 //(this will be the maximum possible radius):
1274 const Double_t maxDistX = TMath::Max(TMath::Abs(center.fX - xMin),
1275 TMath::Abs(center.fX - xMax));
1276 const Double_t maxDistY = TMath::Max(TMath::Abs(center.fY - yMin),
1277 TMath::Abs(center.fY - yMax));
1279 }
1280
1281 //If gradient 'stops inside the polygon', we use
1282 //the solid fill for the area outside of radial gradient:
1283 const Bool_t solidFillAfter = maxR > radius;
1284 //We emulate a radial gradient using triangles and linear gradient:
1285 //TODO: Can be something smarter? (btw even 100 seems to be enough)
1286 const UInt_t nSlices = 500;
1287
1288 const auto nColors = grad->GetNumberOfSteps();
1289 //+1 - the strip from the last color's position to radius,
1290 //and (probably) + 1 for solidFillAfter.
1291 const auto nCircles = nColors + 1 + solidFillAfter;
1292
1293 //TODO: can locations be outside of [0., 1.] ???
1294 //at the moment I assume the answer is NO, NEVER.
1295 const auto locations = grad->GetColorPositions();
1296 // * 2 below == x,y
1297 std::vector<Double_t> circles(nSlices * nCircles * 2);
1298 const Double_t angle = TMath::TwoPi() / nSlices;
1299
1300 //"Main" circles (for colors at locations[i]).
1301 for (UInt_t i = 0; i < nColors; ++i) {
1302 const auto circle = &circles[i * nSlices * 2];
1303 //TODO: either check locations here or somewhere else.
1304 const auto r = radius * locations[i];
1305 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1306 circle[j] = center.fX + r * TMath::Cos(angle * j);
1307 circle[j + 1] = center.fY + r * TMath::Sin(angle * j);
1308 }
1309 //The "closing" vertices:
1310 circle[(nSlices - 1) * 2] = circle[0];
1311 circle[(nSlices - 1) * 2 + 1] = circle[1];
1312 }
1313
1314 {
1315 //The strip between lastPos and radius:
1316 const auto circle = &circles[nColors * nSlices * 2];
1317 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1318 circle[j] = center.fX + radius * TMath::Cos(angle * j);
1319 circle[j + 1] = center.fY + radius * TMath::Sin(angle * j);
1320 }
1321
1322 circle[(nSlices - 1) * 2] = circle[0];
1323 circle[(nSlices - 1) * 2 + 1] = circle[1];
1324 }
1325
1326 if (solidFillAfter) {
1327 //The strip after the radius:
1328 const auto circle = &circles[(nCircles - 1) * nSlices * 2];
1329 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1330 circle[j] = center.fX + maxR * TMath::Cos(angle * j);
1331 circle[j + 1] = center.fY + maxR * TMath::Sin(angle * j);
1332 }
1333
1334 circle[(nSlices - 1) * 2] = circle[0];
1335 circle[(nSlices - 1) * 2 + 1] = circle[1];
1336 }
1337
1338 //Now we draw:
1339 //1) triangle fan in the center (from center to the locations[1],
1340 // with a solid fill).
1341 //2) quad strips for colors.
1342 //3) additional quad strip from the lastLocation to the radius
1343 //4) additional quad strip (if any) from the radius to maxR.
1344
1345 //RGBA values:
1346 const auto rgba = grad->GetColors();
1347
1349 //TODO?
1351
1352 //Probably a degenerated case. Maybe not.
1355 glVertex2d(center.fX, center.fY);
1356
1357 for (UInt_t i = 0, e = nSlices * 2; i < e; i += 2)
1358 glVertex2dv(&circles[i]);
1359
1360 glEnd();
1361
1362 //No auto for circles, explicit types to have const Double_t * const, not Duble_t * const.
1363 for (UInt_t i = 0; i < nColors - 1; ++i) {
1364 const Double_t * const inner = &circles[i * nSlices * 2];
1365 const auto innerRGBA = rgba + i * 4;
1366 const auto outerRGBA = rgba + (i + 1) * 4;
1367 const Double_t * const outer = &circles[(i + 1) * nSlices * 2];
1368
1370 }
1371
1372 //Probably degenerated strip.
1373 {
1374 const Double_t * const inner = &circles[nSlices * (nColors - 1) * 2];
1375 const auto solidRGBA = rgba + (nColors - 1) * 4;
1376 const Double_t * const outer = &circles[nSlices * nColors * 2];
1377
1379 }
1380
1381 if (solidFillAfter) {
1382 const Double_t * const inner = &circles[nSlices * nColors * 2];
1383 const auto solidRGBA = rgba + (nColors - 1) * 4;
1384 const Double_t * const outer = &circles[nSlices * (nColors + 1) * 2];
1385
1387 }
1388
1391}
1392
1393////////////////////////////////////////////////////////////////////////////////
1394
1396 const Double_t *x, const Double_t *y)
1397{
1398 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1399 assert(n > 2 && "DrawGradient, invalid number of points");
1400 assert(x != nullptr && "DrawGradient, parameter 'x' is null");
1401 assert(y != nullptr && "DrawGradient, parameter 'y' is null");
1402
1403 //Now we fill the whole scene with one big rectangle
1404 //(group of rectangles) with a gradient fill using
1405 //stencil test.
1406
1407 //Find a bounding rect.
1408 const auto &bbox = Rgl::Pad::FindBoundingRect(n, x, y);
1409 //TODO: check the bbox??
1410
1411 //For the gradient fill we switch into the
1412 //pixel coordinates.
1415
1416 //A new ortho projection:
1419
1420 const Double_t pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1421 const Double_t pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1422 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1423
1424 //A new modelview:
1427 //
1428 TColorGradient::Point start = grad->GetStart();
1429 TColorGradient::Point end = grad->GetEnd();
1430
1431 //Change gradient coordinates from 'NDC' to pad coords:
1433 {
1434 const Double_t w = gPad->GetX2() - gPad->GetX1();
1435 const Double_t h = gPad->GetY2() - gPad->GetY1();
1436
1437 start.fX = start.fX * w;
1438 start.fY = start.fY * h;
1439 end.fX = end.fX * w;
1440 end.fY = end.fY * h;
1441 } else {
1442 start.fX = start.fX * bbox.fWidth + bbox.fXMin;
1443 start.fY = start.fY * bbox.fHeight + bbox.fYMin;
1444 end.fX = end.fX * bbox.fWidth + bbox.fXMin;
1445 end.fY = end.fY * bbox.fHeight + bbox.fYMin;
1446 }
1447
1448 //TODO: with a radial fill we'll have to extract the code
1449 // below into the separate function/and have additional function
1450 // for a radial gradient.
1451 //Now from pad to pixels:
1452 start.fX = gPad->XtoPixel(start.fX);
1453 start.fY = pixelH - gPad->YtoPixel(start.fY);
1454 end.fX = gPad->XtoPixel(end.fX);
1455 end.fY = pixelH - gPad->YtoPixel(end.fY);
1456 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1457 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1458 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1459 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1460 //
1461
1462 //TODO: check all calculations!
1463
1464 //Get the longest distance from the start point to the bounding box vertices:
1465 const Double_t maxDistX = TMath::Max(TMath::Abs(start.fX - xMin), TMath::Abs(start.fX - xMax));
1466 const Double_t maxDistY = TMath::Max(TMath::Abs(start.fY - yMin), TMath::Abs(start.fY - yMax));
1467
1468 const Double_t startEndLength = TMath::Sqrt((end.fX - start.fX) * (end.fX - start.fX) +
1469 (end.fY - start.fY) * (end.fY - start.fY));
1472
1473 //Boxes with a gradients to emulate gradient fill with many colors:
1474 const Double_t * const colorPositions = grad->GetColorPositions();
1475 std::vector<Double_t> gradBoxes(grad->GetNumberOfSteps() + 2);
1476 gradBoxes[0] = start.fY - h;
1477 for (unsigned i = 1; i <= grad->GetNumberOfSteps(); ++i)
1478 gradBoxes[i] = startEndLength * colorPositions[i - 1] + start.fY;
1479
1480 gradBoxes[grad->GetNumberOfSteps() + 1] = start.fY + h;
1481
1482 //Rotation angle - gradient's axis:
1483 Double_t angle = TMath::ACos((startEndLength * (end.fY - start.fY)) /
1485 if (end.fX > start.fX)
1486 angle *= -1;
1487
1488 glTranslated(start.fX, start.fY, 0.);
1489 glRotated(angle, 0., 0., 1.);
1490 glTranslated(-start.fX, -start.fY, 0.);
1491 //
1492 const Double_t * const rgba = grad->GetColors();
1493
1494 const unsigned nEdges = gradBoxes.size();
1495 const unsigned nColors = grad->GetNumberOfSteps();
1496 const Double_t xLeft = start.fX - h, xRight = start.fX + h;
1497
1499 //TODO?
1501
1504 rgba + (nColors - 1) * 4, rgba + (nColors - 1) * 4);
1505
1506 for (unsigned i = 1; i < nEdges - 2; ++i)
1508 xRight, rgba + (i - 1) * 4, rgba + i * 4);
1509
1512}
1513
1514////////////////////////////////////////////////////////////////////////////////
1515
1517{
1518 assert(n > 2 && "DrawTesselation, invalid number of points");
1519 assert(x != nullptr && "DrawTesselation, parameter 'x' is null");
1520 assert(y != nullptr && "DrawTesselation, parameter 'y' is null");
1521
1522 //Data for a tesselator:
1523 fVs.resize(n * 3);
1524
1525 for (Int_t i = 0; i < n; ++i) {
1526 fVs[i * 3] = x[i];
1527 fVs[i * 3 + 1] = y[i];
1528 fVs[i * 3 + 2] = 0.;
1529 }
1530
1531 //TODO: A very primitive way to tesselate - check what
1532 //kind of polygons we can really have from TPad/TCanvas.
1534 gluBeginPolygon(t);
1536
1537 for (Int_t i = 0; i < n; ++i)
1538 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
1539
1540 gluEndPolygon(t);
1541}
1542
1543
1544//Aux. functions.
1545namespace {
1546
1547template<class ValueType>
1548void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector<TPoint> & dst)
1549{
1550 const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
1551
1552 dst.resize(n);
1553 for (Int_t i = 0; i < n; ++i) {
1554 dst[i].fX = gPad->XtoPixel(x[i]);
1555 dst[i].fY = padH - gPad->YtoPixel(y[i]);
1556 }
1557}
1558
1559}
1560
#define d(i)
Definition RSha256.hxx:102
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
short Style_t
Style number (short)
Definition RtypesCore.h:96
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
char Char_t
Character 1 byte (char)
Definition RtypesCore.h:51
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
short Width_t
Line width (short)
Definition RtypesCore.h:98
short Font_t
Font number (short)
Definition RtypesCore.h:95
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
#define CLRBIT(n, i)
Definition Rtypes.h:93
@ kOpenDoubleDiamond
Definition TAttMarker.h:68
@ kStar
Definition TAttMarker.h:58
@ kFullDotLarge
Definition TAttMarker.h:59
@ kFullDoubleDiamond
Definition TAttMarker.h:68
@ kOpenFourTrianglesX
Definition TAttMarker.h:67
@ kOpenSquare
Definition TAttMarker.h:61
@ kFullThreeTriangles
Definition TAttMarker.h:66
@ kOpenTriangleUp
Definition TAttMarker.h:62
@ kFourSquaresPlus
Definition TAttMarker.h:71
@ kFullDotSmall
Definition TAttMarker.h:59
@ kFullDotMedium
Definition TAttMarker.h:59
@ kOpenTriangleDown
Definition TAttMarker.h:63
@ kOpenThreeTriangles
Definition TAttMarker.h:65
@ kFullCrossX
Definition TAttMarker.h:70
@ kFullFourTrianglesX
Definition TAttMarker.h:67
@ kFullTriangleDown
Definition TAttMarker.h:61
@ kCircle
Definition TAttMarker.h:58
@ kOpenCrossX
Definition TAttMarker.h:70
@ kFullFourTrianglesPlus
Definition TAttMarker.h:69
@ kFullSquare
Definition TAttMarker.h:60
@ kOpenSquareDiagonal
Definition TAttMarker.h:65
@ kFullStar
Definition TAttMarker.h:63
@ kOpenDiamond
Definition TAttMarker.h:62
@ kFullTriangleUp
Definition TAttMarker.h:60
@ kOpenDiamondCross
Definition TAttMarker.h:64
@ kOpenFourTrianglesPlus
Definition TAttMarker.h:69
@ kMultiply
Definition TAttMarker.h:58
@ kPlus
Definition TAttMarker.h:58
@ kOctagonCross
Definition TAttMarker.h:66
@ kFullCircle
Definition TAttMarker.h:60
@ kDot
Definition TAttMarker.h:58
@ kOpenCross
Definition TAttMarker.h:62
@ kFourSquaresX
Definition TAttMarker.h:70
@ kOpenCircle
Definition TAttMarker.h:61
@ kFullCross
Definition TAttMarker.h:64
@ kOpenStar
Definition TAttMarker.h:63
@ kFullDiamond
Definition TAttMarker.h:64
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
const Double_t lineWidthTS
#define GL_BGRA
Definition TGLViewer.cxx:61
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pix
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint xy
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t width
Option_t Option_t TPoint TPoint percent
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint DrawText
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:148
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:783
#define gROOT
Definition TROOT.h:426
#define gPad
#define gVirtualX
Definition TVirtualX.h:375
Double_t GetMaxLineWidth() const
Double_t GetMaxPointSize() const
void DrawOpenThreeTriangles(UInt_t n, const TPoint *xy) const
void DrawFullCrossX(UInt_t n, const TPoint *xy) const
void DrawFullDotSmall(UInt_t n, const TPoint *xy) const
void DrawOpenSquareDiagonal(UInt_t n, const TPoint *xy) const
void DrawOpenDoubleDiamond(UInt_t n, const TPoint *xy) const
void DrawFullFourTrianglesX(UInt_t n, const TPoint *xy) const
void DrawFullDotLarge(UInt_t n, const TPoint *xy) const
void DrawFullThreeTriangles(UInt_t n, const TPoint *xy) const
void DrawCircle(UInt_t n, const TPoint *xy) const
void DrawFullFourTrianglesPlus(UInt_t n, const TPoint *xy) const
void DrawOpenCross(UInt_t n, const TPoint *xy) const
void DrawFullCross(UInt_t n, const TPoint *xy) const
void DrawFullTrianlgeDown(UInt_t n, const TPoint *xy) const
void DrawOpenStar(UInt_t n, const TPoint *xy) const
Full star pentagone.
void DrawX(UInt_t n, const TPoint *xy) const
void DrawPlus(UInt_t n, const TPoint *xy) const
void DrawFullTrianlgeUp(UInt_t n, const TPoint *xy) const
void DrawFullSquare(UInt_t n, const TPoint *xy) const
void DrawOpenFourTrianglesPlus(UInt_t n, const TPoint *xy) const
void DrawStar(UInt_t n, const TPoint *xy) const
void DrawFullDoubleDiamond(UInt_t n, const TPoint *xy) const
void DrawOpenCrossX(UInt_t n, const TPoint *xy) const
void DrawDot(UInt_t n, const TPoint *xy) const
Simple 1-pixel dots.
void DrawOctagonCross(UInt_t n, const TPoint *xy) const
void DrawFourSquaresX(UInt_t n, const TPoint *xy) const
void SetMarkerSizeWidth(Size_t size, Width_t width)
Set marker size and line width.
void DrawFourSquaresPlus(UInt_t n, const TPoint *xy) const
void DrawFullDotMedium(UInt_t n, const TPoint *xy) const
void DrawDiamond(UInt_t n, const TPoint *xy) const
void DrawFullStar(UInt_t n, const TPoint *xy) const
Full star pentagone.
void DrawOpenTrianlgeDown(UInt_t n, const TPoint *xy) const
void DrawFullDiamond(UInt_t n, const TPoint *xy) const
void DrawOpenFourTrianglesX(UInt_t n, const TPoint *xy) const
void DrawOpenDiamondCross(UInt_t n, const TPoint *xy) const
void * GetTess() const
Fill Area Attributes class.
Definition TAttFill.h:21
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
Line Attributes class.
Definition TAttLine.h:21
Marker Attributes class.
Definition TAttMarker.h:21
static Width_t GetMarkerLineWidth(Style_t style)
Internal helper function that returns the line width of the given marker style (0 = filled marker)
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
TColorGradient extends basic TColor.
const Double_t * GetColors() const
Get colors.
SizeType_t GetNumberOfSteps() const
Get number of steps.
ECoordinateMode GetCoordinateMode() const
Get coordinate mode.
const Double_t * GetColorPositions() const
Get color positions.
void RegisterFont(Int_t size, Int_t file, TGLFont::EMode mode, TGLFont &out)
Provide font with given size, file and FTGL class.
static Int_t GetExtendedFontStartIndex()
static const char * GetFontNameFromId(Int_t)
Get font name from TAttAxis font id.
static TObjArray * GetFontFileArray()
Get id to file name map.
Float_t Advance(const char *txt) const
Get advance.
void SetTextAlign(UInt_t align)
void BBox(const char *txt, Float_t &llx, Float_t &lly, Float_t &llz, Float_t &urx, Float_t &ury, Float_t &urz) const
Get bounding box.
void Render(const char *txt, Double_t x, Double_t y, Double_t angle, Double_t mgn) const
virtual void PostRender() const
Reset GL state after FTFont rendering.
virtual void PreRender(Bool_t autoLight=kTRUE, Bool_t lightOn=kFALSE) const
Set-up GL state before FTFont rendering.
void DrawText(Double_t x, Double_t y, const char *text, ETextMode mode) override
Draw text.
void TextExtentHelper(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const Char_t *text)
Helper function to get text extent.
void SetDrawMode(Int_t device, Int_t mode) override
Set drawing mode for specified device.
void TextAscentDescentHelper(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const Char_t *text)
Helper function to get text ascent / descent.
void DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height, Int_t dstX, Int_t dstY, Bool_t enableBlending) override
Int_t ResizeDrawable(Int_t device, UInt_t w, UInt_t h) override
Resize a gVirtualX Pixmap.
void DestroyDrawable(Int_t device) override
Not required at the moment.
void DrawGradient(const TLinearGradient *gradient, Int_t n, const Double_t *x, const Double_t *y)
Rgl::Pad::Tesselator fTess
void SelectGLFont(Font_t font, Float_t size)
Select specified font/size.
void DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) override
Draw line segment in NDC coordinates.
WinContext_t fWinContext
std::vector< TPoint > fPoly
void DrawTextHelper(Double_t x, Double_t y, const Char_t *text, ETextMode mode)
void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode) override
Draw filled or hollow box.
void SetAttLine(const TAttLine &att) override
Set line attributes.
TAttFill fGlFillAtt
void DrawPolygonWithGradient(Int_t n, const Double_t *x, const Double_t *y)
At the moment I assume both linear and radial gradients will work the same way - using a stencil buff...
void GetTextAscentDescent(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const char *mess) override
Get text extent.
void InvalidateCS() override
When TPad::Range for gPad is called, projection must be changed in OpenGL.
void ClearDrawable() override
Do nothing, sub-pads not cleared in GL.
void ClearWindow(Int_t device) override
Clear specified window - calling gVirtualX->ClearWindowW.
void DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v) override
Poly line in NDC.
void OnPad(TVirtualPad *) override
Select pad where current painting will be performed.
void DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) override
Draw poly-line in user coordinates.
Rgl::Pad::GLLimits fLimits
void SetOpacity(Int_t percent) override
Delegate to gVirtualX.
void DrawTextNDC(Double_t x, Double_t y, const char *text, ETextMode mode) override
Draw text in NDC.
void SetAttFill(const TAttFill &att) override
Set fill attributes.
void InitPainter() override
Init gl-pad painter:
void SelectDrawable(Int_t device) override
For gVirtualX this means select pixmap (or window) and all subsequent drawings will go into this pixm...
TGLFontManager fFM
Rgl::Pad::PolygonStippleSet fSSet
Rgl::Pad::MarkerPainter fMarker
void DrawPolyMarker()
Poly-marker.
void SaveViewport()
Extract and save the current viewport.
void CopyDrawable(Int_t device, Int_t px, Int_t py) override
Not required at the moment.
void SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const override
Using TImage save frame-buffer contents as a picture.
void DrawFillArea(Int_t n, const Double_t *x, const Double_t *y) override
Draw tesselated polygon (probably, outline only).
void UpdateDrawable(Int_t mode) override
Call low-level update of selected drawable, redirect to gVirtualX.
void RestoreProjectionMatrix() const
Restore the projection matrix.
void SetAttMarker(const TAttMarker &att) override
Set marker attributes.
void LockPainter() override
Locked state of painter means, that GL context can be invalid, so no GL calls can be executed.
Float_t GetTextMagnitude() const override
Delegate to gVirtualX.
void DrawTesselation(Int_t n, const Double_t *x, const Double_t *y)
Int_t CreateDrawable(UInt_t w, UInt_t h) override
Not required at the moment.
UInt_t GetTextAdvance(Font_t font, Double_t size, const char *text, Bool_t kern) override
Get text advance.
void RestoreModelviewMatrix() const
Restore the modelview matrix.
std::vector< Double_t > fVs
Bool_t fIsHollowArea
void SaveProjectionMatrix() const
Save the projection matrix.
void DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) override
Draw line segment.
void GetTextExtent(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const char *mess) override
Get text extent.
Bool_t IsCocoa() const override
Returns true when cocoa backend is used.
void SaveModelviewMatrix() const
Save the modelview matrix.
void RestoreViewport()
Restore the saved viewport.
static void InitializeIfNeeded()
Initialize globals that require other libraries to be initialized.
Definition TGLUtil.cxx:1573
static Float_t GetScreenScalingFactor()
Returns scaling factor between screen points and GL viewport pixels.
Definition TGLUtil.cxx:1843
EImageFileTypes
Definition TImage.h:36
static TImage * Create()
Create an image.
Definition TImage.cxx:34
const Point & GetEnd() const
Get end.
const Point & GetStart() const
Get start.
void SetAttFill(const TAttFill &att) override
Set fill attributes.
Color_t GetMarkerColor() const override
const TAttText & GetAttText() const override
Get text attributes.
Short_t GetTextAlign() const override
const TAttMarker & GetAttMarker() const override
Get marker attributes.
Style_t GetMarkerStyle() const override
Font_t GetTextFont() const override
Width_t GetLineWidth() const override
Bool_t fFullyTransparent
if transformed fill attributes fully transparent
void SetAttMarker(const TAttMarker &att) override
Set marker attributes.
void SetAttLine(const TAttLine &att) override
Set line attributes.
Float_t GetTextAngle() const override
TAttFill GetAttFillInternal(Bool_t with_transparency)
Returns fill attributes after modification Checks for special fill styles 4000 .
Color_t GetTextColor() const override
Style_t GetLineStyle() const override
const TAttLine & GetAttLine() const override
Get line attributes.
Float_t GetTextSize() const override
The most important graphics class in the ROOT system.
Definition TPad.h:28
Double_t GetRadius() const
Get radius.
const Point & GetCenter() const
Get center.
EGradientType GetGradientType() const
Get gradient type.
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
BoundingRect< ValueType > FindBoundingRect(Int_t nPoints, const ValueType *xs, const ValueType *ys)
void ExtractRGBA(Color_t colorIndex, Float_t *rgba)
void DrawQuadStripWithRadialGradientFill(unsigned nPoints, const Double_t *inner, const Double_t *innerRGBA, const Double_t *outer, const Double_t *outerRGBA)
TODO: is it possible to use GLdouble to avoid problems with Double_t/GLdouble if they are not the sam...
Definition TGLUtil.cxx:3216
void DrawBoxWithGradientFill(Double_t y1, Double_t y2, Double_t x1, Double_t x2, const Double_t *rgba1, const Double_t *rgba2)
Definition TGLUtil.cxx:3196
Double_t ACos(Double_t)
Returns the principal value of the arc cosine of x, expressed in radians.
Definition TMath.h:643
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
constexpr Double_t TwoPi()
Definition TMath.h:47