Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGLPadPainter.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Timur Pocheptsov 06/05/2009
3
4/*************************************************************************
5 * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <stdexcept>
13#include <cassert>
14#include <limits>
15#include <memory>
16#include <vector>
17
18#include "TAttMarker.h"
19#include "TVirtualX.h"
20#include "TError.h"
21#include "TImage.h"
22#include "TROOT.h"
23#include "TPad.h"
24#include "TCanvas.h"
25#include "TCanvasImp.h"
26#include "TImage.h"
27
28#include "TColorGradient.h"
29#include "TGLPadPainter.h"
30#include "TGLIncludes.h"
31#include "TGLUtil.h"
32#include "TMath.h"
33
34#include <glad/gl.h>
35
36namespace {
37
38////////////////////////////////////////////////////////////////////////////////
39///Not a bad idea to assert on gVirtualX != nullptr
40
41bool IsGradientFill(Color_t fillColorIndex)
42{
43 return dynamic_cast<TColorGradient *>(gROOT->GetColor(fillColorIndex));
44}
45
46}
47
48/** \class TGLPadPainter
49\ingroup opengl
50"Delegating" part of TGLPadPainter. Line/fill/etc. attributes can be
51set inside TPad, but not only there:
52many of them are set by base sub-objects of 2d primitives
53(2d primitives usually inherit TAttLine or TAttFill etc.). And these sub-objects
54call gVirtualX->SetLineWidth ... etc. So, if I save some attributes in my painter,
55it will be mess - at any moment I do not know, where to take line attribute - from
56gVirtualX or from my own member. So! All attributed, _ALL_ go to/from gVirtualX.
57*/
58
59
60////////////////////////////////////////////////////////////////////////////////
61
63 : fIsHollowArea(kFALSE),
64 fLocked(kTRUE)
65{
66 fVp[0] = fVp[1] = fVp[2] = fVp[3] = 0;
67 fWinContext = 0;
68}
69
70
71////////////////////////////////////////////////////////////////////////////////
72///Delegate to gVirtualX.
73
75{
76 // does not work this way
77 gVirtualX->SetOpacityW(fWinContext, percent);
78}
79
80////////////////////////////////////////////////////////////////////////////////
81///Delegate to gVirtualX.
82
84{
85 return gVirtualX->GetTextMagnitude();
86}
87
88////////////////////////////////////////////////////////////////////////////////
89/// Select pad where current painting will be performed
90
92{
93 // GL painter does not use proper id for sub-pads (see CreateDrawable)
94 // so one always use canvas ID to execute TVirtualX-specific commands
95 if (!fWinContext)
96 fWinContext = gVirtualX->GetWindowContext(pad->GetCanvasID());
97}
98
99////////////////////////////////////////////////////////////////////////////////
100/// Set fill attributes
101
103{
105
107
108 // TODO: dismiss in the future, gVirtualX attributes not needed in GL
109 if (fWinContext && gVirtualX)
110 gVirtualX->SetAttFill(fWinContext, att);
111}
112
113////////////////////////////////////////////////////////////////////////////////
114/// Set line attributes
115
117{
119
120 // TODO: dismiss in the future, gVirtualX attributes not needed in GL
121 if (fWinContext && gVirtualX)
122 gVirtualX->SetAttLine(fWinContext, att);
123}
124
125////////////////////////////////////////////////////////////////////////////////
126/// Set marker attributes
127
129{
131
132 // TODO: dismiss in the future, gVirtualX attributes not needed in GL
133 if (fWinContext && gVirtualX)
134 gVirtualX->SetAttMarker(fWinContext, att);
135}
136
137/*
138"Pixmap" part of TGLPadPainter.
139*/
140
141////////////////////////////////////////////////////////////////////////////////
142///Not required at the moment.
143
145{
146 // return gVirtualX->OpenPixmap(Int_t(w), Int_t(h));
147 return 0;
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Resize a gVirtualX Pixmap.
152
154{
155 return gVirtualX->ResizePixmap(device, w, h);
156}
157
158////////////////////////////////////////////////////////////////////////////////
159/// Do nothing, sub-pads not cleared in GL
160
164
165////////////////////////////////////////////////////////////////////////////////
166/// Clear specified window - calling gVirtualX->ClearWindowW
167
169{
170 auto ctxt = gVirtualX->GetWindowContext(device);
171 if (ctxt)
172 gVirtualX->ClearWindowW(ctxt);
173}
174
175////////////////////////////////////////////////////////////////////////////////
176/// Returns true when X11 backend is used
177
179{
180 return gVirtualX->InheritsFrom("TGX11");
181}
182
183////////////////////////////////////////////////////////////////////////////////
184/// Returns true when cocoa backend is used
185
187{
188 return gVirtualX->InheritsFrom("TGCocoa");
189}
190
191////////////////////////////////////////////////////////////////////////////////
192///Not required at the moment.
193
194void TGLPadPainter::CopyDrawable(Int_t /* device */, Int_t /* px */, Int_t /* py */)
195{
196 // gVirtualX->CopyPixmapW(fWinContext, device, px, py);
197}
198
199////////////////////////////////////////////////////////////////////////////////
200///Not required at the moment.
201
203{
204 // gVirtualX->SelectWindow(device);
205 // gVirtualX->ClosePixmap();
206 fWinContext = 0;
207}
208
209////////////////////////////////////////////////////////////////////////////////
210///For gVirtualX this means select pixmap (or window)
211///and all subsequent drawings will go into
212///this pixmap. For OpenGL this means the change of
213///coordinate system and viewport.
214
216{
217 auto pad = dynamic_cast<TPad *>(gPad);
218 if (!fWinContext && pad)
219 fWinContext = gVirtualX->GetWindowContext(pad->GetCanvasID());
220
221 if (fLocked)
222 return;
223
224 if (pad) {
225 // GL painter does not use proper id for sub-pads (see CreateDrawable)
226 // so one always use canvas ID to execute TVirtualX-specific commands
227 Int_t px = 0, py = 0;
228
229 pad->XYtoAbsPixel(pad->GetX1(), pad->GetY1(), px, py);
230
231 py = gPad->GetWh() - py;
232 //
235
236 glViewport(GLint(px * scale), GLint(py * scale),
237 GLsizei(gPad->GetWw() * pad->GetAbsWNDC() * scale),
238 GLsizei(gPad->GetWh() * pad->GetAbsHNDC() * scale));
239
240 glMatrixMode(GL_PROJECTION);
241 glLoadIdentity();
242 glOrtho(pad->GetX1(), pad->GetX2(), pad->GetY1(), pad->GetY2(), -10., 10.);
243
244 glMatrixMode(GL_MODELVIEW);
245 glLoadIdentity();
246 glTranslated(0., 0., -1.);
247 } else {
248 ::Error("TGLPadPainter::SelectDrawable",
249 "function was called not from TPad or TCanvas code\n");
250 throw std::runtime_error("");
251 }
252}
253
254////////////////////////////////////////////////////////////////////////////////
255/// Call low-level update of selected drawable, redirect to gVirtualX.
256
258{
259 if (fWinContext)
260 gVirtualX->UpdateWindowW(fWinContext, mode);
261}
262
263
264////////////////////////////////////////////////////////////////////////////////
265/// Set drawing mode for specified device
266
268{
269 auto ctxt = fWinContext;
270 if (device)
271 ctxt = gVirtualX->GetWindowContext(device);
272 if (ctxt)
273 gVirtualX->SetDrawModeW(ctxt, (TVirtualX::EDrawMode) mode);
274}
275
276////////////////////////////////////////////////////////////////////////////////
277///Init gl-pad painter:
278///1. 2D painter does not use depth test, should not modify
279/// depth-buffer content (except initial cleanup).
280///2. Disable cull face.
281///3. Disable lighting.
282///4. Set viewport (to the whole canvas area).
283///5. Set camera.
284///6. Unlock painter.
285
287{
288 static bool gl_init = false;
289 if (!gl_init) {
290 int version = gladLoaderLoadGL();
291 if (version == 0)
292 Warning("TGLPadPainter::InitPainter", "GL initalization failed.");
293 else if (gDebug > 0)
294 Info("TGLPadPainter::InitPainter", "GL initalization successful.");
295 gl_init = true;
296 }
297 glDisable(GL_DEPTH_TEST);
298 glDisable(GL_CULL_FACE);
299 glDisable(GL_LIGHTING);
300
301 //Clear the buffer
302 glViewport(0, 0, GLsizei(gPad->GetWw()), GLsizei(gPad->GetWh()));
303
304 glDepthMask(GL_TRUE);
305 glClearColor(1.,1.,1.,1.);
306 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
307 glDepthMask(GL_FALSE);
308
309 glMatrixMode(GL_PROJECTION);
310 glLoadIdentity();
311
312 glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
313
314 glMatrixMode(GL_MODELVIEW);
315 glLoadIdentity();
316 glTranslated(0., 0., -1.);
317
318 fLocked = kFALSE;
319}
320
321////////////////////////////////////////////////////////////////////////////////
322///When TPad::Range for gPad is called, projection
323///must be changed in OpenGL.
324
326{
327 if (fLocked) return;
328
329 glMatrixMode(GL_PROJECTION);
330 glLoadIdentity();
331
332 glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
333
334 glMatrixMode(GL_MODELVIEW);
335}
336
337////////////////////////////////////////////////////////////////////////////////
338///Locked state of painter means, that
339///GL context can be invalid, so no GL calls
340///can be executed.
341
343{
344 if (fLocked) return;
345
346 glFinish();
347 fLocked = kTRUE;
348}
349
350/*
3512D primitives.
352*/
353
355
356////////////////////////////////////////////////////////////////////////////////
357///Draw line segment.
358
360{
361 if (fLocked) {
362 //GL pad painter can be called in non-standard situation:
363 //not from TPad::Paint, but
364 //from TView3D::ExecuteRotateView. This means in fact,
365 //that TView3D wants to draw itself in a XOR mode, via
366 //gVirtualX.
367 // TODO: only here set line attributes to virtual x
368 if (IsInvertMode())
369 gVirtualX->DrawLineW(fWinContext,
370 gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1),
371 gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2));
372
373 return;
374 }
375
377
378 glBegin(GL_LINES);
379 glVertex2d(x1, y1);
380 glVertex2d(x2, y2);
381 glEnd();
382
384 Double_t pointSize = GetAttLine().GetLineWidth();
385 if (pointSize > fLimits.GetMaxPointSize())
386 pointSize = fLimits.GetMaxPointSize();
387 glPointSize((GLfloat)pointSize);
388 const TGLEnableGuard pointSmooth(GL_POINT_SMOOTH);
389 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
390 glBegin(GL_POINTS);
391
392 glVertex2d(x1, y1);
393 glVertex2d(x2, y2);
394
395 glEnd();
396 glPointSize(1.f);
397 }
398
399}
400
401////////////////////////////////////////////////////////////////////////////////
402///Draw line segment in NDC coordinates.
403
405{
406 if (fLocked) {
407 // this code used when crosshair cursor is drawn or interactive objects move
408 if (IsInvertMode())
409 gVirtualX->DrawLineW(fWinContext,
410 gPad->UtoAbsPixel(u1), gPad->VtoAbsPixel(v1),
411 gPad->UtoAbsPixel(u2), gPad->VtoAbsPixel(v2));
412 return;
413 }
414
416 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
417 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
418
419 glBegin(GL_LINES);
420 glVertex2d(gPad->GetX1() + u1 * xRange, gPad->GetY1() + v1 * yRange);
421 glVertex2d(gPad->GetX1() + u2 * xRange, gPad->GetY1() + v2 * yRange);
422 glEnd();
423}
424
425////////////////////////////////////////////////////////////////////////////////
426///Draw filled or hollow box.
427
429{
430 if (fLocked) {
431 //GL pad painter can be called in non-standard situation:
432 //not from TPad::Paint, but
433 //from TView3D::ExecuteRotateView. This means in fact,
434 //that TView3D wants to draw itself in a XOR mode, via
435 //gVirtualX.
436 // TODO: only here set line attributes to virtual x
437 if (IsInvertMode())
438 gVirtualX->DrawBoxW(fWinContext,
439 gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1),
440 gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2),
442 return;
443 }
444
445 if (IsGradientFill(fGlFillAtt.GetFillColor())) {
446 Double_t xs[] = {x1, x2, x2, x1};
447 Double_t ys[] = {y1, y1, y2, y2};
448 DrawPolygonWithGradient(4, xs, ys);
449 return;
450 }
451
452 if (mode == kHollow) {
454 glBegin(GL_LINE_LOOP);
455 glVertex2d(x1, y1);
456 glVertex2d(x2, y1);
457 glVertex2d(x2, y2);
458 glVertex2d(x1, y2);
459 glEnd();
460 } else {
461 const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE, &fGlFillAtt);//Set filling parameters.
462 glRectd(x1, y1, x2, y2);
463 }
464}
465
466////////////////////////////////////////////////////////////////////////////////
467///Draw tesselated polygon (probably, outline only).
468
470{
471 assert(x != nullptr && "DrawFillArea, parameter 'x' is null");
472 assert(y != nullptr && "DrawFillArea, parameter 'y' is null");
473
474 if (fLocked)
475 return;
476
477 if (n < 3) {
478 ::Error("TGLPadPainter::DrawFillArea",
479 "invalid number of points in a polygon");
480 return;
481 }
482
483 if (IsGradientFill(fGlFillAtt.GetFillColor()))
484 return DrawPolygonWithGradient(n, x, y);
485
486 if (fFullyTransparent) {
488 return DrawPolyLine(n, x, y);
489 }
490
491 const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE, &fGlFillAtt);
492 DrawTesselation(n, x, y);
493}
494
495////////////////////////////////////////////////////////////////////////////////
496///Draw tesselated polygon (never called, probably, since TPad::PaintFillArea for floats
497///is deprecated).
498
500{
501 if (fLocked) return;
502
503 if (fFullyTransparent) {
505 return DrawPolyLine(n, x, y);
506 }
507
508 fVs.resize(n * 3);
509
510 for (Int_t i = 0; i < n; ++i) {
511 fVs[i * 3] = x[i];
512 fVs[i * 3 + 1] = y[i];
513 }
514
515 const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE, &fGlFillAtt);
516
517 GLUtesselator *t = (GLUtesselator *)fTess.GetTess();
518 gluBeginPolygon(t);
519 gluNextContour(t, (GLenum)GLU_UNKNOWN);
520
521 for (Int_t i = 0; i < n; ++i)
522 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
523
524
525 gluEndPolygon(t);
526}
527
528////////////////////////////////////////////////////////////////////////////////
529///Draw poly-line in user coordinates.
530
531template<class ValueType>
532void TGLPadPainter::DrawPolyLineHelper(Int_t n, const ValueType *x, const ValueType *y)
533{
534 if (fLocked) {
535 if (IsInvertMode() && (n > 1)) {
536 std::vector<TPoint> xy(n);
537 for (Int_t i = 0; i < n; ++i) {
538 xy[i].fX = (SCoord_t) gPad->XtoAbsPixel(x[i]);
539 xy[i].fY = (SCoord_t) gPad->YtoAbsPixel(y[i]);
540 }
541 gVirtualX->DrawPolyLineW(fWinContext, xy.size(), xy.data());
542 }
543 return;
544 }
545
547
548 glBegin(GL_LINE_STRIP);
549
550 for (Int_t i = 0; i < n; ++i)
551 glVertex2d(x[i], y[i]);
552
553 if (fIsHollowArea) {
554 glVertex2d(x[0], y[0]);
556 }
557 glEnd();
558
560 Double_t pointSize = GetAttLine().GetLineWidth();
561 if (pointSize > fLimits.GetMaxPointSize())
562 pointSize = fLimits.GetMaxPointSize();
563 glPointSize((GLfloat)pointSize);
564 const TGLEnableGuard pointSmooth(GL_POINT_SMOOTH);
565 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
566 glBegin(GL_POINTS);
567
568 for (Int_t i = 0; i < n; ++i)
569 glVertex2d(x[i], y[i]);
570
571 glEnd();
572 glPointSize(1.f);
573 }
574}
575
576////////////////////////////////////////////////////////////////////////////////
577/// Draw poly-line in user coordinates.
578
580{
582}
583
584////////////////////////////////////////////////////////////////////////////////
585/// Draw poly-line in user coordinates.
586
588{
590}
591
592////////////////////////////////////////////////////////////////////////////////
593///Poly line in NDC.
594
596{
597 if (fLocked) return;
598
600 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
601 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
602 const Double_t x1 = gPad->GetX1(), y1 = gPad->GetY1();
603
604 glBegin(GL_LINE_STRIP);
605
606 for (Int_t i = 0; i < n; ++i)
607 glVertex2d(x1 + u[i] * xRange, y1 + v[i] * yRange);
608
609 glEnd();
610}
611
612////////////////////////////////////////////////////////////////////////////////
613/// Returns true when invert mode is configured and painter in locked state
614/// Used when non-opaque of objects moving is involved
615
620
621////////////////////////////////////////////////////////////////////////////////
622///Poly-marker drawing
623
624template<class ValueType>
625void TGLPadPainter::DrawPolyMarkerHelper(Int_t n, const ValueType *x, const ValueType *y)
626{
627 std::vector<TPoint> poly(n);
628
629 if (fLocked) {
630 if (IsInvertMode()) {
631 for (Int_t i = 0; i < n; ++i) {
632 poly[i].fX = gPad->XtoAbsPixel(x[i]);
633 poly[i].fY = gPad->YtoAbsPixel(y[i]);
634 }
635 gVirtualX->DrawPolyMarkerW(fWinContext, poly.size(), poly.data());
636 }
637 return;
638 }
639
640 const UInt_t padH = gPad->GetPadHeight();
641
642 for (Int_t i = 0; i < n; ++i) {
643 poly[i].fX = gPad->XtoPixel(x[i]);
644 poly[i].fY = padH - gPad->YtoPixel(y[i]);
645 }
646
648 glLoadIdentity();
649 //
650 glOrtho(0, gPad->GetPadWidth(), 0, gPad->GetPadHeight(), -10., 10.);
651 //
652 glMatrixMode(GL_MODELVIEW);
653 //
654 const TGLEnableGuard blendGuard(GL_BLEND);
655
656 Float_t rgba[4] = {};
658 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
659 glColor4fv(rgba);
660
662 glLineWidth(w > fLimits.GetMaxLineWidth() ? fLimits.GetMaxLineWidth() : !w ? 1.f : w);
663
665
667 glMatrixMode(GL_MODELVIEW);
668 glLineWidth(1.f);
669}
670
671////////////////////////////////////////////////////////////////////////////////
672///Poly-marker.
673
678
679////////////////////////////////////////////////////////////////////////////////
680///Poly-marker.
681
686
687////////////////////////////////////////////////////////////////////////////////
688/// Select specified font/size
689
691{
692 //10 is the first valid font index.
693 //20 is FreeSerifBold, as in TTF.cxx and in TGLFontManager.cxx.
694 //shift - is the shift to access "extended" fonts.
696
697 Int_t fontIndex = TMath::Max(Font_t(10), font);
698 if (fontIndex / 10 + shift > TGLFontManager::GetFontFileArray()->GetEntries())
699 fontIndex = 20 + shift * 10;
700 else
701 fontIndex += shift * 10;
702
703 Int_t textSize = TMath::Max(Int_t(tsize) - 1, 10);
704
705 const char *name = TGLFontManager::GetFontNameFromId(fontIndex);
706
708}
709
710////////////////////////////////////////////////////////////////////////////////
711/// Indicate that TTF can be used for text metrics
712/// Drawing done with FTGL which is based on Freetype library
713
715{
716 return kTRUE;
717}
718
719
720////////////////////////////////////////////////////////////////////////////////
721/// Helper function to draw text
722
723template<class Char>
725{
727
728 glLoadIdentity();
729 //
730 glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
731 //
732 glMatrixMode(GL_MODELVIEW);
733
734 Float_t rgba[4] = {};
736 glColor4fv(rgba);
737
738 SelectGLFont(GetAttText().GetTextFont(), GetAttText().GetTextSizePixels(*gPad));
739
741
742 fF.PreRender();
743
744 const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
745 fF.Render(text, gPad->XtoPixel(x), padH - gPad->YtoPixel(y), GetTextAngle(), GetTextMagnitude());
746
747 fF.PostRender();
749
750 glMatrixMode(GL_MODELVIEW);
751}
752
753////////////////////////////////////////////////////////////////////////////////
754///Draw text. This operation is especially
755///dangerous if in locked state -
756///ftgl will assert on zero texture size
757///(which is result of bad GL context).
758
760{
761 if (fLocked) return;
762
763 if (GetAttText().GetTextSize() > 0)
765}
766
767////////////////////////////////////////////////////////////////////////////////
768///Draw text. This operation is especially
769///dangerous if in locked state -
770///ftgl will assert on zero texture size
771///(which is result of bad GL context).
772
774{
775 if (fLocked) return;
776
777 if (GetAttText().GetTextSize() > 0)
779}
780
781////////////////////////////////////////////////////////////////////////////////
782///Draw text in NDC. This operation is especially
783///dangerous if in locked state -
784///ftgl will assert on zero texture size
785///(which is result of bad GL context).
786
788{
789 if (fLocked) return;
790
791 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
792 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
793 DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
794}
795
796////////////////////////////////////////////////////////////////////////////////
797///Draw text in NDC. This operation is especially
798///dangerous if in locked state -
799///ftgl will assert on zero texture size
800///(which is result of bad GL context).
801
803{
804 if (fLocked) return;
805
806 const Double_t xRange = gPad->GetX2() - gPad->GetX1();
807 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
808 DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
809}
810
811////////////////////////////////////////////////////////////////////////////////
812///Save the projection matrix.
813///Attention! GL_PROJECTION will become the current matrix
814///after this call!
815
817{
818 glMatrixMode(GL_PROJECTION);
819 glPushMatrix();
820}
821
822////////////////////////////////////////////////////////////////////////////////
823///Restore the projection matrix.
824///Attention! GL_PROJECTION will become the current matrix
825///after this call!
826
828{
829 glMatrixMode(GL_PROJECTION);
830 glPopMatrix();
831}
832
833////////////////////////////////////////////////////////////////////////////////
834///Save the modelview matrix.
835///Attention! GL_MODELVIEW will become the current matrix
836///after this call!
837
839{
840 glMatrixMode(GL_MODELVIEW);
841 glPushMatrix();
842}
843
844////////////////////////////////////////////////////////////////////////////////
845///Restore the modelview matrix.
846///Attention! GL_MODELVIEW will become the current matrix
847///after this call!
848
850{
851 glMatrixMode(GL_MODELVIEW);
852 glPopMatrix();
853}
854
855////////////////////////////////////////////////////////////////////////////////
856///Extract and save the current viewport.
857
859{
860 glGetIntegerv(GL_VIEWPORT, fVp);
861}
862
863////////////////////////////////////////////////////////////////////////////////
864///Restore the saved viewport.
865
867{
868 glViewport(fVp[0], fVp[1], fVp[2], fVp[3]);
869}
870
871
872////////////////////////////////////////////////////////////////////////////////
873/// Draw image on the GL window
874
876{
877 Int_t width = img->GetWidth();
878 Int_t height = img->GetHeight();
879 auto bits = img->GetArgbArray();
880 if (bits)
881 DrawPixels((unsigned char *)bits, width, height, x, y, flags);
882}
883
884////////////////////////////////////////////////////////////////////////////////
885/// Fill image object with the pixel data from the pad
886/// Implements special handling for X11 where ASImage has native implementation
887
889{
890 auto canvas = pad ? pad->GetCanvas() : nullptr;
891 if (!canvas || !image)
892 return kFALSE;
893
894 UInt_t width = canvas->GetPadWidth(), height = canvas->GetPadHeight();
895 Int_t x0 = 0, y0 = 0;
896
897 if (pad != canvas) {
898 // GL always paint complete canvas - just extract part out of the complete buffer
899 UInt_t pad_width = pad->GetPadWidth();
900 UInt_t pad_height = pad->GetPadHeight();
901 if (!pad_width || !pad_height) {
902 Error("FillImageFromPad", "Pad dimensions are zero");
903 return kFALSE;
904 }
905
906 x0 = TMath::Max(0, pad->UtoAbsPixel(0));
907 y0 = TMath::Max(0, pad->VtoAbsPixel(1));
908 if ((x0 + pad_width > width) || (y0 + pad_height > height)) {
909 Error("FillImageFromPad", "Pad dimensions exceed canvas size");
910 return kFALSE;
911 }
912
913 // because of GL lines swapping need to recalculate first line
914 y0 = height - (y0 + pad_height);
915
916 width = pad_width;
917 height = pad_height;
918 }
919
920 // special mode to request window attributes, implemented only in TRootCanvas
921 Int_t update_arg = 101;
922 // on Mac redo update again - no other way found to get GL image updated
923 if (IsCocoa()) {
924 canvas->Update();
925 update_arg = 1;
926 }
927
928 canvas->GetCanvasImp()->UpdateDisplay(update_arg, kFALSE);
929
930#ifndef WIN32
931 // crash on Windows
932 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
933#endif
934
935 glPixelStorei(GL_PACK_ALIGNMENT, 1);
936 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
937 glReadBuffer(GL_BACK);
938
939 //In case GL_BGRA is not in gl.h (old windows' gl) - comment/uncomment lines.
940 //glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_BGRA, GL_UNSIGNED_BYTE, (char *)&buff[0]);
941
942 std::vector<unsigned> buff(width * height);
943
944 glReadPixels(x0, y0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (char *) buff.data());
945
946 TGLUtil::SwapPixelBuffer((UChar_t *) buff.data(), width, height);
947
948 // convert rgba into bgra
949 for (auto &pix : buff)
950 pix = ((pix & 0xff) << 16) | (pix & 0xff00) | ((pix & 0xff0000) >> 16) | (pix & 0xff000000);
951
952 image->FromBitmap((UChar_t *) buff.data(), width, height);
953
954 return image->IsValid();
955}
956
957
958////////////////////////////////////////////////////////////////////////////////
959
960void TGLPadPainter::DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height,
961 Int_t dstX, Int_t dstY, Bool_t enableBlending)
962{
963 if (fLocked)
964 return;
965
966 if (!pixelData) {
967 //I'd prefer an assert.
968 ::Error("TGLPadPainter::DrawPixels", "pixel data is null");
969 return;
970 }
971
972 if (std::numeric_limits<UInt_t>::digits >= 32) {
973 //TASImage uses bit 31 as ...
974 //alpha channel flag! FUUUUUUUUUUUUU ..... !!!
975 CLRBIT(width, 31);
976 CLRBIT(height, 31);
977 }
978
979 if (!width) {
980 //Assert is better.
981 ::Error("TGLPadPainter::DrawPixels", "invalid width");
982 return;
983 }
984
985 if (!height) {
986 //Assert is better.
987 ::Error("TGLPadPainter::DrawPixels", "invalid height");
988 return;
989 }
990
991 if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
992 //TASImage passes pixel coordinates in pad's pixmap coordinate space.
993 //While glRasterPosX said to work with 'window' coordinates,
994 //that's a lie :) it does not :)
995
996 const Double_t rasterX = Double_t(dstX) / (pad->GetAbsWNDC() * pad->GetWw()) *
997 (pad->GetX2() - pad->GetX1()) + pad->GetX1();
998
999 const Double_t yRange = pad->GetY2() - pad->GetY1();
1000 const Double_t rasterY = yRange - Double_t(dstY + height) / (pad->GetAbsHNDC() * pad->GetWh()) * yRange +
1001 pad->GetY1();
1002
1003 GLdouble oldPos[4] = {};
1004 //Save the previous raster pos.
1005 glGetDoublev(GL_CURRENT_RASTER_POSITION, oldPos);
1006
1007 glRasterPos2d(rasterX, rasterY);
1008 //Stupid asimage provides us upside-down image.
1009 std::vector<unsigned char> upsideDownImage(4 * width * height);
1010 const unsigned char *srcLine = pixelData + 4 * width * (height - 1);
1011 unsigned char *dstLine = &upsideDownImage[0];
1012 for (UInt_t i = 0; i < height; ++i, srcLine -= 4 * width, dstLine += 4 * width)
1013 std::copy(srcLine, srcLine + 4 * width, dstLine);
1014
1015 if (enableBlending) {
1016 glEnable(GL_BLEND);
1017 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1018 }
1019
1020 glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, &upsideDownImage[0]);
1021
1022 if (enableBlending)
1023 glDisable(GL_BLEND);
1024
1025 //Restore raster pos.
1026 glRasterPos2d(oldPos[0], oldPos[1]);
1027 } else
1028 ::Error("TGLPadPainter::DrawPixels", "no pad found to draw");
1029}
1030
1031//Aux. functions - gradient and solid fill of arbitrary area.
1032
1033////////////////////////////////////////////////////////////////////////////////
1034///At the moment I assume both linear and radial gradients will work the same way -
1035///using a stencil buffer and some big rectangle(s) to fill with a gradient.
1036///Thus I have a 'common' part - the part responsible for a stencil test.
1037
1039{
1040 assert(n > 2 && "DrawPolygonWithGradient, invalid number of points");
1041 assert(x != nullptr && "DrawPolygonWithGradient, parameter 'x' is null");
1042 assert(y != nullptr && "DrawPolygonWithGradient, parameter 'y' is null");
1043
1044 auto grad = dynamic_cast<TColorGradient *>(gROOT->GetColor(fGlFillAtt.GetFillColor()));
1045 assert(grad != nullptr && "DrawPolygonWithGradient, the current fill color is not a gradient fill");
1046
1047 if (fLocked)
1048 return;
1049
1050 //Now, some magic!
1051 const TGLEnableGuard stencilGuard(GL_STENCIL_TEST);
1052
1053 //TODO: check that the state is restored back correctly after
1054 // we done with a gradient.
1055 //TODO: make sure that we have glDepthMask set to false in general!
1056 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1057
1058 glStencilFunc(GL_NEVER, 1, 0xFF);
1059 glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);// draw 1s on test fail (always)
1060 //Draw stencil pattern
1061 glStencilMask(0xFF);
1062 glClear(GL_STENCIL_BUFFER_BIT);
1063
1064 //Draw our polygon into the stencil buffer:
1065 DrawTesselation(n, x, y);
1066
1067 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1068 glStencilMask(0x00);
1069 //Draw where stencil's value is 0
1070 glStencilFunc(GL_EQUAL, 0, 0xFF);
1071 //Draw only where stencil's value is 1
1072 glStencilFunc(GL_EQUAL, 1, 0xFF);
1073
1074 //At the moment radial gradient is derived from linear - it was convenient
1075 //at some point, but in fact it was a bad idea. And now I have to
1076 //first check radial gradient.
1077 //TODO: TRadialGradient must inherit TColorGradient directly.
1078 const TRadialGradient * const rGrad = dynamic_cast<const TRadialGradient *>(grad);
1079 if (rGrad)
1080 DrawGradient(rGrad, n, x, y);
1081 else {
1082 const TLinearGradient * const lGrad = dynamic_cast<const TLinearGradient *>(grad);
1083 assert(lGrad != nullptr && "DrawPolygonWithGradient, unknown gradient type");
1084 DrawGradient(lGrad, n, x, y);
1085 }
1086}
1087
1088////////////////////////////////////////////////////////////////////////////////
1089
1091 const Double_t *xs, const Double_t *ys)
1092{
1093 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1094 assert(nPoints > 2 && "DrawGradient, invalid number of points");
1095 assert(xs != nullptr && "DrawGradient, parameter 'xs' is null");
1096 assert(ys != nullptr && "DrawGradient, parameter 'ys' is null");
1097
1099 ::Warning("TGLPadPainter::DrawGradient",
1100 "extended radial gradient is not supported");//yet?
1101 return;
1102 }
1103
1104 //TODO: check the polygon's bbox!
1105 const auto &bbox = Rgl::Pad::FindBoundingRect(nPoints, xs, ys);
1106 //
1107 auto center = grad->GetCenter();
1108 auto radius = grad->GetRadius();
1109 //Adjust the center and radius depending on coordinate mode.
1111 radius *= TMath::Max(bbox.fWidth, bbox.fHeight);
1112 center.fX = bbox.fWidth * center.fX + bbox.fXMin;
1113 center.fY = bbox.fHeight * center.fY + bbox.fYMin;
1114 } else {
1115 const auto w = gPad->GetX2() - gPad->GetX1();
1116 const auto h = gPad->GetY2() - gPad->GetY1();
1117
1118 radius *= TMath::Max(w, h);
1119 center.fX *= w;
1120 center.fY *= h;
1121 }
1122 //Now for the gradient fill we switch into pixel coordinates:
1123 const auto pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1124 const auto pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1125 //
1128 //A new ortho projection:
1129 glMatrixMode(GL_PROJECTION);
1130 glLoadIdentity();
1131 //
1132 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1133 //
1134 radius *= TMath::Max(pixelH, pixelW);
1135 center.fX = gPad->XtoPixel(center.fX);
1136 center.fY = pixelH - gPad->YtoPixel(center.fY);
1137
1138 Double_t maxR = 0.;
1139 {
1140 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1141 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1142 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1143 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1144 //Get the longest distance from the center to the bounding box vertices
1145 //(this will be the maximum possible radius):
1146 const Double_t maxDistX = TMath::Max(TMath::Abs(center.fX - xMin),
1147 TMath::Abs(center.fX - xMax));
1148 const Double_t maxDistY = TMath::Max(TMath::Abs(center.fY - yMin),
1149 TMath::Abs(center.fY - yMax));
1150 maxR = TMath::Sqrt(maxDistX * maxDistX + maxDistY * maxDistY);
1151 }
1152
1153 //If gradient 'stops inside the polygon', we use
1154 //the solid fill for the area outside of radial gradient:
1155 const Bool_t solidFillAfter = maxR > radius;
1156 //We emulate a radial gradient using triangles and linear gradient:
1157 //TODO: Can be something smarter? (btw even 100 seems to be enough)
1158 const UInt_t nSlices = 500;
1159
1160 const auto nColors = grad->GetNumberOfSteps();
1161 //+1 - the strip from the last color's position to radius,
1162 //and (probably) + 1 for solidFillAfter.
1163 const auto nCircles = nColors + 1 + solidFillAfter;
1164
1165 //TODO: can locations be outside of [0., 1.] ???
1166 //at the moment I assume the answer is NO, NEVER.
1167 const auto locations = grad->GetColorPositions();
1168 // * 2 below == x,y
1169 std::vector<Double_t> circles(nSlices * nCircles * 2);
1170 const Double_t angle = TMath::TwoPi() / nSlices;
1171
1172 //"Main" circles (for colors at locations[i]).
1173 for (UInt_t i = 0; i < nColors; ++i) {
1174 const auto circle = &circles[i * nSlices * 2];
1175 //TODO: either check locations here or somewhere else.
1176 const auto r = radius * locations[i];
1177 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1178 circle[j] = center.fX + r * TMath::Cos(angle * j);
1179 circle[j + 1] = center.fY + r * TMath::Sin(angle * j);
1180 }
1181 //The "closing" vertices:
1182 circle[(nSlices - 1) * 2] = circle[0];
1183 circle[(nSlices - 1) * 2 + 1] = circle[1];
1184 }
1185
1186 {
1187 //The strip between lastPos and radius:
1188 const auto circle = &circles[nColors * nSlices * 2];
1189 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1190 circle[j] = center.fX + radius * TMath::Cos(angle * j);
1191 circle[j + 1] = center.fY + radius * TMath::Sin(angle * j);
1192 }
1193
1194 circle[(nSlices - 1) * 2] = circle[0];
1195 circle[(nSlices - 1) * 2 + 1] = circle[1];
1196 }
1197
1198 if (solidFillAfter) {
1199 //The strip after the radius:
1200 const auto circle = &circles[(nCircles - 1) * nSlices * 2];
1201 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1202 circle[j] = center.fX + maxR * TMath::Cos(angle * j);
1203 circle[j + 1] = center.fY + maxR * TMath::Sin(angle * j);
1204 }
1205
1206 circle[(nSlices - 1) * 2] = circle[0];
1207 circle[(nSlices - 1) * 2 + 1] = circle[1];
1208 }
1209
1210 //Now we draw:
1211 //1) triangle fan in the center (from center to the locations[1],
1212 // with a solid fill).
1213 //2) quad strips for colors.
1214 //3) additional quad strip from the lastLocation to the radius
1215 //4) additional quad strip (if any) from the radius to maxR.
1216
1217 //RGBA values:
1218 const auto rgba = grad->GetColors();
1219
1220 const TGLEnableGuard alphaGuard(GL_BLEND);
1221 //TODO?
1222 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1223
1224 //Probably a degenerated case. Maybe not.
1225 glBegin(GL_TRIANGLE_FAN);
1226 glColor4dv(rgba);
1227 glVertex2d(center.fX, center.fY);
1228
1229 for (UInt_t i = 0, e = nSlices * 2; i < e; i += 2)
1230 glVertex2dv(&circles[i]);
1231
1232 glEnd();
1233
1234 //No auto for circles, explicit types to have const Double_t * const, not Duble_t * const.
1235 for (UInt_t i = 0; i < nColors - 1; ++i) {
1236 const Double_t * const inner = &circles[i * nSlices * 2];
1237 const auto innerRGBA = rgba + i * 4;
1238 const auto outerRGBA = rgba + (i + 1) * 4;
1239 const Double_t * const outer = &circles[(i + 1) * nSlices * 2];
1240
1241 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, innerRGBA, outer, outerRGBA);
1242 }
1243
1244 //Probably degenerated strip.
1245 {
1246 const Double_t * const inner = &circles[nSlices * (nColors - 1) * 2];
1247 const auto solidRGBA = rgba + (nColors - 1) * 4;
1248 const Double_t * const outer = &circles[nSlices * nColors * 2];
1249
1250 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, solidRGBA, outer, solidRGBA);
1251 }
1252
1253 if (solidFillAfter) {
1254 const Double_t * const inner = &circles[nSlices * nColors * 2];
1255 const auto solidRGBA = rgba + (nColors - 1) * 4;
1256 const Double_t * const outer = &circles[nSlices * (nColors + 1) * 2];
1257
1258 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, solidRGBA, outer, solidRGBA);
1259 }
1260
1263}
1264
1265////////////////////////////////////////////////////////////////////////////////
1266
1268 const Double_t *x, const Double_t *y)
1269{
1270 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1271 assert(n > 2 && "DrawGradient, invalid number of points");
1272 assert(x != nullptr && "DrawGradient, parameter 'x' is null");
1273 assert(y != nullptr && "DrawGradient, parameter 'y' is null");
1274
1275 //Now we fill the whole scene with one big rectangle
1276 //(group of rectangles) with a gradient fill using
1277 //stencil test.
1278
1279 //Find a bounding rect.
1280 const auto &bbox = Rgl::Pad::FindBoundingRect(n, x, y);
1281 //TODO: check the bbox??
1282
1283 //For the gradient fill we switch into the
1284 //pixel coordinates.
1287
1288 //A new ortho projection:
1289 glMatrixMode(GL_PROJECTION);
1290 glLoadIdentity();
1291
1292 const Double_t pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1293 const Double_t pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1294 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1295
1296 //A new modelview:
1297 glMatrixMode(GL_MODELVIEW);
1298 glLoadIdentity();
1299 //
1300 TColorGradient::Point start = grad->GetStart();
1301 TColorGradient::Point end = grad->GetEnd();
1302
1303 //Change gradient coordinates from 'NDC' to pad coords:
1305 {
1306 const Double_t w = gPad->GetX2() - gPad->GetX1();
1307 const Double_t h = gPad->GetY2() - gPad->GetY1();
1308
1309 start.fX = start.fX * w;
1310 start.fY = start.fY * h;
1311 end.fX = end.fX * w;
1312 end.fY = end.fY * h;
1313 } else {
1314 start.fX = start.fX * bbox.fWidth + bbox.fXMin;
1315 start.fY = start.fY * bbox.fHeight + bbox.fYMin;
1316 end.fX = end.fX * bbox.fWidth + bbox.fXMin;
1317 end.fY = end.fY * bbox.fHeight + bbox.fYMin;
1318 }
1319
1320 //TODO: with a radial fill we'll have to extract the code
1321 // below into the separate function/and have additional function
1322 // for a radial gradient.
1323 //Now from pad to pixels:
1324 start.fX = gPad->XtoPixel(start.fX);
1325 start.fY = pixelH - gPad->YtoPixel(start.fY);
1326 end.fX = gPad->XtoPixel(end.fX);
1327 end.fY = pixelH - gPad->YtoPixel(end.fY);
1328 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1329 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1330 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1331 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1332 //
1333
1334 //TODO: check all calculations!
1335
1336 //Get the longest distance from the start point to the bounding box vertices:
1337 const Double_t maxDistX = TMath::Max(TMath::Abs(start.fX - xMin), TMath::Abs(start.fX - xMax));
1338 const Double_t maxDistY = TMath::Max(TMath::Abs(start.fY - yMin), TMath::Abs(start.fY - yMax));
1339
1340 const Double_t startEndLength = TMath::Sqrt((end.fX - start.fX) * (end.fX - start.fX) +
1341 (end.fY - start.fY) * (end.fY - start.fY));
1342 const Double_t h = TMath::Max(TMath::Sqrt(maxDistX * maxDistX + maxDistY * maxDistY),
1343 startEndLength);
1344
1345 //Boxes with a gradients to emulate gradient fill with many colors:
1346 const Double_t * const colorPositions = grad->GetColorPositions();
1347 std::vector<Double_t> gradBoxes(grad->GetNumberOfSteps() + 2);
1348 gradBoxes[0] = start.fY - h;
1349 for (unsigned i = 1; i <= grad->GetNumberOfSteps(); ++i)
1350 gradBoxes[i] = startEndLength * colorPositions[i - 1] + start.fY;
1351
1352 gradBoxes[grad->GetNumberOfSteps() + 1] = start.fY + h;
1353
1354 //Rotation angle - gradient's axis:
1355 Double_t angle = TMath::ACos((startEndLength * (end.fY - start.fY)) /
1356 (startEndLength * startEndLength)) * TMath::RadToDeg();
1357 if (end.fX > start.fX)
1358 angle *= -1;
1359
1360 glTranslated(start.fX, start.fY, 0.);
1361 glRotated(angle, 0., 0., 1.);
1362 glTranslated(-start.fX, -start.fY, 0.);
1363 //
1364 const Double_t * const rgba = grad->GetColors();
1365
1366 const unsigned nEdges = gradBoxes.size();
1367 const unsigned nColors = grad->GetNumberOfSteps();
1368 const Double_t xLeft = start.fX - h, xRight = start.fX + h;
1369
1370 const TGLEnableGuard alphaGuard(GL_BLEND);
1371 //TODO?
1372 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1373
1374 Rgl::DrawBoxWithGradientFill(gradBoxes[0], gradBoxes[1], xLeft, xRight, rgba, rgba);
1375 Rgl::DrawBoxWithGradientFill(gradBoxes[nEdges - 2], gradBoxes[nEdges - 1], xLeft, xRight,
1376 rgba + (nColors - 1) * 4, rgba + (nColors - 1) * 4);
1377
1378 for (unsigned i = 1; i < nEdges - 2; ++i)
1379 Rgl::DrawBoxWithGradientFill(gradBoxes[i], gradBoxes[i + 1], xLeft,
1380 xRight, rgba + (i - 1) * 4, rgba + i * 4);
1381
1384}
1385
1386////////////////////////////////////////////////////////////////////////////////
1387
1389{
1390 assert(n > 2 && "DrawTesselation, invalid number of points");
1391 assert(x != nullptr && "DrawTesselation, parameter 'x' is null");
1392 assert(y != nullptr && "DrawTesselation, parameter 'y' is null");
1393
1394 //Data for a tesselator:
1395 fVs.resize(n * 3);
1396
1397 for (Int_t i = 0; i < n; ++i) {
1398 fVs[i * 3] = x[i];
1399 fVs[i * 3 + 1] = y[i];
1400 fVs[i * 3 + 2] = 0.;
1401 }
1402
1403 //TODO: A very primitive way to tesselate - check what
1404 //kind of polygons we can really have from TPad/TCanvas.
1405 GLUtesselator *t = (GLUtesselator *)fTess.GetTess();
1406 gluBeginPolygon(t);
1407 gluNextContour(t, (GLenum)GLU_UNKNOWN);
1408
1409 for (Int_t i = 0; i < n; ++i)
1410 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
1411
1412 gluEndPolygon(t);
1413}
1414
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
char * device
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Color_t
Color number (short)
Definition RtypesCore.h:100
unsigned char UChar_t
Unsigned Character 1 byte (unsigned char)
Definition RtypesCore.h:53
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
short Width_t
Line width (short)
Definition RtypesCore.h:99
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
short Font_t
Font number (short)
Definition RtypesCore.h:96
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
short SCoord_t
Screen coordinates (short)
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
#define CLRBIT(n, i)
Definition Rtypes.h:92
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
const Double_t lineWidthTS
#define GL_BGRA
Definition TGLViewer.cxx:61
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pix
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint xy
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t width
Option_t Option_t TPoint TPoint percent
Option_t Option_t TPoint TPoint DrawText
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:142
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:792
#define gROOT
Definition TROOT.h:417
#define gPad
#define gVirtualX
Definition TVirtualX.h:379
Double_t GetMaxLineWidth() const
Double_t GetMaxPointSize() const
static void DrawMarkers(UInt_t n, const TPoint *xy, const TAttMarker &attr)
Auxiliary class to draw markers in a gl-pad.
void * GetTess() const
Fill Area Attributes class.
Definition TAttFill.h:21
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
Line Attributes class.
Definition TAttLine.h:21
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
Marker Attributes class.
Definition TAttMarker.h:22
static Width_t GetMarkerLineWidth(Style_t style)
Internal helper function that returns the line width of the given marker style (0 = filled marker)
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 SetTextAlign(UInt_t align)
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 DrawPolyMarkerHelper(Int_t n, const ValueType *x, const ValueType *y)
Poly-marker drawing.
void SetDrawMode(Int_t device, Int_t mode) override
Set drawing mode for specified device.
void DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height, Int_t dstX, Int_t dstY, Bool_t enableBlending) override
Int_t ResizeDrawable(Int_t device, UInt_t w, UInt_t h) override
Resize a gVirtualX Pixmap.
void DestroyDrawable(Int_t device) override
Not required at the moment.
void DrawGradient(const TLinearGradient *gradient, Int_t n, const Double_t *x, const Double_t *y)
Rgl::Pad::Tesselator fTess
void SelectGLFont(Font_t font, Float_t size)
Select specified font/size.
void DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) override
Draw line segment in NDC coordinates.
WinContext_t fWinContext
void DrawTextHelper(Double_t x, Double_t y, const Char_t *text, ETextMode mode)
void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode) override
Draw filled or hollow box.
void SetAttLine(const TAttLine &att) override
Set line attributes.
TAttFill fGlFillAtt
void DrawPolygonWithGradient(Int_t n, const Double_t *x, const Double_t *y)
At the moment I assume both linear and radial gradients will work the same way - using a stencil buff...
Bool_t IsInvertMode()
Returns true when invert mode is configured and painter in locked state Used when non-opaque of objec...
void InvalidateCS() override
When TPad::Range for gPad is called, projection must be changed in OpenGL.
void ClearDrawable() override
Do nothing, sub-pads not cleared in GL.
void ClearWindow(Int_t device) override
Clear specified window - calling gVirtualX->ClearWindowW.
void DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v) override
Poly line in NDC.
void OnPad(TVirtualPad *) override
Select pad where current painting will be performed.
void DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) override
Draw poly-line in user coordinates.
void DrawImage(TImage *img, Int_t x, Int_t y, Int_t flags=0) override
Draw image on the GL window.
Rgl::Pad::GLLimits fLimits
void SetOpacity(Int_t percent) override
Delegate to gVirtualX.
void DrawTextNDC(Double_t x, Double_t y, const char *text, ETextMode mode) override
Draw text in NDC.
void SetAttFill(const TAttFill &att) override
Set fill attributes.
void InitPainter() override
Init gl-pad painter:
void SelectDrawable(Int_t device) override
For gVirtualX this means select pixmap (or window) and all subsequent drawings will go into this pixm...
TGLFontManager fFM
Rgl::Pad::PolygonStippleSet fSSet
void SaveViewport()
Extract and save the current viewport.
void CopyDrawable(Int_t device, Int_t px, Int_t py) override
Not required at the moment.
Bool_t IsX11() const override
Returns true when X11 backend is used.
void DrawFillArea(Int_t n, const Double_t *x, const Double_t *y) override
Draw tesselated polygon (probably, outline only).
void DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y) override
Poly-marker.
void DrawPolyLineHelper(Int_t n, const ValueType *x, const ValueType *y)
Draw poly-line in user coordinates.
Bool_t FillImageFromPad(TImage *image, TVirtualPad *pad) const override
Fill image object with the pixel data from the pad Implements special handling for X11 where ASImage ...
void UpdateDrawable(Int_t mode) override
Call low-level update of selected drawable, redirect to gVirtualX.
void RestoreProjectionMatrix() const
Restore the projection matrix.
void SetAttMarker(const TAttMarker &att) override
Set marker attributes.
void LockPainter() override
Locked state of painter means, that GL context can be invalid, so no GL calls can be executed.
Float_t GetTextMagnitude() const override
Delegate to gVirtualX.
void DrawTesselation(Int_t n, const Double_t *x, const Double_t *y)
Bool_t HasTTFonts() const override
Indicate that TTF can be used for text metrics Drawing done with FTGL which is based on Freetype libr...
Int_t CreateDrawable(UInt_t w, UInt_t h) override
Not required at the moment.
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.
Bool_t IsCocoa() const override
Returns true when cocoa backend is used.
void SaveModelviewMatrix() const
Save the modelview matrix.
void RestoreViewport()
Restore the saved viewport.
static void InitializeIfNeeded()
Initialize globals that require other libraries to be initialized.
Definition TGLUtil.cxx:1573
static void SwapPixelBuffer(UChar_t *buf, UInt_t width, UInt_t height)
Swap rows in pixel buffer returned by glReadPixels function To be able create ASImage from it.
Definition TGLUtil.cxx:2674
static Float_t GetScreenScalingFactor()
Returns scaling factor between screen points and GL viewport pixels.
Definition TGLUtil.cxx:1843
An abstract interface to image processing library.
Definition TImage.h:29
virtual UInt_t * GetArgbArray()
Definition TImage.h:254
virtual UInt_t GetWidth() const
Definition TImage.h:245
virtual Bool_t IsValid() const
Definition TImage.h:247
virtual void FromBitmap(const UChar_t *, UInt_t, UInt_t)
Definition TImage.h:126
virtual UInt_t GetHeight() const
Definition TImage.h:246
const Point & GetEnd() const
Get end.
const Point & GetStart() const
Get start.
void SetAttFill(const TAttFill &att) override
Set fill attributes.
Color_t GetMarkerColor() const override
const TAttText & GetAttText() const override
Get text attributes.
Short_t GetTextAlign() const override
const TAttMarker & GetAttMarker() const override
Get marker attributes.
Style_t GetMarkerStyle() const override
Font_t GetTextFont() const override
Width_t GetLineWidth() const override
Bool_t fFullyTransparent
if transformed fill attributes fully transparent
void SetAttMarker(const TAttMarker &att) override
Set marker attributes.
void SetAttLine(const TAttLine &att) override
Set line attributes.
Float_t GetTextAngle() const override
TAttFill GetAttFillInternal(Bool_t with_transparency)
Returns fill attributes after modification Checks for special fill styles 4000 .
Color_t GetTextColor() const override
Style_t GetLineStyle() const override
const TAttLine & GetAttLine() const override
Get line attributes.
Float_t GetTextSize() const override
The most important graphics class in the ROOT system.
Definition TPad.h:32
SCoord_t fY
Definition TPoint.h:36
SCoord_t fX
Definition TPoint.h:35
Double_t GetRadius() const
Get radius.
const Point & GetCenter() const
Get center.
EGradientType GetGradientType() const
Get gradient type.
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:53
virtual Int_t UtoAbsPixel(Double_t u) const =0
virtual UInt_t GetPadWidth() const =0
virtual UInt_t GetPadHeight() const =0
virtual Int_t VtoAbsPixel(Double_t v) const =0
virtual Int_t GetCanvasID() const =0
virtual TCanvas * GetCanvas() const =0
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
BoundingRect< ValueType > FindBoundingRect(Int_t nPoints, const ValueType *xs, const ValueType *ys)
void ExtractRGBA(Color_t colorIndex, Float_t *rgba)
void DrawQuadStripWithRadialGradientFill(unsigned nPoints, const Double_t *inner, const Double_t *innerRGBA, const Double_t *outer, const Double_t *outerRGBA)
TODO: is it possible to use GLdouble to avoid problems with Double_t/GLdouble if they are not the sam...
Definition TGLUtil.cxx:3230
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:3210
Double_t ACos(Double_t)
Returns the principal value of the arc cosine of x, expressed in radians.
Definition TMath.h:645
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:675
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:607
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:601
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
constexpr Double_t TwoPi()
Definition TMath.h:47