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