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
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
54
55////////////////////////////////////////////////////////////////////////////////
56
58 : fIsHollowArea(kFALSE),
59 fLocked(kTRUE)
60{
61 fVp[0] = fVp[1] = fVp[2] = fVp[3] = 0;
62}
63
64
65////////////////////////////////////////////////////////////////////////////////
66///Delegate to gVirtualX.
67
69{
70 return gVirtualX->GetLineColor();
71}
72
73////////////////////////////////////////////////////////////////////////////////
74///Delegate to gVirtualX.
75
77{
78 return gVirtualX->GetLineStyle();
79}
80
81////////////////////////////////////////////////////////////////////////////////
82///Delegate to gVirtualX.
83
85{
86 return gVirtualX->GetLineWidth();
87}
88
89////////////////////////////////////////////////////////////////////////////////
90///Delegate to gVirtualX.
91
96
97////////////////////////////////////////////////////////////////////////////////
98///Delegate to gVirtualX.
99
101{
102 gVirtualX->SetLineStyle(lstyle);
103}
104
105////////////////////////////////////////////////////////////////////////////////
106///Delegate to gVirtualX.
107
109{
110 gVirtualX->SetLineWidth(lwidth);
111}
112
113////////////////////////////////////////////////////////////////////////////////
114///Delegate to gVirtualX.
115
117{
118 return gVirtualX->GetFillColor();
119}
120
121////////////////////////////////////////////////////////////////////////////////
122///Delegate to gVirtualX.
123
125{
126 return gVirtualX->GetFillStyle();
127}
128
129////////////////////////////////////////////////////////////////////////////////
130///Delegate to gVirtualX.
131///IsTransparent is implemented as inline function in TAttFill.
132
134{
135 return gVirtualX->IsTransparent();
136}
137
138////////////////////////////////////////////////////////////////////////////////
139///Delegate to gVirtualX.
140
142{
143 gVirtualX->SetFillColor(fcolor);
144}
145
146////////////////////////////////////////////////////////////////////////////////
147///Delegate to gVirtualX.
148
150{
151 gVirtualX->SetFillStyle(fstyle);
152}
153
154////////////////////////////////////////////////////////////////////////////////
155///Delegate to gVirtualX.
156
158{
159 gVirtualX->SetOpacity(percent);
160}
161
162////////////////////////////////////////////////////////////////////////////////
163///Delegate to gVirtualX.
164
166{
167 return gVirtualX->GetTextAlign();
168}
169
170////////////////////////////////////////////////////////////////////////////////
171///Delegate to gVirtualX.
172
174{
175 return gVirtualX->GetTextAngle();
176}
177
178////////////////////////////////////////////////////////////////////////////////
179///Delegate to gVirtualX.
180
182{
183 return gVirtualX->GetTextColor();
184}
185
186////////////////////////////////////////////////////////////////////////////////
187///Delegate to gVirtualX.
188
190{
191 return gVirtualX->GetTextFont();
192}
193
194////////////////////////////////////////////////////////////////////////////////
195///Delegate to gVirtualX.
196
198{
199 return gVirtualX->GetTextSize();
200}
201
202////////////////////////////////////////////////////////////////////////////////
203///Delegate to gVirtualX.
204
206{
207 return gVirtualX->GetTextMagnitude();
208}
209
210////////////////////////////////////////////////////////////////////////////////
211///Delegate to gVirtualX.
212
214{
215 gVirtualX->SetTextAlign(align);
216}
217
218////////////////////////////////////////////////////////////////////////////////
219///Delegate to gVirtualX.
220
222{
223 gVirtualX->SetTextAngle(tangle);
224}
225
226////////////////////////////////////////////////////////////////////////////////
227///Delegate to gVirtualX.
228
230{
231 gVirtualX->SetTextColor(tcolor);
232}
233
234////////////////////////////////////////////////////////////////////////////////
235///Delegate to gVirtualX.
236
238{
239 gVirtualX->SetTextFont(tfont);
240}
241
242////////////////////////////////////////////////////////////////////////////////
243///Delegate to gVirtualX.
244
246{
247 gVirtualX->SetTextSize(tsize);
248}
249
250////////////////////////////////////////////////////////////////////////////////
251///Delegate to gVirtualX.
252
254{
255 gVirtualX->SetTextSizePixels(npixels);
256}
257
258/*
259"Pixmap" part of TGLPadPainter.
260*/
261
262////////////////////////////////////////////////////////////////////////////////
263///Not required at the moment.
264
266{
267 return 0;
268}
269
270////////////////////////////////////////////////////////////////////////////////
271///Not required at the moment.
272
276
277////////////////////////////////////////////////////////////////////////////////
278///Not required at the moment.
279
280void TGLPadPainter::CopyDrawable(Int_t /*device*/, Int_t /*px*/, Int_t /*py*/)
281{
282}
283
284////////////////////////////////////////////////////////////////////////////////
285///Not required at the moment.
286
288{
289}
290
291////////////////////////////////////////////////////////////////////////////////
292///For gVirtualX this means select pixmap (or window)
293///and all subsequent drawings will go into
294///this pixmap. For OpenGL this means the change of
295///coordinate system and viewport.
296
298{
299 if (fLocked)
300 return;
301
302 if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
303 Int_t px = 0, py = 0;
304
305 pad->XYtoAbsPixel(pad->GetX1(), pad->GetY1(), px, py);
306
307 py = gPad->GetWh() - py;
308 //
311
312 glViewport(GLint(px * scale), GLint(py * scale),
313 GLsizei(gPad->GetWw() * pad->GetAbsWNDC() * scale),
314 GLsizei(gPad->GetWh() * pad->GetAbsHNDC() * scale));
315
318 glOrtho(pad->GetX1(), pad->GetX2(), pad->GetY1(), pad->GetY2(), -10., 10.);
319
322 glTranslated(0., 0., -1.);
323 } else {
324 ::Error("TGLPadPainter::SelectDrawable",
325 "function was called not from TPad or TCanvas code\n");
326 throw std::runtime_error("");
327 }
328}
329
330////////////////////////////////////////////////////////////////////////////////
331///Init gl-pad painter:
332///1. 2D painter does not use depth test, should not modify
333/// depth-buffer content (except initial cleanup).
334///2. Disable cull face.
335///3. Disable lighting.
336///4. Set viewport (to the whole canvas area).
337///5. Set camera.
338///6. Unlock painter.
339
341{
345
346 //Clear the buffer
347 glViewport(0, 0, GLsizei(gPad->GetWw()), GLsizei(gPad->GetWh()));
348
350 glClearColor(1.,1.,1.,1.);
353
356
357 glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
358
361 glTranslated(0., 0., -1.);
362
363 fLocked = kFALSE;
364}
365
366////////////////////////////////////////////////////////////////////////////////
367///When TPad::Range for gPad is called, projection
368///must be changed in OpenGL.
369
371{
372 if (fLocked) return;
373
376
377 glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
378
380}
381
382////////////////////////////////////////////////////////////////////////////////
383///Locked state of painter means, that
384///GL context can be invalid, so no GL calls
385///can be executed.
386
388{
389 if (fLocked) return;
390
391 glFinish();
392 fLocked = kTRUE;
393}
394
395/*
3962D primitives.
397*/
398
400
401////////////////////////////////////////////////////////////////////////////////
402///Draw line segment.
403
405{
406 if (fLocked) {
407 //GL pad painter can be called in non-standard situation:
408 //not from TPad::Paint, but
409 //from TView3D::ExecuteRotateView. This means in fact,
410 //that TView3D wants to draw itself in a XOR mode, via
411 //gVirtualX.
412 if (gVirtualX->GetDrawMode() == TVirtualX::kInvert) {
413 gVirtualX->DrawLine(gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1),
414 gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2));
415 }
416
417 return;
418 }
419
421
422 glBegin(GL_LINES);
423 glVertex2d(x1, y1);
424 glVertex2d(x2, y2);
425 glEnd();
426
427 if (gVirtualX->GetLineWidth() > lineWidthTS) {
428 Double_t pointSize = gVirtualX->GetLineWidth();
434 glBegin(GL_POINTS);
435
436 glVertex2d(x1, y1);
437 glVertex2d(x2, y2);
438
439 glEnd();
440 glPointSize(1.f);
441 }
442
443}
444
445////////////////////////////////////////////////////////////////////////////////
446///Draw line segment in NDC coordinates.
447
449{
450 if (fLocked) return;
451
453 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
454 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
455
456 glBegin(GL_LINES);
457 glVertex2d(gPad->GetX1() + u1 * xRange, gPad->GetY1() + v1 * yRange);
458 glVertex2d(gPad->GetX1() + u2 * xRange, gPad->GetY1() + v2 * yRange);
459 glEnd();
460}
461
462////////////////////////////////////////////////////////////////////////////////
463///Draw filled or hollow box.
464
466{
467 if (fLocked) return;
468
469 if (IsGradientFill(gVirtualX->GetFillColor())) {
470 Double_t xs[] = {x1, x2, x2, x1};
471 Double_t ys[] = {y1, y1, y2, y2};
473 return;
474 }
475
476 if (mode == kHollow) {
478 //
480 glRectd(x1, y1, x2, y2);
482 glLineWidth(1.f);
483 } else {
484 const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);//Set filling parameters.
485 glRectd(x1, y1, x2, y2);
486 }
487}
488
489////////////////////////////////////////////////////////////////////////////////
490///Draw tesselated polygon (probably, outline only).
491
493{
494 assert(x != nullptr && "DrawFillArea, parameter 'x' is null");
495 assert(y != nullptr && "DrawFillArea, parameter 'y' is null");
496
497 if (fLocked)
498 return;
499
500 if (n < 3) {
501 ::Error("TGLPadPainter::DrawFillArea",
502 "invalid number of points in a polygon");
503 return;
504 }
505
506 if (IsGradientFill(gVirtualX->GetFillColor()))
507 return DrawPolygonWithGradient(n, x, y);
508
509 if (!gVirtualX->GetFillStyle()) {
511 return DrawPolyLine(n, x, y);
512 }
513
515 DrawTesselation(n, x, y);
516}
517
518////////////////////////////////////////////////////////////////////////////////
519///Draw tesselated polygon (never called, probably, since TPad::PaintFillArea for floats
520///is deprecated).
521
523{
524 if (fLocked) return;
525
526 if (!gVirtualX->GetFillStyle()) {
528 return DrawPolyLine(n, x, y);
529 }
530
531 fVs.resize(n * 3);
532
533 for (Int_t i = 0; i < n; ++i) {
534 fVs[i * 3] = x[i];
535 fVs[i * 3 + 1] = y[i];
536 }
537
539
543
544 for (Int_t i = 0; i < n; ++i)
545 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
546
547
548 gluEndPolygon(t);
549}
550
551////////////////////////////////////////////////////////////////////////////////
552///Draw poly-line in user coordinates.
553
555{
556 if (fLocked) return;
557
559
560 glBegin(GL_LINE_STRIP);
561
562 for (Int_t i = 0; i < n; ++i)
563 glVertex2d(x[i], y[i]);
564
565 if (fIsHollowArea) {
566 glVertex2d(x[0], y[0]);
568 }
569 glEnd();
570
571 if (gVirtualX->GetLineWidth() > lineWidthTS) {
572 Double_t pointSize = gVirtualX->GetLineWidth();
578 glBegin(GL_POINTS);
579
580 for (Int_t i = 0; i < n; ++i)
581 glVertex2d(x[i], y[i]);
582
583 glEnd();
584 glPointSize(1.f);
585 }
586}
587
588////////////////////////////////////////////////////////////////////////////////
589///Never called?
590
592{
593 if (fLocked) return;
594
596
597 glBegin(GL_LINE_STRIP);
598
599 for (Int_t i = 0; i < n; ++i)
600 glVertex2f(x[i], y[i]);
601
602 if (fIsHollowArea) {
603 glVertex2f(x[0], y[0]);
605 }
606
607 glEnd();
608}
609
610////////////////////////////////////////////////////////////////////////////////
611///Poly line in NDC.
612
614{
615 if (fLocked) return;
616
618 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
619 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
620 const Double_t x1 = gPad->GetX1(), y1 = gPad->GetY1();
621
622 glBegin(GL_LINE_STRIP);
623
624 for (Int_t i = 0; i < n; ++i)
625 glVertex2d(x1 + u[i] * xRange, y1 + v[i] * yRange);
626
627 glEnd();
628}
629
630namespace {
631
632//Aux. function.
633template<class ValueType>
634void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector<TPoint> & dst);
635
636}
637
638////////////////////////////////////////////////////////////////////////////////
639///Poly-marker.
640
642{
643 if (fLocked) return;
644
647}
648
649////////////////////////////////////////////////////////////////////////////////
650///Poly-marker.
651
653{
654 if (fLocked) return;
655
658}
659
660////////////////////////////////////////////////////////////////////////////////
661///Poly-marker.
662
664{
665 if (fLocked) return;
666
669 //
670 glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
671 //
673 //
675
676 Float_t rgba[4] = {};
677 Rgl::Pad::ExtractRGBA(gVirtualX->GetMarkerColor(), rgba);
680
681 const Width_t w = TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())));
683
684 const TPoint *xy = &fPoly[0];
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:
728 break;
729 case kOpenTriangleUp:
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
804 glLineWidth(1.f);
805}
806
807////////////////////////////////////////////////////////////////////////////////
808
809template<class Char>
811{
813
815 //
816 glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
817 //
819
820 Float_t rgba[4] = {};
821 Rgl::Pad::ExtractRGBA(gVirtualX->GetTextColor(), rgba);
823
824 //10 is the first valid font index.
825 //20 is FreeSerifBold, as in TTF.cxx and in TGLFontManager.cxx.
826 //shift - is the shift to access "extended" fonts.
828
829 Int_t fontIndex = TMath::Max(Short_t(10), gVirtualX->GetTextFont());
830 if (fontIndex / 10 + shift > TGLFontManager::GetFontFileArray()->GetEntries())
831 fontIndex = 20 + shift * 10;
832 else
833 fontIndex += shift * 10;
834
835 fFM.RegisterFont(TMath::Max(Int_t(gVirtualX->GetTextSize()) - 1, 10),//kTexture does not work if size < 10.
838 fF.PreRender();
839
840 const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
841 fF.Render(text, gPad->XtoPixel(x), padH - gPad->YtoPixel(y), GetTextAngle(), GetTextMagnitude());
842
843 fF.PostRender();
845
847}
848
849////////////////////////////////////////////////////////////////////////////////
850///Draw text. This operation is especially
851///dangerous if in locked state -
852///ftgl will assert on zero texture size
853///(which is result of bad GL context).
854
856{
857 if (fLocked) return;
858
859 if (!gVirtualX->GetTextSize())
860 return;
861
863}
864
865////////////////////////////////////////////////////////////////////////////////
866///Draw text. This operation is especially
867///dangerous if in locked state -
868///ftgl will assert on zero texture size
869///(which is result of bad GL context).
870
872{
873 if (fLocked) return;
874
875 if (!gVirtualX->GetTextSize())
876 return;
877
879}
880
881////////////////////////////////////////////////////////////////////////////////
882///Draw text in NDC. This operation is especially
883///dangerous if in locked state -
884///ftgl will assert on zero texture size
885///(which is result of bad GL context).
886
888{
889 if (fLocked) return;
890
891 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
892 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
893 DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
894}
895
896////////////////////////////////////////////////////////////////////////////////
897///Draw text in NDC. This operation is especially
898///dangerous if in locked state -
899///ftgl will assert on zero texture size
900///(which is result of bad GL context).
901
903{
904 if (fLocked) return;
905
906 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
907 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
908 DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
909}
910
911////////////////////////////////////////////////////////////////////////////////
912///Save the projection matrix.
913///Attention! GL_PROJECTION will become the current matrix
914///after this call!
915
921
922////////////////////////////////////////////////////////////////////////////////
923///Restore the projection matrix.
924///Attention! GL_PROJECTION will become the current matrix
925///after this call!
926
932
933////////////////////////////////////////////////////////////////////////////////
934///Save the modelview matrix.
935///Attention! GL_MODELVIEW will become the current matrix
936///after this call!
937
943
944////////////////////////////////////////////////////////////////////////////////
945///Restore the modelview matrix.
946///Attention! GL_MODELVIEW will become the current matrix
947///after this call!
948
954
955////////////////////////////////////////////////////////////////////////////////
956///Extract and save the current viewport.
957
962
963////////////////////////////////////////////////////////////////////////////////
964///Restore the saved viewport.
965
967{
968 glViewport(fVp[0], fVp[1], fVp[2], fVp[3]);
969}
970
971////////////////////////////////////////////////////////////////////////////////
972/// Using TImage save frame-buffer contents as a picture.
973
974void TGLPadPainter::SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const
975{
976 TVirtualPad *canvas = (TVirtualPad *)pad->GetCanvas();
977 if (!canvas)
978 return;
979
980 gROOT->ProcessLine(Form("((TCanvas *)0x%zx)->Flush();", (size_t)canvas));
981
982 std::vector<unsigned> buff(canvas->GetWw() * canvas->GetWh());
985 //In case GL_BGRA is not in gl.h (old windows' gl) - comment/uncomment lines.
986 //glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_BGRA, GL_UNSIGNED_BYTE, (char *)&buff[0]);
987 glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_RGBA, GL_UNSIGNED_BYTE, (char *)&buff[0]);
988
989 std::unique_ptr<TImage> image(TImage::Create());
990 if (!image.get()) {
991 ::Error("TGLPadPainter::SaveImage", "TImage creation failed");
992 return;
993 }
994
995 image->DrawRectangle(0, 0, canvas->GetWw(), canvas->GetWh());
996 UInt_t *argb = image->GetArgbArray();
997
998 if (!argb) {
999 ::Error("TGLPadPainter::SaveImage", "null argb array in TImage object");
1000 return;
1001 }
1002
1003 const Int_t nLines = canvas->GetWh();
1004 const Int_t nPixels = canvas->GetWw();
1005
1006 for (Int_t i = 0; i < nLines; ++i) {
1007 Int_t base = (nLines - 1 - i) * nPixels;
1008 for (Int_t j = 0; j < nPixels; ++j, ++base) {
1009 //Uncomment/comment if you don't have GL_BGRA.
1010
1011 const UInt_t pix = buff[base];
1012 const UInt_t bgra = ((pix & 0xff) << 16) | (pix & 0xff00) |
1013 ((pix & 0xff0000) >> 16) | (pix & 0xff000000);
1014
1015 //argb[i * nPixels + j] = buff[base];
1016 argb[i * nPixels + j] = bgra;
1017 }
1018 }
1019
1020 image->WriteImage(fileName, (TImage::EImageFileTypes)type);
1021}
1022
1023////////////////////////////////////////////////////////////////////////////////
1024
1027{
1028 if (fLocked)
1029 return;
1030
1031 if (!pixelData) {
1032 //I'd prefer an assert.
1033 ::Error("TGLPadPainter::DrawPixels", "pixel data is null");
1034 return;
1035 }
1036
1037 if (std::numeric_limits<UInt_t>::digits >= 32) {
1038 //TASImage uses bit 31 as ...
1039 //alpha channel flag! FUUUUUUUUUUUUU ..... !!!
1040 CLRBIT(width, 31);
1041 CLRBIT(height, 31);
1042 }
1043
1044 if (!width) {
1045 //Assert is better.
1046 ::Error("TGLPadPainter::DrawPixels", "invalid width");
1047 return;
1048 }
1049
1050 if (!height) {
1051 //Assert is better.
1052 ::Error("TGLPadPainter::DrawPixels", "invalid height");
1053 return;
1054 }
1055
1056 if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
1057 //TASImage passes pixel coordinates in pad's pixmap coordinate space.
1058 //While glRasterPosX said to work with 'window' coordinates,
1059 //that's a lie :) it does not :)
1060
1061 const Double_t rasterX = Double_t(dstX) / (pad->GetAbsWNDC() * pad->GetWw()) *
1062 (pad->GetX2() - pad->GetX1()) + pad->GetX1();
1063
1064 const Double_t yRange = pad->GetY2() - pad->GetY1();
1065 const Double_t rasterY = yRange - Double_t(dstY + height) / (pad->GetAbsHNDC() * pad->GetWh()) * yRange +
1066 pad->GetY1();
1067
1068 GLdouble oldPos[4] = {};
1069 //Save the previous raster pos.
1071
1073 //Stupid asimage provides us upside-down image.
1074 std::vector<unsigned char> upsideDownImage(4 * width * height);
1075 const unsigned char *srcLine = pixelData + 4 * width * (height - 1);
1076 unsigned char *dstLine = &upsideDownImage[0];
1077 for (UInt_t i = 0; i < height; ++i, srcLine -= 4 * width, dstLine += 4 * width)
1078 std::copy(srcLine, srcLine + 4 * width, dstLine);
1079
1080 if (enableBlending) {
1083 }
1084
1086
1087 if (enableBlending)
1089
1090 //Restore raster pos.
1091 glRasterPos2d(oldPos[0], oldPos[1]);
1092 } else
1093 ::Error("TGLPadPainter::DrawPixels", "no pad found to draw");
1094}
1095
1096//Aux. functions - gradient and solid fill of arbitrary area.
1097
1098////////////////////////////////////////////////////////////////////////////////
1099///At the moment I assume both linear and radial gradients will work the same way -
1100///using a stencil buffer and some big rectangle(s) to fill with a gradient.
1101///Thus I have a 'common' part - the part responsible for a stencil test.
1102
1104{
1105 assert(n > 2 && "DrawPolygonWithGradient, invalid number of points");
1106 assert(x != nullptr && "DrawPolygonWithGradient, parameter 'x' is null");
1107 assert(y != nullptr && "DrawPolygonWithGradient, parameter 'y' is null");
1108
1109 assert(dynamic_cast<TColorGradient *>(gROOT->GetColor(gVirtualX->GetFillColor())) != nullptr &&
1110 "DrawPolygonWithGradient, the current fill color is not a gradient fill");
1111 const TColorGradient * const grad =
1112 dynamic_cast<TColorGradient *>(gROOT->GetColor(gVirtualX->GetFillColor()));
1113
1114 if (fLocked)
1115 return;
1116
1117 //Now, some magic!
1119
1120 //TODO: check that the state is restored back correctly after
1121 // we done with a gradient.
1122 //TODO: make sure that we have glDepthMask set to false in general!
1124
1125 glStencilFunc(GL_NEVER, 1, 0xFF);
1126 glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);// draw 1s on test fail (always)
1127 //Draw stencil pattern
1128 glStencilMask(0xFF);
1130
1131 //Draw our polygon into the stencil buffer:
1132 DrawTesselation(n, x, y);
1133
1135 glStencilMask(0x00);
1136 //Draw where stencil's value is 0
1137 glStencilFunc(GL_EQUAL, 0, 0xFF);
1138 //Draw only where stencil's value is 1
1139 glStencilFunc(GL_EQUAL, 1, 0xFF);
1140
1141 //At the moment radial gradient is derived from linear - it was convenient
1142 //at some point, but in fact it was a bad idea. And now I have to
1143 //first check radial gradient.
1144 //TODO: TRadialGradient must inherit TColorGradient directly.
1145 const TRadialGradient * const rGrad = dynamic_cast<const TRadialGradient *>(grad);
1146 if (rGrad)
1147 DrawGradient(rGrad, n, x, y);
1148 else {
1149 const TLinearGradient * const lGrad = dynamic_cast<const TLinearGradient *>(grad);
1150 assert(lGrad != nullptr && "DrawPolygonWithGradient, unknown gradient type");
1151 DrawGradient(lGrad, n, x, y);
1152 }
1153}
1154
1155////////////////////////////////////////////////////////////////////////////////
1156
1158 const Double_t *xs, const Double_t *ys)
1159{
1160 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1161 assert(nPoints > 2 && "DrawGradient, invalid number of points");
1162 assert(xs != nullptr && "DrawGradient, parameter 'xs' is null");
1163 assert(ys != nullptr && "DrawGradient, parameter 'ys' is null");
1164
1166 ::Warning("TGLPadPainter::DrawGradient",
1167 "extended radial gradient is not supported");//yet?
1168 return;
1169 }
1170
1171 //TODO: check the polygon's bbox!
1172 const auto &bbox = Rgl::Pad::FindBoundingRect(nPoints, xs, ys);
1173 //
1174 auto center = grad->GetCenter();
1175 auto radius = grad->GetRadius();
1176 //Adjust the center and radius depending on coordinate mode.
1178 radius *= TMath::Max(bbox.fWidth, bbox.fHeight);
1179 center.fX = bbox.fWidth * center.fX + bbox.fXMin;
1180 center.fY = bbox.fHeight * center.fY + bbox.fYMin;
1181 } else {
1182 const auto w = gPad->GetX2() - gPad->GetX1();
1183 const auto h = gPad->GetY2() - gPad->GetY1();
1184
1185 radius *= TMath::Max(w, h);
1186 center.fX *= w;
1187 center.fY *= h;
1188 }
1189 //Now for the gradient fill we switch into pixel coordinates:
1190 const auto pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1191 const auto pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1192 //
1195 //A new ortho projection:
1198 //
1199 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1200 //
1202 center.fX = gPad->XtoPixel(center.fX);
1203 center.fY = pixelH - gPad->YtoPixel(center.fY);
1204
1205 Double_t maxR = 0.;
1206 {
1207 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1208 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1209 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1210 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1211 //Get the longest distance from the center to the bounding box vertices
1212 //(this will be the maximum possible radius):
1213 const Double_t maxDistX = TMath::Max(TMath::Abs(center.fX - xMin),
1214 TMath::Abs(center.fX - xMax));
1215 const Double_t maxDistY = TMath::Max(TMath::Abs(center.fY - yMin),
1216 TMath::Abs(center.fY - yMax));
1218 }
1219
1220 //If gradient 'stops inside the polygon', we use
1221 //the solid fill for the area outside of radial gradient:
1222 const Bool_t solidFillAfter = maxR > radius;
1223 //We emulate a radial gradient using triangles and linear gradient:
1224 //TODO: Can be something smarter? (btw even 100 seems to be enough)
1225 const UInt_t nSlices = 500;
1226
1227 const auto nColors = grad->GetNumberOfSteps();
1228 //+1 - the strip from the last color's position to radius,
1229 //and (probably) + 1 for solidFillAfter.
1230 const auto nCircles = nColors + 1 + solidFillAfter;
1231
1232 //TODO: can locations be outside of [0., 1.] ???
1233 //at the moment I assume the answer is NO, NEVER.
1234 const auto locations = grad->GetColorPositions();
1235 // * 2 below == x,y
1236 std::vector<Double_t> circles(nSlices * nCircles * 2);
1237 const Double_t angle = TMath::TwoPi() / nSlices;
1238
1239 //"Main" circles (for colors at locations[i]).
1240 for (UInt_t i = 0; i < nColors; ++i) {
1241 const auto circle = &circles[i * nSlices * 2];
1242 //TODO: either check locations here or somewhere else.
1243 const auto r = radius * locations[i];
1244 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1245 circle[j] = center.fX + r * TMath::Cos(angle * j);
1246 circle[j + 1] = center.fY + r * TMath::Sin(angle * j);
1247 }
1248 //The "closing" vertices:
1249 circle[(nSlices - 1) * 2] = circle[0];
1250 circle[(nSlices - 1) * 2 + 1] = circle[1];
1251 }
1252
1253 {
1254 //The strip between lastPos and radius:
1255 const auto circle = &circles[nColors * nSlices * 2];
1256 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1257 circle[j] = center.fX + radius * TMath::Cos(angle * j);
1258 circle[j + 1] = center.fY + radius * TMath::Sin(angle * j);
1259 }
1260
1261 circle[(nSlices - 1) * 2] = circle[0];
1262 circle[(nSlices - 1) * 2 + 1] = circle[1];
1263 }
1264
1265 if (solidFillAfter) {
1266 //The strip after the radius:
1267 const auto circle = &circles[(nCircles - 1) * nSlices * 2];
1268 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1269 circle[j] = center.fX + maxR * TMath::Cos(angle * j);
1270 circle[j + 1] = center.fY + maxR * TMath::Sin(angle * j);
1271 }
1272
1273 circle[(nSlices - 1) * 2] = circle[0];
1274 circle[(nSlices - 1) * 2 + 1] = circle[1];
1275 }
1276
1277 //Now we draw:
1278 //1) triangle fan in the center (from center to the locations[1],
1279 // with a solid fill).
1280 //2) quad strips for colors.
1281 //3) additional quad strip from the lastLocation to the radius
1282 //4) additional quad strip (if any) from the radius to maxR.
1283
1284 //RGBA values:
1285 const auto rgba = grad->GetColors();
1286
1288 //TODO?
1290
1291 //Probably a degenerated case. Maybe not.
1294 glVertex2d(center.fX, center.fY);
1295
1296 for (UInt_t i = 0, e = nSlices * 2; i < e; i += 2)
1297 glVertex2dv(&circles[i]);
1298
1299 glEnd();
1300
1301 //No auto for circles, explicit types to have const Double_t * const, not Duble_t * const.
1302 for (UInt_t i = 0; i < nColors - 1; ++i) {
1303 const Double_t * const inner = &circles[i * nSlices * 2];
1304 const auto innerRGBA = rgba + i * 4;
1305 const auto outerRGBA = rgba + (i + 1) * 4;
1306 const Double_t * const outer = &circles[(i + 1) * nSlices * 2];
1307
1309 }
1310
1311 //Probably degenerated strip.
1312 {
1314 const Double_t * const inner = &circles[nSlices * (nColors - 1) * 2];
1315 const auto solidRGBA = rgba + (nColors - 1) * 4;
1316 const Double_t * const outer = &circles[nSlices * nColors * 2];
1317
1319 }
1320
1321 if (solidFillAfter) {
1323 const Double_t * const inner = &circles[nSlices * nColors * 2];
1324 const auto solidRGBA = rgba + (nColors - 1) * 4;
1325 const Double_t * const outer = &circles[nSlices * (nColors + 1) * 2];
1326
1328 }
1329
1332}
1333
1334////////////////////////////////////////////////////////////////////////////////
1335
1337 const Double_t *x, const Double_t *y)
1338{
1339 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1340 assert(n > 2 && "DrawGradient, invalid number of points");
1341 assert(x != nullptr && "DrawGradient, parameter 'x' is null");
1342 assert(y != nullptr && "DrawGradient, parameter 'y' is null");
1343
1344 //Now we fill the whole scene with one big rectangle
1345 //(group of rectangles) with a gradient fill using
1346 //stencil test.
1347
1348 //Find a bounding rect.
1349 const auto &bbox = Rgl::Pad::FindBoundingRect(n, x, y);
1350 //TODO: check the bbox??
1351
1352 //For the gradient fill we switch into the
1353 //pixel coordinates.
1356
1357 //A new ortho projection:
1360
1361 const Double_t pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1362 const Double_t pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1363 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1364
1365 //A new modelview:
1368 //
1369 TColorGradient::Point start = grad->GetStart();
1370 TColorGradient::Point end = grad->GetEnd();
1371
1372 //Change gradient coordinates from 'NDC' to pad coords:
1374 {
1375 const Double_t w = gPad->GetX2() - gPad->GetX1();
1376 const Double_t h = gPad->GetY2() - gPad->GetY1();
1377
1378 start.fX = start.fX * w;
1379 start.fY = start.fY * h;
1380 end.fX = end.fX * w;
1381 end.fY = end.fY * h;
1382 } else {
1383 start.fX = start.fX * bbox.fWidth + bbox.fXMin;
1384 start.fY = start.fY * bbox.fHeight + bbox.fYMin;
1385 end.fX = end.fX * bbox.fWidth + bbox.fXMin;
1386 end.fY = end.fY * bbox.fHeight + bbox.fYMin;
1387 }
1388
1389 //TODO: with a radial fill we'll have to extract the code
1390 // below into the separate function/and have additional function
1391 // for a radial gradient.
1392 //Now from pad to pixels:
1393 start.fX = gPad->XtoPixel(start.fX);
1394 start.fY = pixelH - gPad->YtoPixel(start.fY);
1395 end.fX = gPad->XtoPixel(end.fX);
1396 end.fY = pixelH - gPad->YtoPixel(end.fY);
1397 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1398 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1399 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1400 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1401 //
1402
1403 //TODO: check all calculations!
1404
1405 //Get the longest distance from the start point to the bounding box vertices:
1406 const Double_t maxDistX = TMath::Max(TMath::Abs(start.fX - xMin), TMath::Abs(start.fX - xMax));
1407 const Double_t maxDistY = TMath::Max(TMath::Abs(start.fY - yMin), TMath::Abs(start.fY - yMax));
1408
1409 const Double_t startEndLength = TMath::Sqrt((end.fX - start.fX) * (end.fX - start.fX) +
1410 (end.fY - start.fY) * (end.fY - start.fY));
1413
1414 //Boxes with a gradients to emulate gradient fill with many colors:
1415 const Double_t * const colorPositions = grad->GetColorPositions();
1416 std::vector<Double_t> gradBoxes(grad->GetNumberOfSteps() + 2);
1417 gradBoxes[0] = start.fY - h;
1418 for (unsigned i = 1; i <= grad->GetNumberOfSteps(); ++i)
1419 gradBoxes[i] = startEndLength * colorPositions[i - 1] + start.fY;
1420
1421 gradBoxes[grad->GetNumberOfSteps() + 1] = start.fY + h;
1422
1423 //Rotation angle - gradient's axis:
1424 Double_t angle = TMath::ACos((startEndLength * (end.fY - start.fY)) /
1426 if (end.fX > start.fX)
1427 angle *= -1;
1428
1429 glTranslated(start.fX, start.fY, 0.);
1430 glRotated(angle, 0., 0., 1.);
1431 glTranslated(-start.fX, -start.fY, 0.);
1432 //
1433 const Double_t * const rgba = grad->GetColors();
1434
1435 const unsigned nEdges = gradBoxes.size();
1436 const unsigned nColors = grad->GetNumberOfSteps();
1437 const Double_t xLeft = start.fX - h, xRight = start.fX + h;
1438
1440 //TODO?
1442
1445 rgba + (nColors - 1) * 4, rgba + (nColors - 1) * 4);
1446
1447 for (unsigned i = 1; i < nEdges - 2; ++i)
1449 xRight, rgba + (i - 1) * 4, rgba + i * 4);
1450
1453}
1454
1455////////////////////////////////////////////////////////////////////////////////
1456
1458{
1459 assert(n > 2 && "DrawTesselation, invalid number of points");
1460 assert(x != nullptr && "DrawTesselation, parameter 'x' is null");
1461 assert(y != nullptr && "DrawTesselation, parameter 'y' is null");
1462
1463 //Data for a tesselator:
1464 fVs.resize(n * 3);
1465
1466 for (Int_t i = 0; i < n; ++i) {
1467 fVs[i * 3] = x[i];
1468 fVs[i * 3 + 1] = y[i];
1469 fVs[i * 3 + 2] = 0.;
1470 }
1471
1472 //TODO: A very primitive way to tesselate - check what
1473 //kind of polygons we can really have from TPad/TCanvas.
1475 gluBeginPolygon(t);
1477
1478 for (Int_t i = 0; i < n; ++i)
1479 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
1480
1481 gluEndPolygon(t);
1482}
1483
1484
1485//Aux. functions.
1486namespace {
1487
1488template<class ValueType>
1489void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector<TPoint> & dst)
1490{
1491 const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
1492
1493 dst.resize(n);
1494 for (Int_t i = 0; i < n; ++i) {
1495 dst[i].fX = gPad->XtoPixel(x[i]);
1496 dst[i].fY = padH - gPad->YtoPixel(y[i]);
1497 }
1498}
1499
1500}
1501
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
short Style_t
Style number (short)
Definition RtypesCore.h:96
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
short Width_t
Line width (short)
Definition RtypesCore.h:98
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Font_t
Font number (short)
Definition RtypesCore.h:95
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
#define CLRBIT(n, i)
Definition Rtypes.h:93
@ kOpenDoubleDiamond
Definition TAttMarker.h:66
@ kStar
Definition TAttMarker.h:56
@ kFullDotLarge
Definition TAttMarker.h:57
@ kFullDoubleDiamond
Definition TAttMarker.h:66
@ kOpenFourTrianglesX
Definition TAttMarker.h:65
@ kOpenSquare
Definition TAttMarker.h:59
@ kFullThreeTriangles
Definition TAttMarker.h:64
@ kOpenTriangleUp
Definition TAttMarker.h:60
@ kFourSquaresPlus
Definition TAttMarker.h:69
@ kFullDotSmall
Definition TAttMarker.h:57
@ kFullDotMedium
Definition TAttMarker.h:57
@ kOpenTriangleDown
Definition TAttMarker.h:61
@ kOpenThreeTriangles
Definition TAttMarker.h:63
@ kFullCrossX
Definition TAttMarker.h:68
@ kFullFourTrianglesX
Definition TAttMarker.h:65
@ kFullTriangleDown
Definition TAttMarker.h:59
@ kCircle
Definition TAttMarker.h:56
@ kOpenCrossX
Definition TAttMarker.h:68
@ kFullFourTrianglesPlus
Definition TAttMarker.h:67
@ kFullSquare
Definition TAttMarker.h:58
@ kOpenSquareDiagonal
Definition TAttMarker.h:63
@ kFullStar
Definition TAttMarker.h:61
@ kOpenDiamond
Definition TAttMarker.h:60
@ kFullTriangleUp
Definition TAttMarker.h:58
@ kOpenDiamondCross
Definition TAttMarker.h:62
@ kOpenFourTrianglesPlus
Definition TAttMarker.h:67
@ kMultiply
Definition TAttMarker.h:56
@ kPlus
Definition TAttMarker.h:56
@ kOctagonCross
Definition TAttMarker.h:64
@ kFullCircle
Definition TAttMarker.h:58
@ kDot
Definition TAttMarker.h:56
@ kOpenCross
Definition TAttMarker.h:60
@ kFourSquaresX
Definition TAttMarker.h:68
@ kOpenCircle
Definition TAttMarker.h:59
@ kFullCross
Definition TAttMarker.h:62
@ kOpenStar
Definition TAttMarker.h:61
@ kFullDiamond
Definition TAttMarker.h:62
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
const Double_t lineWidthTS
#define GL_BGRA
Definition TGLViewer.cxx:61
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pix
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint xy
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t width
Option_t Option_t TPoint TPoint percent
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint DrawText
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
#define gROOT
Definition TROOT.h:411
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2495
#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.
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:1573
static Float_t GetScreenScalingFactor()
Returns scaling factor between screen points and GL viewport pixels.
Definition TGLUtil.cxx:1843
EImageFileTypes
Definition TImage.h:36
static TImage * Create()
Create an image.
Definition TImage.cxx:34
const Point & GetEnd() const
Get end.
const Point & GetStart() const
Get start.
The most important graphics class in the ROOT system.
Definition TPad.h:28
Double_t GetRadius() const
Get radius.
const Point & GetCenter() const
Get center.
EGradientType GetGradientType() const
Get gradient type.
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
virtual UInt_t GetWh() const =0
virtual UInt_t GetWw() 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:3216
void DrawBoxWithGradientFill(Double_t y1, Double_t y2, Double_t x1, Double_t x2, const Double_t *rgba1, const Double_t *rgba2)
Definition TGLUtil.cxx:3196
Double_t ACos(Double_t)
Returns the principal value of the arc cosine of x, expressed in radians.
Definition TMath.h:643
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:251
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124
constexpr Double_t TwoPi()
Definition TMath.h:47