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
25#include "TColorGradient.h"
26#include "TGLPadPainter.h"
27#include "TGLIncludes.h"
28#include "TGLUtil.h"
29#include "TMath.h"
30
31namespace {
32
33////////////////////////////////////////////////////////////////////////////////
34///Not a bad idea to assert on gVirtualX != nullptr
35
36bool IsGradientFill(Color_t fillColorIndex)
37{
38 return dynamic_cast<TColorGradient *>(gROOT->GetColor(fillColorIndex));
39}
40
41}
42
43/** \class TGLPadPainter
44\ingroup opengl
45"Delegating" part of TGLPadPainter. Line/fill/etc. attributes can be
46set inside TPad, but not only there:
47many of them are set by base sub-objects of 2d primitives
48(2d primitives usually inherit TAttLine or TAttFill etc.). And these sub-objects
49call gVirtualX->SetLineWidth ... etc. So, if I save some attributes in my painter,
50it will be mess - at any moment I do not know, where to take line attribute - from
51gVirtualX or from my own member. So! All attributed, _ALL_ go to/from gVirtualX.
52*/
53
55
56////////////////////////////////////////////////////////////////////////////////
57
59 : fIsHollowArea(kFALSE),
60 fLocked(kTRUE)
61{
62 fVp[0] = fVp[1] = fVp[2] = fVp[3] = 0;
63}
64
65
66////////////////////////////////////////////////////////////////////////////////
67///Delegate to gVirtualX.
68
70{
71 return gVirtualX->GetLineColor();
72}
73
74////////////////////////////////////////////////////////////////////////////////
75///Delegate to gVirtualX.
76
78{
79 return gVirtualX->GetLineStyle();
80}
81
82////////////////////////////////////////////////////////////////////////////////
83///Delegate to gVirtualX.
84
86{
87 return gVirtualX->GetLineWidth();
88}
89
90////////////////////////////////////////////////////////////////////////////////
91///Delegate to gVirtualX.
92
94{
95 gVirtualX->SetLineColor(lcolor);
96}
97
98////////////////////////////////////////////////////////////////////////////////
99///Delegate to gVirtualX.
100
102{
103 gVirtualX->SetLineStyle(lstyle);
104}
105
106////////////////////////////////////////////////////////////////////////////////
107///Delegate to gVirtualX.
108
110{
111 gVirtualX->SetLineWidth(lwidth);
112}
113
114////////////////////////////////////////////////////////////////////////////////
115///Delegate to gVirtualX.
116
118{
119 return gVirtualX->GetFillColor();
120}
121
122////////////////////////////////////////////////////////////////////////////////
123///Delegate to gVirtualX.
124
126{
127 return gVirtualX->GetFillStyle();
128}
129
130////////////////////////////////////////////////////////////////////////////////
131///Delegate to gVirtualX.
132///IsTransparent is implemented as inline function in TAttFill.
133
135{
136 return gVirtualX->IsTransparent();
137}
138
139////////////////////////////////////////////////////////////////////////////////
140///Delegate to gVirtualX.
141
143{
144 gVirtualX->SetFillColor(fcolor);
145}
146
147////////////////////////////////////////////////////////////////////////////////
148///Delegate to gVirtualX.
149
151{
152 gVirtualX->SetFillStyle(fstyle);
153}
154
155////////////////////////////////////////////////////////////////////////////////
156///Delegate to gVirtualX.
157
159{
160 gVirtualX->SetOpacity(percent);
161}
162
163////////////////////////////////////////////////////////////////////////////////
164///Delegate to gVirtualX.
165
167{
168 return gVirtualX->GetTextAlign();
169}
170
171////////////////////////////////////////////////////////////////////////////////
172///Delegate to gVirtualX.
173
175{
176 return gVirtualX->GetTextAngle();
177}
178
179////////////////////////////////////////////////////////////////////////////////
180///Delegate to gVirtualX.
181
183{
184 return gVirtualX->GetTextColor();
185}
186
187////////////////////////////////////////////////////////////////////////////////
188///Delegate to gVirtualX.
189
191{
192 return gVirtualX->GetTextFont();
193}
194
195////////////////////////////////////////////////////////////////////////////////
196///Delegate to gVirtualX.
197
199{
200 return gVirtualX->GetTextSize();
201}
202
203////////////////////////////////////////////////////////////////////////////////
204///Delegate to gVirtualX.
205
207{
208 return gVirtualX->GetTextMagnitude();
209}
210
211////////////////////////////////////////////////////////////////////////////////
212///Delegate to gVirtualX.
213
215{
216 gVirtualX->SetTextAlign(align);
217}
218
219////////////////////////////////////////////////////////////////////////////////
220///Delegate to gVirtualX.
221
223{
224 gVirtualX->SetTextAngle(tangle);
225}
226
227////////////////////////////////////////////////////////////////////////////////
228///Delegate to gVirtualX.
229
231{
232 gVirtualX->SetTextColor(tcolor);
233}
234
235////////////////////////////////////////////////////////////////////////////////
236///Delegate to gVirtualX.
237
239{
240 gVirtualX->SetTextFont(tfont);
241}
242
243////////////////////////////////////////////////////////////////////////////////
244///Delegate to gVirtualX.
245
247{
248 gVirtualX->SetTextSize(tsize);
249}
250
251////////////////////////////////////////////////////////////////////////////////
252///Delegate to gVirtualX.
253
255{
256 gVirtualX->SetTextSizePixels(npixels);
257}
258
259/*
260"Pixmap" part of TGLPadPainter.
261*/
262
263////////////////////////////////////////////////////////////////////////////////
264///Not required at the moment.
265
267{
268 return 0;
269}
270
271////////////////////////////////////////////////////////////////////////////////
272///Not required at the moment.
273
275{
276}
277
278////////////////////////////////////////////////////////////////////////////////
279///Not required at the moment.
280
281void TGLPadPainter::CopyDrawable(Int_t /*device*/, Int_t /*px*/, Int_t /*py*/)
282{
283}
284
285////////////////////////////////////////////////////////////////////////////////
286///Not required at the moment.
287
289{
290}
291
292////////////////////////////////////////////////////////////////////////////////
293///For gVirtualX this means select pixmap (or window)
294///and all subsequent drawings will go into
295///this pixmap. For OpenGL this means the change of
296///coordinate system and viewport.
297
299{
300 if (fLocked)
301 return;
302
303 if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
304 Int_t px = 0, py = 0;
305
306 pad->XYtoAbsPixel(pad->GetX1(), pad->GetY1(), px, py);
307
308 py = gPad->GetWh() - py;
309 //
312
313 glViewport(GLint(px * scale), GLint(py * scale),
314 GLsizei(gPad->GetWw() * pad->GetAbsWNDC() * scale),
315 GLsizei(gPad->GetWh() * pad->GetAbsHNDC() * scale));
316
317 glMatrixMode(GL_PROJECTION);
318 glLoadIdentity();
319 glOrtho(pad->GetX1(), pad->GetX2(), pad->GetY1(), pad->GetY2(), -10., 10.);
320
321 glMatrixMode(GL_MODELVIEW);
322 glLoadIdentity();
323 glTranslated(0., 0., -1.);
324 } else {
325 ::Error("TGLPadPainter::SelectDrawable",
326 "function was called not from TPad or TCanvas code\n");
327 throw std::runtime_error("");
328 }
329}
330
331////////////////////////////////////////////////////////////////////////////////
332///Init gl-pad painter:
333///1. 2D painter does not use depth test, should not modify
334/// depth-buffer content (except initial cleanup).
335///2. Disable cull face.
336///3. Disable lighting.
337///4. Set viewport (to the whole canvas area).
338///5. Set camera.
339///6. Unlock painter.
340
342{
343 glDisable(GL_DEPTH_TEST);
344 glDisable(GL_CULL_FACE);
345 glDisable(GL_LIGHTING);
346
347 //Clear the buffer
348 glViewport(0, 0, GLsizei(gPad->GetWw()), GLsizei(gPad->GetWh()));
349
350 glDepthMask(GL_TRUE);
351 glClearColor(1.,1.,1.,1.);
352 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
353 glDepthMask(GL_FALSE);
354
355 glMatrixMode(GL_PROJECTION);
356 glLoadIdentity();
357
358 glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
359
360 glMatrixMode(GL_MODELVIEW);
361 glLoadIdentity();
362 glTranslated(0., 0., -1.);
363
364 fLocked = kFALSE;
365}
366
367////////////////////////////////////////////////////////////////////////////////
368///When TPad::Range for gPad is called, projection
369///must be changed in OpenGL.
370
372{
373 if (fLocked) return;
374
375 glMatrixMode(GL_PROJECTION);
376 glLoadIdentity();
377
378 glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
379
380 glMatrixMode(GL_MODELVIEW);
381}
382
383////////////////////////////////////////////////////////////////////////////////
384///Locked state of painter means, that
385///GL context can be invalid, so no GL calls
386///can be executed.
387
389{
390 if (fLocked) return;
391
392 glFinish();
393 fLocked = kTRUE;
394}
395
396/*
3972D primitives.
398*/
399
401
402////////////////////////////////////////////////////////////////////////////////
403///Draw line segment.
404
406{
407 if (fLocked) {
408 //GL pad painter can be called in non-standard situation:
409 //not from TPad::Paint, but
410 //from TView3D::ExecuteRotateView. This means in fact,
411 //that TView3D wants to draw itself in a XOR mode, via
412 //gVirtualX.
413 if (gVirtualX->GetDrawMode() == TVirtualX::kInvert) {
414 gVirtualX->DrawLine(gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1),
415 gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2));
416 }
417
418 return;
419 }
420
421 const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
422
423 glBegin(GL_LINES);
424 glVertex2d(x1, y1);
425 glVertex2d(x2, y2);
426 glEnd();
427
428 if (gVirtualX->GetLineWidth() > lineWidthTS) {
429 Double_t pointSize = gVirtualX->GetLineWidth();
430 if (pointSize > fLimits.GetMaxPointSize())
431 pointSize = fLimits.GetMaxPointSize();
432 glPointSize((GLfloat)pointSize);
433 const TGLEnableGuard pointSmooth(GL_POINT_SMOOTH);
434 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
435 glBegin(GL_POINTS);
436
437 glVertex2d(x1, y1);
438 glVertex2d(x2, y2);
439
440 glEnd();
441 glPointSize(1.f);
442 }
443
444}
445
446////////////////////////////////////////////////////////////////////////////////
447///Draw line segment in NDC coordinates.
448
450{
451 if (fLocked) return;
452
453 const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
454 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
455 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
456
457 glBegin(GL_LINES);
458 glVertex2d(gPad->GetX1() + u1 * xRange, gPad->GetY1() + v1 * yRange);
459 glVertex2d(gPad->GetX1() + u2 * xRange, gPad->GetY1() + v2 * yRange);
460 glEnd();
461}
462
463////////////////////////////////////////////////////////////////////////////////
464///Draw filled or hollow box.
465
467{
468 if (fLocked) return;
469
470 if (IsGradientFill(gVirtualX->GetFillColor())) {
471 Double_t xs[] = {x1, x2, x2, x1};
472 Double_t ys[] = {y1, y1, y2, y2};
473 DrawPolygonWithGradient(4, xs, ys);
474 return;
475 }
476
477 if (mode == kHollow) {
479 //
480 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
481 glRectd(x1, y1, x2, y2);
482 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
483 glLineWidth(1.f);
484 } else {
485 const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);//Set filling parameters.
486 glRectd(x1, y1, x2, y2);
487 }
488}
489
490////////////////////////////////////////////////////////////////////////////////
491///Draw tesselated polygon (probably, outline only).
492
494{
495 assert(x != nullptr && "DrawFillArea, parameter 'x' is null");
496 assert(y != nullptr && "DrawFillArea, parameter 'y' is null");
497
498 if (fLocked)
499 return;
500
501 if (n < 3) {
502 ::Error("TGLPadPainter::DrawFillArea",
503 "invalid number of points in a polygon");
504 return;
505 }
506
507 if (IsGradientFill(gVirtualX->GetFillColor()))
508 return DrawPolygonWithGradient(n, x, y);
509
510 if (!gVirtualX->GetFillStyle()) {
512 return DrawPolyLine(n, x, y);
513 }
514
515 const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);
516 DrawTesselation(n, x, y);
517}
518
519////////////////////////////////////////////////////////////////////////////////
520///Draw tesselated polygon (never called, probably, since TPad::PaintFillArea for floats
521///is deprecated).
522
524{
525 if (fLocked) return;
526
527 if (!gVirtualX->GetFillStyle()) {
529 return DrawPolyLine(n, x, y);
530 }
531
532 fVs.resize(n * 3);
533
534 for (Int_t i = 0; i < n; ++i) {
535 fVs[i * 3] = x[i];
536 fVs[i * 3 + 1] = y[i];
537 }
538
539 const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);
540
544
545 for (Int_t i = 0; i < n; ++i)
546 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
547
548
549 gluEndPolygon(t);
550}
551
552////////////////////////////////////////////////////////////////////////////////
553///Draw poly-line in user coordinates.
554
556{
557 if (fLocked) return;
558
559 const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
560
561 glBegin(GL_LINE_STRIP);
562
563 for (Int_t i = 0; i < n; ++i)
564 glVertex2d(x[i], y[i]);
565
566 if (fIsHollowArea) {
567 glVertex2d(x[0], y[0]);
569 }
570 glEnd();
571
572 if (gVirtualX->GetLineWidth() > lineWidthTS) {
573 Double_t pointSize = gVirtualX->GetLineWidth();
574 if (pointSize > fLimits.GetMaxPointSize())
575 pointSize = fLimits.GetMaxPointSize();
576 glPointSize((GLfloat)pointSize);
577 const TGLEnableGuard pointSmooth(GL_POINT_SMOOTH);
578 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
579 glBegin(GL_POINTS);
580
581 for (Int_t i = 0; i < n; ++i)
582 glVertex2d(x[i], y[i]);
583
584 glEnd();
585 glPointSize(1.f);
586 }
587}
588
589////////////////////////////////////////////////////////////////////////////////
590///Never called?
591
593{
594 if (fLocked) return;
595
596 const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
597
598 glBegin(GL_LINE_STRIP);
599
600 for (Int_t i = 0; i < n; ++i)
601 glVertex2f(x[i], y[i]);
602
603 if (fIsHollowArea) {
604 glVertex2f(x[0], y[0]);
606 }
607
608 glEnd();
609}
610
611////////////////////////////////////////////////////////////////////////////////
612///Poly line in NDC.
613
615{
616 if (fLocked) return;
617
618 const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
619 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
620 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
621 const Double_t x1 = gPad->GetX1(), y1 = gPad->GetY1();
622
623 glBegin(GL_LINE_STRIP);
624
625 for (Int_t i = 0; i < n; ++i)
626 glVertex2d(x1 + u[i] * xRange, y1 + v[i] * yRange);
627
628 glEnd();
629}
630
631namespace {
632
633//Aux. function.
634template<class ValueType>
635void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector<TPoint> & dst);
636
637}
638
639////////////////////////////////////////////////////////////////////////////////
640///Poly-marker.
641
643{
644 if (fLocked) return;
645
646 ConvertMarkerPoints(n, x, y, fPoly);
648}
649
650////////////////////////////////////////////////////////////////////////////////
651///Poly-marker.
652
654{
655 if (fLocked) return;
656
657 ConvertMarkerPoints(n, x, y, fPoly);
659}
660
661////////////////////////////////////////////////////////////////////////////////
662///Poly-marker.
663
665{
666 if (fLocked) return;
667
669 glLoadIdentity();
670 //
671 glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
672 //
673 glMatrixMode(GL_MODELVIEW);
674 //
675 const TGLEnableGuard blendGuard(GL_BLEND);
676
677 Float_t rgba[4] = {};
678 Rgl::Pad::ExtractRGBA(gVirtualX->GetMarkerColor(), rgba);
679 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
680 glColor4fv(rgba);
681
682 const Width_t w = TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())));
683 glLineWidth(w > fLimits.GetMaxLineWidth() ? fLimits.GetMaxLineWidth() : !w ? 1.f : w);
684
685 const TPoint *xy = &fPoly[0];
686 const Style_t markerStyle = TAttMarker::GetMarkerStyleBase(gVirtualX->GetMarkerStyle());
687 const UInt_t n = UInt_t(fPoly.size());
688 switch (markerStyle) {
689 case kDot:
691 break;
692 case kPlus:
694 break;
695 case kStar:
696 case 31:
698 break;
699 case kCircle:
700 case kOpenCircle:
702 break;
703 case kMultiply:
704 fMarker.DrawX(n, xy);
705 break;
706 case kFullDotSmall://"Full dot small"
708 break;
709 case kFullDotMedium:
711 break;
712 case kFullDotLarge:
713 case kFullCircle:
715 break;
716 case kFullSquare:
718 break;
719 case kFullTriangleUp:
721 break;
724 break;
725 case kOpenSquare:
726 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
728 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
729 break;
730 case kOpenTriangleUp:
731 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
733 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
734 break;
735 case kOpenDiamond:
737 break;
738 case kOpenCross:
740 break;
741 case kFullStar:
743 break;
744 case kOpenStar:
746 break;
749 break;
750 case kFullDiamond:
752 break;
753 case kFullCross:
755 break;
758 break;
761 break;
764 break;
765 case kOctagonCross:
767 break;
770 break;
773 break;
776 break;
779 break;
782 break;
785 break;
788 break;
789 case kOpenCrossX:
791 break;
792 case kFullCrossX:
794 break;
795 case kFourSquaresX:
797 break;
798 case kFourSquaresPlus:
800 break;
801 }
802
804 glMatrixMode(GL_MODELVIEW);
805 glLineWidth(1.f);
806}
807
808////////////////////////////////////////////////////////////////////////////////
809
810template<class Char>
812{
814
815 glLoadIdentity();
816 //
817 glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
818 //
819 glMatrixMode(GL_MODELVIEW);
820
821 Float_t rgba[4] = {};
822 Rgl::Pad::ExtractRGBA(gVirtualX->GetTextColor(), rgba);
823 glColor4fv(rgba);
824
825 //10 is the first valid font index.
826 //20 is FreeSerifBold, as in TTF.cxx and in TGLFontManager.cxx.
827 //shift - is the shift to access "extended" fonts.
829
830 Int_t fontIndex = TMath::Max(Short_t(10), gVirtualX->GetTextFont());
831 if (fontIndex / 10 + shift > TGLFontManager::GetFontFileArray()->GetEntries())
832 fontIndex = 20 + shift * 10;
833 else
834 fontIndex += shift * 10;
835
836 fFM.RegisterFont(TMath::Max(Int_t(gVirtualX->GetTextSize()) - 1, 10),//kTexture does not work if size < 10.
839 fF.PreRender();
840
841 const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
842 fF.Render(text, gPad->XtoPixel(x), padH - gPad->YtoPixel(y), GetTextAngle(), GetTextMagnitude());
843
844 fF.PostRender();
846
847 glMatrixMode(GL_MODELVIEW);
848}
849
850////////////////////////////////////////////////////////////////////////////////
851///Draw text. This operation is especially
852///dangerous if in locked state -
853///ftgl will assert on zero texture size
854///(which is result of bad GL context).
855
857{
858 if (fLocked) return;
859
860 if (!gVirtualX->GetTextSize())
861 return;
862
864}
865
866////////////////////////////////////////////////////////////////////////////////
867///Draw text. This operation is especially
868///dangerous if in locked state -
869///ftgl will assert on zero texture size
870///(which is result of bad GL context).
871
873{
874 if (fLocked) return;
875
876 if (!gVirtualX->GetTextSize())
877 return;
878
880}
881
882////////////////////////////////////////////////////////////////////////////////
883///Draw text in NDC. This operation is especially
884///dangerous if in locked state -
885///ftgl will assert on zero texture size
886///(which is result of bad GL context).
887
889{
890 if (fLocked) return;
891
892 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
893 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
894 DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
895}
896
897////////////////////////////////////////////////////////////////////////////////
898///Draw text in NDC. This operation is especially
899///dangerous if in locked state -
900///ftgl will assert on zero texture size
901///(which is result of bad GL context).
902
904{
905 if (fLocked) return;
906
907 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
908 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
909 DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
910}
911
912////////////////////////////////////////////////////////////////////////////////
913///Save the projection matrix.
914///Attention! GL_PROJECTION will become the current matrix
915///after this call!
916
918{
919 glMatrixMode(GL_PROJECTION);
920 glPushMatrix();
921}
922
923////////////////////////////////////////////////////////////////////////////////
924///Restore the projection matrix.
925///Attention! GL_PROJECTION will become the current matrix
926///after this call!
927
929{
930 glMatrixMode(GL_PROJECTION);
931 glPopMatrix();
932}
933
934////////////////////////////////////////////////////////////////////////////////
935///Save the modelview matrix.
936///Attention! GL_MODELVIEW will become the current matrix
937///after this call!
938
940{
941 glMatrixMode(GL_MODELVIEW);
942 glPushMatrix();
943}
944
945////////////////////////////////////////////////////////////////////////////////
946///Restore the modelview matrix.
947///Attention! GL_MODELVIEW will become the current matrix
948///after this call!
949
951{
952 glMatrixMode(GL_MODELVIEW);
953 glPopMatrix();
954}
955
956////////////////////////////////////////////////////////////////////////////////
957///Extract and save the current viewport.
958
960{
961 glGetIntegerv(GL_VIEWPORT, fVp);
962}
963
964////////////////////////////////////////////////////////////////////////////////
965///Restore the saved viewport.
966
968{
969 glViewport(fVp[0], fVp[1], fVp[2], fVp[3]);
970}
971
972////////////////////////////////////////////////////////////////////////////////
973/// Using TImage save frame-buffer contents as a picture.
974
975void TGLPadPainter::SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const
976{
977 TVirtualPad *canvas = (TVirtualPad *)pad->GetCanvas();
978 if (!canvas)
979 return;
980
981 gROOT->ProcessLine(Form("((TCanvas *)0x%zx)->Flush();", (size_t)canvas));
982
983 std::vector<unsigned> buff(canvas->GetWw() * canvas->GetWh());
984 glPixelStorei(GL_PACK_ALIGNMENT, 1);
985 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
986 //In case GL_BGRA is not in gl.h (old windows' gl) - comment/uncomment lines.
987 //glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_BGRA, GL_UNSIGNED_BYTE, (char *)&buff[0]);
988 glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_RGBA, GL_UNSIGNED_BYTE, (char *)&buff[0]);
989
990 std::unique_ptr<TImage> image(TImage::Create());
991 if (!image.get()) {
992 ::Error("TGLPadPainter::SaveImage", "TImage creation failed");
993 return;
994 }
995
996 image->DrawRectangle(0, 0, canvas->GetWw(), canvas->GetWh());
997 UInt_t *argb = image->GetArgbArray();
998
999 if (!argb) {
1000 ::Error("TGLPadPainter::SaveImage", "null argb array in TImage object");
1001 return;
1002 }
1003
1004 const Int_t nLines = canvas->GetWh();
1005 const Int_t nPixels = canvas->GetWw();
1006
1007 for (Int_t i = 0; i < nLines; ++i) {
1008 Int_t base = (nLines - 1 - i) * nPixels;
1009 for (Int_t j = 0; j < nPixels; ++j, ++base) {
1010 //Uncomment/comment if you don't have GL_BGRA.
1011
1012 const UInt_t pix = buff[base];
1013 const UInt_t bgra = ((pix & 0xff) << 16) | (pix & 0xff00) |
1014 ((pix & 0xff0000) >> 16) | (pix & 0xff000000);
1015
1016 //argb[i * nPixels + j] = buff[base];
1017 argb[i * nPixels + j] = bgra;
1018 }
1019 }
1020
1021 image->WriteImage(fileName, (TImage::EImageFileTypes)type);
1022}
1023
1024////////////////////////////////////////////////////////////////////////////////
1025
1026void TGLPadPainter::DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height,
1027 Int_t dstX, Int_t dstY, Bool_t enableBlending)
1028{
1029 if (fLocked)
1030 return;
1031
1032 if (!pixelData) {
1033 //I'd prefer an assert.
1034 ::Error("TGLPadPainter::DrawPixels", "pixel data is null");
1035 return;
1036 }
1037
1038 if (std::numeric_limits<UInt_t>::digits >= 32) {
1039 //TASImage uses bit 31 as ...
1040 //alpha channel flag! FUUUUUUUUUUUUU ..... !!!
1041 CLRBIT(width, 31);
1042 CLRBIT(height, 31);
1043 }
1044
1045 if (!width) {
1046 //Assert is better.
1047 ::Error("TGLPadPainter::DrawPixels", "invalid width");
1048 return;
1049 }
1050
1051 if (!height) {
1052 //Assert is better.
1053 ::Error("TGLPadPainter::DrawPixels", "invalid height");
1054 return;
1055 }
1056
1057 if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
1058 //TASImage passes pixel coordinates in pad's pixmap coordinate space.
1059 //While glRasterPosX said to work with 'window' coordinates,
1060 //that's a lie :) it does not :)
1061
1062 const Double_t rasterX = Double_t(dstX) / (pad->GetAbsWNDC() * pad->GetWw()) *
1063 (pad->GetX2() - pad->GetX1()) + pad->GetX1();
1064
1065 const Double_t yRange = pad->GetY2() - pad->GetY1();
1066 const Double_t rasterY = yRange - Double_t(dstY + height) / (pad->GetAbsHNDC() * pad->GetWh()) * yRange +
1067 pad->GetY1();
1068
1069 GLdouble oldPos[4] = {};
1070 //Save the previous raster pos.
1071 glGetDoublev(GL_CURRENT_RASTER_POSITION, oldPos);
1072
1073 glRasterPos2d(rasterX, rasterY);
1074 //Stupid asimage provides us upside-down image.
1075 std::vector<unsigned char> upsideDownImage(4 * width * height);
1076 const unsigned char *srcLine = pixelData + 4 * width * (height - 1);
1077 unsigned char *dstLine = &upsideDownImage[0];
1078 for (UInt_t i = 0; i < height; ++i, srcLine -= 4 * width, dstLine += 4 * width)
1079 std::copy(srcLine, srcLine + 4 * width, dstLine);
1080
1081 if (enableBlending) {
1082 glEnable(GL_BLEND);
1083 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1084 }
1085
1086 glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, &upsideDownImage[0]);
1087
1088 if (enableBlending)
1089 glDisable(GL_BLEND);
1090
1091 //Restore raster pos.
1092 glRasterPos2d(oldPos[0], oldPos[1]);
1093 } else
1094 ::Error("TGLPadPainter::DrawPixels", "no pad found to draw");
1095}
1096
1097//Aux. functions - gradient and solid fill of arbitrary area.
1098
1099////////////////////////////////////////////////////////////////////////////////
1100///At the moment I assume both linear and radial gradients will work the same way -
1101///using a stencil buffer and some big rectangle(s) to fill with a gradient.
1102///Thus I have a 'common' part - the part responsible for a stencil test.
1103
1105{
1106 assert(n > 2 && "DrawPolygonWithGradient, invalid number of points");
1107 assert(x != nullptr && "DrawPolygonWithGradient, parameter 'x' is null");
1108 assert(y != nullptr && "DrawPolygonWithGradient, parameter 'y' is null");
1109
1110 assert(dynamic_cast<TColorGradient *>(gROOT->GetColor(gVirtualX->GetFillColor())) != nullptr &&
1111 "DrawPolygonWithGradient, the current fill color is not a gradient fill");
1112 const TColorGradient * const grad =
1113 dynamic_cast<TColorGradient *>(gROOT->GetColor(gVirtualX->GetFillColor()));
1114
1115 if (fLocked)
1116 return;
1117
1118 //Now, some magic!
1119 const TGLEnableGuard stencilGuard(GL_STENCIL_TEST);
1120
1121 //TODO: check that the state is restored back correctly after
1122 // we done with a gradient.
1123 //TODO: make sure that we have glDepthMask set to false in general!
1124 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1125
1126 glStencilFunc(GL_NEVER, 1, 0xFF);
1127 glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);// draw 1s on test fail (always)
1128 //Draw stencil pattern
1129 glStencilMask(0xFF);
1130 glClear(GL_STENCIL_BUFFER_BIT);
1131
1132 //Draw our polygon into the stencil buffer:
1133 DrawTesselation(n, x, y);
1134
1135 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1136 glStencilMask(0x00);
1137 //Draw where stencil's value is 0
1138 glStencilFunc(GL_EQUAL, 0, 0xFF);
1139 //Draw only where stencil's value is 1
1140 glStencilFunc(GL_EQUAL, 1, 0xFF);
1141
1142 //At the moment radial gradient is derived from linear - it was convenient
1143 //at some point, but in fact it was a bad idea. And now I have to
1144 //first check radial gradient.
1145 //TODO: TRadialGradient must inherit TColorGradient directly.
1146 const TRadialGradient * const rGrad = dynamic_cast<const TRadialGradient *>(grad);
1147 if (rGrad)
1148 DrawGradient(rGrad, n, x, y);
1149 else {
1150 const TLinearGradient * const lGrad = dynamic_cast<const TLinearGradient *>(grad);
1151 assert(lGrad != nullptr && "DrawPolygonWithGradient, unknown gradient type");
1152 DrawGradient(lGrad, n, x, y);
1153 }
1154}
1155
1156////////////////////////////////////////////////////////////////////////////////
1157
1159 const Double_t *xs, const Double_t *ys)
1160{
1161 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1162 assert(nPoints > 2 && "DrawGradient, invalid number of points");
1163 assert(xs != nullptr && "DrawGradient, parameter 'xs' is null");
1164 assert(ys != nullptr && "DrawGradient, parameter 'ys' is null");
1165
1167 ::Warning("TGLPadPainter::DrawGradient",
1168 "extended radial gradient is not supported");//yet?
1169 return;
1170 }
1171
1172 //TODO: check the polygon's bbox!
1173 const auto &bbox = Rgl::Pad::FindBoundingRect(nPoints, xs, ys);
1174 //
1175 auto center = grad->GetCenter();
1176 auto radius = grad->GetRadius();
1177 //Adjust the center and radius depending on coordinate mode.
1179 radius *= TMath::Max(bbox.fWidth, bbox.fHeight);
1180 center.fX = bbox.fWidth * center.fX + bbox.fXMin;
1181 center.fY = bbox.fHeight * center.fY + bbox.fYMin;
1182 } else {
1183 const auto w = gPad->GetX2() - gPad->GetX1();
1184 const auto h = gPad->GetY2() - gPad->GetY1();
1185
1186 radius *= TMath::Max(w, h);
1187 center.fX *= w;
1188 center.fY *= h;
1189 }
1190 //Now for the gradient fill we switch into pixel coordinates:
1191 const auto pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1192 const auto pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1193 //
1196 //A new ortho projection:
1197 glMatrixMode(GL_PROJECTION);
1198 glLoadIdentity();
1199 //
1200 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1201 //
1202 radius *= TMath::Max(pixelH, pixelW);
1203 center.fX = gPad->XtoPixel(center.fX);
1204 center.fY = pixelH - gPad->YtoPixel(center.fY);
1205
1206 Double_t maxR = 0.;
1207 {
1208 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1209 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1210 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1211 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1212 //Get the longest distance from the center to the bounding box vertices
1213 //(this will be the maximum possible radius):
1214 const Double_t maxDistX = TMath::Max(TMath::Abs(center.fX - xMin),
1215 TMath::Abs(center.fX - xMax));
1216 const Double_t maxDistY = TMath::Max(TMath::Abs(center.fY - yMin),
1217 TMath::Abs(center.fY - yMax));
1218 maxR = TMath::Sqrt(maxDistX * maxDistX + maxDistY * maxDistY);
1219 }
1220
1221 //If gradient 'stops inside the polygon', we use
1222 //the solid fill for the area outside of radial gradient:
1223 const Bool_t solidFillAfter = maxR > radius;
1224 //We emulate a radial gradient using triangles and linear gradient:
1225 //TODO: Can be something smarter? (btw even 100 seems to be enough)
1226 const UInt_t nSlices = 500;
1227
1228 const auto nColors = grad->GetNumberOfSteps();
1229 //+1 - the strip from the last color's position to radius,
1230 //and (probably) + 1 for solidFillAfter.
1231 const auto nCircles = nColors + 1 + solidFillAfter;
1232
1233 //TODO: can locations be outside of [0., 1.] ???
1234 //at the moment I assume the answer is NO, NEVER.
1235 const auto locations = grad->GetColorPositions();
1236 // * 2 below == x,y
1237 std::vector<Double_t> circles(nSlices * nCircles * 2);
1238 const Double_t angle = TMath::TwoPi() / nSlices;
1239
1240 //"Main" circles (for colors at locations[i]).
1241 for (UInt_t i = 0; i < nColors; ++i) {
1242 const auto circle = &circles[i * nSlices * 2];
1243 //TODO: either check locations here or somewhere else.
1244 const auto r = radius * locations[i];
1245 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1246 circle[j] = center.fX + r * TMath::Cos(angle * j);
1247 circle[j + 1] = center.fY + r * TMath::Sin(angle * j);
1248 }
1249 //The "closing" vertices:
1250 circle[(nSlices - 1) * 2] = circle[0];
1251 circle[(nSlices - 1) * 2 + 1] = circle[1];
1252 }
1253
1254 {
1255 //The strip between lastPos and radius:
1256 const auto circle = &circles[nColors * nSlices * 2];
1257 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1258 circle[j] = center.fX + radius * TMath::Cos(angle * j);
1259 circle[j + 1] = center.fY + radius * TMath::Sin(angle * j);
1260 }
1261
1262 circle[(nSlices - 1) * 2] = circle[0];
1263 circle[(nSlices - 1) * 2 + 1] = circle[1];
1264 }
1265
1266 if (solidFillAfter) {
1267 //The strip after the radius:
1268 const auto circle = &circles[(nCircles - 1) * nSlices * 2];
1269 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1270 circle[j] = center.fX + maxR * TMath::Cos(angle * j);
1271 circle[j + 1] = center.fY + maxR * TMath::Sin(angle * j);
1272 }
1273
1274 circle[(nSlices - 1) * 2] = circle[0];
1275 circle[(nSlices - 1) * 2 + 1] = circle[1];
1276 }
1277
1278 //Now we draw:
1279 //1) triangle fan in the center (from center to the locations[1],
1280 // with a solid fill).
1281 //2) quad strips for colors.
1282 //3) additional quad strip from the lastLocation to the radius
1283 //4) additional quad strip (if any) from the radius to maxR.
1284
1285 //RGBA values:
1286 const auto rgba = grad->GetColors();
1287
1288 const TGLEnableGuard alphaGuard(GL_BLEND);
1289 //TODO?
1290 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1291
1292 //Probably a degenerated case. Maybe not.
1293 glBegin(GL_TRIANGLE_FAN);
1294 glColor4dv(rgba);
1295 glVertex2d(center.fX, center.fY);
1296
1297 for (UInt_t i = 0, e = nSlices * 2; i < e; i += 2)
1298 glVertex2dv(&circles[i]);
1299
1300 glEnd();
1301
1302 //No auto for circles, explicit types to have const Double_t * const, not Duble_t * const.
1303 for (UInt_t i = 0; i < nColors - 1; ++i) {
1304 const Double_t * const inner = &circles[i * nSlices * 2];
1305 const auto innerRGBA = rgba + i * 4;
1306 const auto outerRGBA = rgba + (i + 1) * 4;
1307 const Double_t * const outer = &circles[(i + 1) * nSlices * 2];
1308
1309 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, innerRGBA, outer, outerRGBA);
1310 }
1311
1312 //Probably degenerated strip.
1313 {
1314 glBegin(GL_QUAD_STRIP);
1315 const Double_t * const inner = &circles[nSlices * (nColors - 1) * 2];
1316 const auto solidRGBA = rgba + (nColors - 1) * 4;
1317 const Double_t * const outer = &circles[nSlices * nColors * 2];
1318
1319 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, solidRGBA, outer, solidRGBA);
1320 }
1321
1322 if (solidFillAfter) {
1323 glBegin(GL_QUAD_STRIP);
1324 const Double_t * const inner = &circles[nSlices * nColors * 2];
1325 const auto solidRGBA = rgba + (nColors - 1) * 4;
1326 const Double_t * const outer = &circles[nSlices * (nColors + 1) * 2];
1327
1328 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, solidRGBA, outer, solidRGBA);
1329 }
1330
1333}
1334
1335////////////////////////////////////////////////////////////////////////////////
1336
1338 const Double_t *x, const Double_t *y)
1339{
1340 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1341 assert(n > 2 && "DrawGradient, invalid number of points");
1342 assert(x != nullptr && "DrawGradient, parameter 'x' is null");
1343 assert(y != nullptr && "DrawGradient, parameter 'y' is null");
1344
1345 //Now we fill the whole scene with one big rectangle
1346 //(group of rectangles) with a gradient fill using
1347 //stencil test.
1348
1349 //Find a bounding rect.
1350 const auto &bbox = Rgl::Pad::FindBoundingRect(n, x, y);
1351 //TODO: check the bbox??
1352
1353 //For the gradient fill we switch into the
1354 //pixel coordinates.
1357
1358 //A new ortho projection:
1359 glMatrixMode(GL_PROJECTION);
1360 glLoadIdentity();
1361
1362 const Double_t pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1363 const Double_t pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1364 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1365
1366 //A new modelview:
1367 glMatrixMode(GL_MODELVIEW);
1368 glLoadIdentity();
1369 //
1370 TColorGradient::Point start = grad->GetStart();
1371 TColorGradient::Point end = grad->GetEnd();
1372
1373 //Change gradient coordinates from 'NDC' to pad coords:
1375 {
1376 const Double_t w = gPad->GetX2() - gPad->GetX1();
1377 const Double_t h = gPad->GetY2() - gPad->GetY1();
1378
1379 start.fX = start.fX * w;
1380 start.fY = start.fY * h;
1381 end.fX = end.fX * w;
1382 end.fY = end.fY * h;
1383 } else {
1384 start.fX = start.fX * bbox.fWidth + bbox.fXMin;
1385 start.fY = start.fY * bbox.fHeight + bbox.fYMin;
1386 end.fX = end.fX * bbox.fWidth + bbox.fXMin;
1387 end.fY = end.fY * bbox.fHeight + bbox.fYMin;
1388 }
1389
1390 //TODO: with a radial fill we'll have to extract the code
1391 // below into the separate function/and have additional function
1392 // for a radial gradient.
1393 //Now from pad to pixels:
1394 start.fX = gPad->XtoPixel(start.fX);
1395 start.fY = pixelH - gPad->YtoPixel(start.fY);
1396 end.fX = gPad->XtoPixel(end.fX);
1397 end.fY = pixelH - gPad->YtoPixel(end.fY);
1398 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1399 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1400 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1401 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1402 //
1403
1404 //TODO: check all calculations!
1405
1406 //Get the longest distance from the start point to the bounding box vertices:
1407 const Double_t maxDistX = TMath::Max(TMath::Abs(start.fX - xMin), TMath::Abs(start.fX - xMax));
1408 const Double_t maxDistY = TMath::Max(TMath::Abs(start.fY - yMin), TMath::Abs(start.fY - yMax));
1409
1410 const Double_t startEndLength = TMath::Sqrt((end.fX - start.fX) * (end.fX - start.fX) +
1411 (end.fY - start.fY) * (end.fY - start.fY));
1412 const Double_t h = TMath::Max(TMath::Sqrt(maxDistX * maxDistX + maxDistY * maxDistY),
1413 startEndLength);
1414
1415 //Boxes with a gradients to emulate gradient fill with many colors:
1416 const Double_t * const colorPositions = grad->GetColorPositions();
1417 std::vector<Double_t> gradBoxes(grad->GetNumberOfSteps() + 2);
1418 gradBoxes[0] = start.fY - h;
1419 for (unsigned i = 1; i <= grad->GetNumberOfSteps(); ++i)
1420 gradBoxes[i] = startEndLength * colorPositions[i - 1] + start.fY;
1421
1422 gradBoxes[grad->GetNumberOfSteps() + 1] = start.fY + h;
1423
1424 //Rotation angle - gradient's axis:
1425 Double_t angle = TMath::ACos((startEndLength * (end.fY - start.fY)) /
1426 (startEndLength * startEndLength)) * TMath::RadToDeg();
1427 if (end.fX > start.fX)
1428 angle *= -1;
1429
1430 glTranslated(start.fX, start.fY, 0.);
1431 glRotated(angle, 0., 0., 1.);
1432 glTranslated(-start.fX, -start.fY, 0.);
1433 //
1434 const Double_t * const rgba = grad->GetColors();
1435
1436 const unsigned nEdges = gradBoxes.size();
1437 const unsigned nColors = grad->GetNumberOfSteps();
1438 const Double_t xLeft = start.fX - h, xRight = start.fX + h;
1439
1440 const TGLEnableGuard alphaGuard(GL_BLEND);
1441 //TODO?
1442 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1443
1444 Rgl::DrawBoxWithGradientFill(gradBoxes[0], gradBoxes[1], xLeft, xRight, rgba, rgba);
1445 Rgl::DrawBoxWithGradientFill(gradBoxes[nEdges - 2], gradBoxes[nEdges - 1], xLeft, xRight,
1446 rgba + (nColors - 1) * 4, rgba + (nColors - 1) * 4);
1447
1448 for (unsigned i = 1; i < nEdges - 2; ++i)
1449 Rgl::DrawBoxWithGradientFill(gradBoxes[i], gradBoxes[i + 1], xLeft,
1450 xRight, rgba + (i - 1) * 4, rgba + i * 4);
1451
1454}
1455
1456////////////////////////////////////////////////////////////////////////////////
1457
1459{
1460 assert(n > 2 && "DrawTesselation, invalid number of points");
1461 assert(x != nullptr && "DrawTesselation, parameter 'x' is null");
1462 assert(y != nullptr && "DrawTesselation, parameter 'y' is null");
1463
1464 //Data for a tesselator:
1465 fVs.resize(n * 3);
1466
1467 for (Int_t i = 0; i < n; ++i) {
1468 fVs[i * 3] = x[i];
1469 fVs[i * 3 + 1] = y[i];
1470 fVs[i * 3 + 2] = 0.;
1471 }
1472
1473 //TODO: A very primitive way to tesselate - check what
1474 //kind of polygons we can really have from TPad/TCanvas.
1476 gluBeginPolygon(t);
1478
1479 for (Int_t i = 0; i < n; ++i)
1480 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
1481
1482 gluEndPolygon(t);
1483}
1484
1485
1486//Aux. functions.
1487namespace {
1488
1489template<class ValueType>
1490void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector<TPoint> & dst)
1491{
1492 const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
1493
1494 dst.resize(n);
1495 for (Int_t i = 0; i < n; ++i) {
1496 dst[i].fX = gPad->XtoPixel(x[i]);
1497 dst[i].fY = padH - gPad->YtoPixel(y[i]);
1498 }
1499}
1500
1501}
1502
#define GL_TRUE
Definition GL_glu.h:262
float GLfloat
Definition GL_glu.h:277
#define GL_TRIANGLE_FAN
Definition GL_glu.h:289
void gluNextContour(GLUtesselator *tess, GLenum type)
Definition tess.c:630
#define GL_LINE_STRIP
Definition GL_glu.h:286
#define GL_LINES
Definition GL_glu.h:284
#define GLU_UNKNOWN
Definition GL_glu.h:229
int GLint
Definition GL_glu.h:272
void gluBeginPolygon(GLUtesselator *tess)
Definition tess.c:621
#define GL_POINTS
Definition GL_glu.h:283
int GLsizei
Definition GL_glu.h:276
void gluEndPolygon(GLUtesselator *tess)
Definition tess.c:639
#define GL_FALSE
Definition GL_glu.h:261
void gluTessVertex(GLUtesselator *tess, GLdouble *location, GLvoid *data)
Definition tess.c:425
#define GL_QUAD_STRIP
Definition GL_glu.h:291
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
short Style_t
Definition RtypesCore.h:82
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:85
unsigned int UInt_t
Definition RtypesCore.h:46
short Width_t
Definition RtypesCore.h:84
float Float_t
Definition RtypesCore.h:57
short Font_t
Definition RtypesCore.h:81
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
#define ClassImp(name)
Definition Rtypes.h:382
#define CLRBIT(n, i)
Definition Rtypes.h:92
@ kOpenDoubleDiamond
Definition TAttMarker.h:63
@ kStar
Definition TAttMarker.h:53
@ kFullDotLarge
Definition TAttMarker.h:54
@ kFullDoubleDiamond
Definition TAttMarker.h:63
@ kOpenFourTrianglesX
Definition TAttMarker.h:62
@ kOpenSquare
Definition TAttMarker.h:56
@ kFullThreeTriangles
Definition TAttMarker.h:61
@ kOpenTriangleUp
Definition TAttMarker.h:57
@ kFourSquaresPlus
Definition TAttMarker.h:66
@ kFullDotSmall
Definition TAttMarker.h:54
@ kFullDotMedium
Definition TAttMarker.h:54
@ kOpenTriangleDown
Definition TAttMarker.h:58
@ kOpenThreeTriangles
Definition TAttMarker.h:60
@ kFullCrossX
Definition TAttMarker.h:65
@ kFullFourTrianglesX
Definition TAttMarker.h:62
@ kFullTriangleDown
Definition TAttMarker.h:56
@ kCircle
Definition TAttMarker.h:53
@ kOpenCrossX
Definition TAttMarker.h:65
@ kFullFourTrianglesPlus
Definition TAttMarker.h:64
@ kFullSquare
Definition TAttMarker.h:55
@ kOpenSquareDiagonal
Definition TAttMarker.h:60
@ kFullStar
Definition TAttMarker.h:58
@ kOpenDiamond
Definition TAttMarker.h:57
@ kFullTriangleUp
Definition TAttMarker.h:55
@ kOpenDiamondCross
Definition TAttMarker.h:59
@ kOpenFourTrianglesPlus
Definition TAttMarker.h:64
@ kMultiply
Definition TAttMarker.h:53
@ kPlus
Definition TAttMarker.h:53
@ kOctagonCross
Definition TAttMarker.h:61
@ kFullCircle
Definition TAttMarker.h:55
@ kDot
Definition TAttMarker.h:53
@ kOpenCross
Definition TAttMarker.h:57
@ kFourSquaresX
Definition TAttMarker.h:65
@ kOpenCircle
Definition TAttMarker.h:56
@ kFullCross
Definition TAttMarker.h:59
@ kOpenStar
Definition TAttMarker.h:58
@ kFullDiamond
Definition TAttMarker.h:59
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
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
#define gROOT
Definition TROOT.h:406
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
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 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
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.
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.
"Delegating" part of TGLPadPainter.
void DrawText(Double_t x, Double_t y, const char *text, ETextMode mode) override
Draw text.
void SetLineColor(Color_t lcolor) override
Delegate to gVirtualX.
void DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height, Int_t dstX, Int_t dstY, Bool_t enableBlending) override
Float_t GetTextSize() const override
Delegate to gVirtualX.
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
Float_t GetTextAngle() const override
Delegate to gVirtualX.
void DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) override
Draw line segment in NDC coordinates.
Style_t GetLineStyle() const override
Delegate to gVirtualX.
Color_t GetTextColor() const override
Delegate to gVirtualX.
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 SetFillColor(Color_t fcolor) override
Delegate to gVirtualX.
void SetTextSizePixels(Int_t npixels) override
Delegate to gVirtualX.
void SetTextFont(Font_t tfont) override
Delegate to gVirtualX.
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 InvalidateCS() override
When TPad::Range for gPad is called, projection must be changed in OpenGL.
void ClearDrawable() override
Not required at the moment.
Color_t GetLineColor() const override
Delegate to gVirtualX.
void DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v) override
Poly line in NDC.
void DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) override
Draw poly-line in user coordinates.
void SetTextAlign(Short_t align) override
Delegate to gVirtualX.
Rgl::Pad::GLLimits fLimits
void SetOpacity(Int_t percent) override
Delegate to gVirtualX.
void SetTextAngle(Float_t tangle) override
Delegate to gVirtualX.
void DrawTextNDC(Double_t x, Double_t y, const char *text, ETextMode mode) override
Draw text in NDC.
void SetTextColor(Color_t tcolor) override
Delegate to gVirtualX.
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 SetLineWidth(Width_t lwidth) override
Delegate to gVirtualX.
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 SetTextSize(Float_t tsize) override
Delegate to gVirtualX.
void DrawFillArea(Int_t n, const Double_t *x, const Double_t *y) override
Draw tesselated polygon (probably, outline only).
Short_t GetTextAlign() const override
Delegate to gVirtualX.
Style_t GetFillStyle() const override
Delegate to gVirtualX.
void SetFillStyle(Style_t fstyle) override
Delegate to gVirtualX.
Font_t GetTextFont() const override
Delegate to gVirtualX.
void RestoreProjectionMatrix() const
Restore the projection matrix.
void SetLineStyle(Style_t lstyle) override
Delegate to gVirtualX.
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.
Width_t GetLineWidth() const override
Delegate to gVirtualX.
void DrawTesselation(Int_t n, const Double_t *x, const Double_t *y)
Color_t GetFillColor() const override
Delegate to gVirtualX.
Int_t CreateDrawable(UInt_t w, UInt_t h) override
Not required at the moment.
Bool_t IsTransparent() const override
Delegate to gVirtualX.
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 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:1582
static Float_t GetScreenScalingFactor()
Returns scaling factor between screen points and GL viewport pixels.
Definition TGLUtil.cxx:1852
EImageFileTypes
Definition TImage.h:36
static TImage * Create()
Create an image.
Definition TImage.cxx:35
const Point & GetEnd() const
Get end.
const Point & GetStart() const
Get start.
The most important graphics class in the ROOT system.
Definition TPad.h:28
SCoord_t fX
Definition TPoint.h:35
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
virtual UInt_t GetWh() const =0
virtual UInt_t GetWw() const =0
virtual TCanvas * GetCanvas() const =0
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:3226
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:3206
Double_t ACos(Double_t)
Returns the principal value of the arc cosine of x, expressed in radians.
Definition TMath.h:632
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:662
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:594
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:588
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:72
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
constexpr Double_t TwoPi()
Definition TMath.h:44