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
875void TGLPadPainter::DrawImage(TImage *img, Int_t dstX, Int_t dstY, Int_t flags)
876{
877 if (fLocked)
878 return;
879
880 auto width = img->GetWidth();
881 auto height = img->GetHeight();
882 auto pixelData = (unsigned char *) img->GetArgbArray();
883
884 if (!pixelData) {
885 ::Error("TGLPadPainter::DrawImage", "pixel data is null");
886 return;
887 }
888
889 if (!width || !height) {
890 //Assert is better.
891 ::Error("TGLPadPainter::DrawImage", "invalid image dimentsion");
892 return;
893 }
894
895 if (!gPad) {
896 ::Error("TGLPadPainter::DrawImage", "pad is not provided");
897 return;
898 }
899
900 const Double_t rasterX = Double_t(dstX) / gPad->GetPadWidth() * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1();
901
902 const Double_t yRange = gPad->GetY2() - gPad->GetY1();
903 const Double_t rasterY = yRange - Double_t(dstY + height) / gPad->GetPadHeight() * yRange + gPad->GetY1();
904
905 GLdouble oldPos[4] = {};
906 // Save the previous raster pos.
907 glGetDoublev(GL_CURRENT_RASTER_POSITION, oldPos);
908
909 glRasterPos2d(rasterX, rasterY);
910 // Stupid asimage provides us upside-down image.
911 std::vector<unsigned char> upsideDownImage(4 * width * height);
912 const unsigned char *srcLine = pixelData + 4 * width * (height - 1);
913 unsigned char *dstLine = &upsideDownImage[0];
914 for (UInt_t i = 0; i < height; ++i, srcLine -= 4 * width, dstLine += 4 * width)
915 std::copy(srcLine, srcLine + 4 * width, dstLine);
916
917 if (flags) {
918 glEnable(GL_BLEND);
919 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
920 }
921
922 glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, &upsideDownImage[0]);
923
924 if (flags)
925 glDisable(GL_BLEND);
926
927 //Restore raster pos.
928 glRasterPos2d(oldPos[0], oldPos[1]);
929}
930
931////////////////////////////////////////////////////////////////////////////////
932/// Fill image object with the pixel data from the pad
933/// Implements special handling for X11 where ASImage has native implementation
934
936{
937 auto canvas = pad ? pad->GetCanvas() : nullptr;
938 if (!canvas || !image)
939 return kFALSE;
940
941 UInt_t width = canvas->GetPadWidth(), height = canvas->GetPadHeight();
942 Int_t x0 = 0, y0 = 0;
943
944 if (pad != canvas) {
945 // GL always paint complete canvas - just extract part out of the complete buffer
946 UInt_t pad_width = pad->GetPadWidth();
947 UInt_t pad_height = pad->GetPadHeight();
948 if (!pad_width || !pad_height) {
949 Error("FillImageFromPad", "Pad dimensions are zero");
950 return kFALSE;
951 }
952
953 x0 = TMath::Max(0, pad->UtoAbsPixel(0));
954 y0 = TMath::Max(0, pad->VtoAbsPixel(1));
955 if ((x0 + pad_width > width) || (y0 + pad_height > height)) {
956 Error("FillImageFromPad", "Pad dimensions exceed canvas size");
957 return kFALSE;
958 }
959
960 // because of GL lines swapping need to recalculate first line
961 y0 = height - (y0 + pad_height);
962
963 width = pad_width;
964 height = pad_height;
965 }
966
967 // special mode to request window attributes, implemented only in TRootCanvas
968 Int_t update_arg = 101;
969 // on Mac redo update again - no other way found to get GL image updated
970 if (IsCocoa()) {
971 canvas->Update();
972 update_arg = 1;
973 }
974
975 canvas->GetCanvasImp()->UpdateDisplay(update_arg, kFALSE);
976
977#ifndef WIN32
978 // crash on Windows
979 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
980#endif
981
982 glPixelStorei(GL_PACK_ALIGNMENT, 1);
983 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
984 glReadBuffer(GL_BACK);
985
986 //In case GL_BGRA is not in gl.h (old windows' gl) - comment/uncomment lines.
987 //glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_BGRA, GL_UNSIGNED_BYTE, (char *)&buff[0]);
988
989 std::vector<unsigned> buff(width * height);
990
991 glReadPixels(x0, y0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (char *) buff.data());
992
993 TGLUtil::SwapPixelBuffer((UChar_t *) buff.data(), width, height);
994
995 // convert rgba into bgra
996 for (auto &pix : buff)
997 pix = ((pix & 0xff) << 16) | (pix & 0xff00) | ((pix & 0xff0000) >> 16) | (pix & 0xff000000);
998
999 image->FromBitmap((UChar_t *) buff.data(), width, height);
1000
1001 return image->IsValid();
1002}
1003
1004
1005////////////////////////////////////////////////////////////////////////////////
1006
1007void TGLPadPainter::DrawPixels(const unsigned char *, UInt_t, UInt_t,
1008 Int_t, Int_t, Bool_t)
1009{
1010}
1011
1012//Aux. functions - gradient and solid fill of arbitrary area.
1013
1014////////////////////////////////////////////////////////////////////////////////
1015///At the moment I assume both linear and radial gradients will work the same way -
1016///using a stencil buffer and some big rectangle(s) to fill with a gradient.
1017///Thus I have a 'common' part - the part responsible for a stencil test.
1018
1020{
1021 assert(n > 2 && "DrawPolygonWithGradient, invalid number of points");
1022 assert(x != nullptr && "DrawPolygonWithGradient, parameter 'x' is null");
1023 assert(y != nullptr && "DrawPolygonWithGradient, parameter 'y' is null");
1024
1025 auto grad = dynamic_cast<TColorGradient *>(gROOT->GetColor(fGlFillAtt.GetFillColor()));
1026 assert(grad != nullptr && "DrawPolygonWithGradient, the current fill color is not a gradient fill");
1027
1028 if (fLocked)
1029 return;
1030
1031 //Now, some magic!
1032 const TGLEnableGuard stencilGuard(GL_STENCIL_TEST);
1033
1034 //TODO: check that the state is restored back correctly after
1035 // we done with a gradient.
1036 //TODO: make sure that we have glDepthMask set to false in general!
1037 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1038
1039 glStencilFunc(GL_NEVER, 1, 0xFF);
1040 glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);// draw 1s on test fail (always)
1041 //Draw stencil pattern
1042 glStencilMask(0xFF);
1043 glClear(GL_STENCIL_BUFFER_BIT);
1044
1045 //Draw our polygon into the stencil buffer:
1046 DrawTesselation(n, x, y);
1047
1048 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1049 glStencilMask(0x00);
1050 //Draw where stencil's value is 0
1051 glStencilFunc(GL_EQUAL, 0, 0xFF);
1052 //Draw only where stencil's value is 1
1053 glStencilFunc(GL_EQUAL, 1, 0xFF);
1054
1055 //At the moment radial gradient is derived from linear - it was convenient
1056 //at some point, but in fact it was a bad idea. And now I have to
1057 //first check radial gradient.
1058 //TODO: TRadialGradient must inherit TColorGradient directly.
1059 const TRadialGradient * const rGrad = dynamic_cast<const TRadialGradient *>(grad);
1060 if (rGrad)
1061 DrawGradient(rGrad, n, x, y);
1062 else {
1063 const TLinearGradient * const lGrad = dynamic_cast<const TLinearGradient *>(grad);
1064 assert(lGrad != nullptr && "DrawPolygonWithGradient, unknown gradient type");
1065 DrawGradient(lGrad, n, x, y);
1066 }
1067}
1068
1069////////////////////////////////////////////////////////////////////////////////
1070
1072 const Double_t *xs, const Double_t *ys)
1073{
1074 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1075 assert(nPoints > 2 && "DrawGradient, invalid number of points");
1076 assert(xs != nullptr && "DrawGradient, parameter 'xs' is null");
1077 assert(ys != nullptr && "DrawGradient, parameter 'ys' is null");
1078
1080 ::Warning("TGLPadPainter::DrawGradient",
1081 "extended radial gradient is not supported");//yet?
1082 return;
1083 }
1084
1085 //TODO: check the polygon's bbox!
1086 const auto &bbox = Rgl::Pad::FindBoundingRect(nPoints, xs, ys);
1087 //
1088 auto center = grad->GetCenter();
1089 auto radius = grad->GetRadius();
1090 //Adjust the center and radius depending on coordinate mode.
1092 radius *= TMath::Max(bbox.fWidth, bbox.fHeight);
1093 center.fX = bbox.fWidth * center.fX + bbox.fXMin;
1094 center.fY = bbox.fHeight * center.fY + bbox.fYMin;
1095 } else {
1096 const auto w = gPad->GetX2() - gPad->GetX1();
1097 const auto h = gPad->GetY2() - gPad->GetY1();
1098
1099 radius *= TMath::Max(w, h);
1100 center.fX *= w;
1101 center.fY *= h;
1102 }
1103 //Now for the gradient fill we switch into pixel coordinates:
1104 const auto pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1105 const auto pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1106 //
1109 //A new ortho projection:
1110 glMatrixMode(GL_PROJECTION);
1111 glLoadIdentity();
1112 //
1113 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1114 //
1115 radius *= TMath::Max(pixelH, pixelW);
1116 center.fX = gPad->XtoPixel(center.fX);
1117 center.fY = pixelH - gPad->YtoPixel(center.fY);
1118
1119 Double_t maxR = 0.;
1120 {
1121 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1122 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1123 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1124 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1125 //Get the longest distance from the center to the bounding box vertices
1126 //(this will be the maximum possible radius):
1127 const Double_t maxDistX = TMath::Max(TMath::Abs(center.fX - xMin),
1128 TMath::Abs(center.fX - xMax));
1129 const Double_t maxDistY = TMath::Max(TMath::Abs(center.fY - yMin),
1130 TMath::Abs(center.fY - yMax));
1131 maxR = TMath::Sqrt(maxDistX * maxDistX + maxDistY * maxDistY);
1132 }
1133
1134 //If gradient 'stops inside the polygon', we use
1135 //the solid fill for the area outside of radial gradient:
1136 const Bool_t solidFillAfter = maxR > radius;
1137 //We emulate a radial gradient using triangles and linear gradient:
1138 //TODO: Can be something smarter? (btw even 100 seems to be enough)
1139 const UInt_t nSlices = 500;
1140
1141 const auto nColors = grad->GetNumberOfSteps();
1142 //+1 - the strip from the last color's position to radius,
1143 //and (probably) + 1 for solidFillAfter.
1144 const auto nCircles = nColors + 1 + solidFillAfter;
1145
1146 //TODO: can locations be outside of [0., 1.] ???
1147 //at the moment I assume the answer is NO, NEVER.
1148 const auto locations = grad->GetColorPositions();
1149 // * 2 below == x,y
1150 std::vector<Double_t> circles(nSlices * nCircles * 2);
1151 const Double_t angle = TMath::TwoPi() / nSlices;
1152
1153 //"Main" circles (for colors at locations[i]).
1154 for (UInt_t i = 0; i < nColors; ++i) {
1155 const auto circle = &circles[i * nSlices * 2];
1156 //TODO: either check locations here or somewhere else.
1157 const auto r = radius * locations[i];
1158 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1159 circle[j] = center.fX + r * TMath::Cos(angle * j);
1160 circle[j + 1] = center.fY + r * TMath::Sin(angle * j);
1161 }
1162 //The "closing" vertices:
1163 circle[(nSlices - 1) * 2] = circle[0];
1164 circle[(nSlices - 1) * 2 + 1] = circle[1];
1165 }
1166
1167 {
1168 //The strip between lastPos and radius:
1169 const auto circle = &circles[nColors * nSlices * 2];
1170 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1171 circle[j] = center.fX + radius * TMath::Cos(angle * j);
1172 circle[j + 1] = center.fY + radius * TMath::Sin(angle * j);
1173 }
1174
1175 circle[(nSlices - 1) * 2] = circle[0];
1176 circle[(nSlices - 1) * 2 + 1] = circle[1];
1177 }
1178
1179 if (solidFillAfter) {
1180 //The strip after the radius:
1181 const auto circle = &circles[(nCircles - 1) * nSlices * 2];
1182 for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
1183 circle[j] = center.fX + maxR * TMath::Cos(angle * j);
1184 circle[j + 1] = center.fY + maxR * TMath::Sin(angle * j);
1185 }
1186
1187 circle[(nSlices - 1) * 2] = circle[0];
1188 circle[(nSlices - 1) * 2 + 1] = circle[1];
1189 }
1190
1191 //Now we draw:
1192 //1) triangle fan in the center (from center to the locations[1],
1193 // with a solid fill).
1194 //2) quad strips for colors.
1195 //3) additional quad strip from the lastLocation to the radius
1196 //4) additional quad strip (if any) from the radius to maxR.
1197
1198 //RGBA values:
1199 const auto rgba = grad->GetColors();
1200
1201 const TGLEnableGuard alphaGuard(GL_BLEND);
1202 //TODO?
1203 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1204
1205 //Probably a degenerated case. Maybe not.
1206 glBegin(GL_TRIANGLE_FAN);
1207 glColor4dv(rgba);
1208 glVertex2d(center.fX, center.fY);
1209
1210 for (UInt_t i = 0, e = nSlices * 2; i < e; i += 2)
1211 glVertex2dv(&circles[i]);
1212
1213 glEnd();
1214
1215 //No auto for circles, explicit types to have const Double_t * const, not Duble_t * const.
1216 for (UInt_t i = 0; i < nColors - 1; ++i) {
1217 const Double_t * const inner = &circles[i * nSlices * 2];
1218 const auto innerRGBA = rgba + i * 4;
1219 const auto outerRGBA = rgba + (i + 1) * 4;
1220 const Double_t * const outer = &circles[(i + 1) * nSlices * 2];
1221
1222 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, innerRGBA, outer, outerRGBA);
1223 }
1224
1225 //Probably degenerated strip.
1226 {
1227 const Double_t * const inner = &circles[nSlices * (nColors - 1) * 2];
1228 const auto solidRGBA = rgba + (nColors - 1) * 4;
1229 const Double_t * const outer = &circles[nSlices * nColors * 2];
1230
1231 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, solidRGBA, outer, solidRGBA);
1232 }
1233
1234 if (solidFillAfter) {
1235 const Double_t * const inner = &circles[nSlices * nColors * 2];
1236 const auto solidRGBA = rgba + (nColors - 1) * 4;
1237 const Double_t * const outer = &circles[nSlices * (nColors + 1) * 2];
1238
1239 Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, solidRGBA, outer, solidRGBA);
1240 }
1241
1244}
1245
1246////////////////////////////////////////////////////////////////////////////////
1247
1249 const Double_t *x, const Double_t *y)
1250{
1251 assert(grad != nullptr && "DrawGradient, parameter 'grad' is null");
1252 assert(n > 2 && "DrawGradient, invalid number of points");
1253 assert(x != nullptr && "DrawGradient, parameter 'x' is null");
1254 assert(y != nullptr && "DrawGradient, parameter 'y' is null");
1255
1256 //Now we fill the whole scene with one big rectangle
1257 //(group of rectangles) with a gradient fill using
1258 //stencil test.
1259
1260 //Find a bounding rect.
1261 const auto &bbox = Rgl::Pad::FindBoundingRect(n, x, y);
1262 //TODO: check the bbox??
1263
1264 //For the gradient fill we switch into the
1265 //pixel coordinates.
1268
1269 //A new ortho projection:
1270 glMatrixMode(GL_PROJECTION);
1271 glLoadIdentity();
1272
1273 const Double_t pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
1274 const Double_t pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
1275 glOrtho(0., pixelW, 0., pixelH, -10., 10.);
1276
1277 //A new modelview:
1278 glMatrixMode(GL_MODELVIEW);
1279 glLoadIdentity();
1280 //
1281 TColorGradient::Point start = grad->GetStart();
1282 TColorGradient::Point end = grad->GetEnd();
1283
1284 //Change gradient coordinates from 'NDC' to pad coords:
1286 {
1287 const Double_t w = gPad->GetX2() - gPad->GetX1();
1288 const Double_t h = gPad->GetY2() - gPad->GetY1();
1289
1290 start.fX = start.fX * w;
1291 start.fY = start.fY * h;
1292 end.fX = end.fX * w;
1293 end.fY = end.fY * h;
1294 } else {
1295 start.fX = start.fX * bbox.fWidth + bbox.fXMin;
1296 start.fY = start.fY * bbox.fHeight + bbox.fYMin;
1297 end.fX = end.fX * bbox.fWidth + bbox.fXMin;
1298 end.fY = end.fY * bbox.fHeight + bbox.fYMin;
1299 }
1300
1301 //TODO: with a radial fill we'll have to extract the code
1302 // below into the separate function/and have additional function
1303 // for a radial gradient.
1304 //Now from pad to pixels:
1305 start.fX = gPad->XtoPixel(start.fX);
1306 start.fY = pixelH - gPad->YtoPixel(start.fY);
1307 end.fX = gPad->XtoPixel(end.fX);
1308 end.fY = pixelH - gPad->YtoPixel(end.fY);
1309 const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
1310 const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
1311 const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
1312 const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
1313 //
1314
1315 //TODO: check all calculations!
1316
1317 //Get the longest distance from the start point to the bounding box vertices:
1318 const Double_t maxDistX = TMath::Max(TMath::Abs(start.fX - xMin), TMath::Abs(start.fX - xMax));
1319 const Double_t maxDistY = TMath::Max(TMath::Abs(start.fY - yMin), TMath::Abs(start.fY - yMax));
1320
1321 const Double_t startEndLength = TMath::Sqrt((end.fX - start.fX) * (end.fX - start.fX) +
1322 (end.fY - start.fY) * (end.fY - start.fY));
1323 const Double_t h = TMath::Max(TMath::Sqrt(maxDistX * maxDistX + maxDistY * maxDistY),
1324 startEndLength);
1325
1326 //Boxes with a gradients to emulate gradient fill with many colors:
1327 const Double_t * const colorPositions = grad->GetColorPositions();
1328 std::vector<Double_t> gradBoxes(grad->GetNumberOfSteps() + 2);
1329 gradBoxes[0] = start.fY - h;
1330 for (unsigned i = 1; i <= grad->GetNumberOfSteps(); ++i)
1331 gradBoxes[i] = startEndLength * colorPositions[i - 1] + start.fY;
1332
1333 gradBoxes[grad->GetNumberOfSteps() + 1] = start.fY + h;
1334
1335 //Rotation angle - gradient's axis:
1336 Double_t angle = TMath::ACos((startEndLength * (end.fY - start.fY)) /
1337 (startEndLength * startEndLength)) * TMath::RadToDeg();
1338 if (end.fX > start.fX)
1339 angle *= -1;
1340
1341 glTranslated(start.fX, start.fY, 0.);
1342 glRotated(angle, 0., 0., 1.);
1343 glTranslated(-start.fX, -start.fY, 0.);
1344 //
1345 const Double_t * const rgba = grad->GetColors();
1346
1347 const unsigned nEdges = gradBoxes.size();
1348 const unsigned nColors = grad->GetNumberOfSteps();
1349 const Double_t xLeft = start.fX - h, xRight = start.fX + h;
1350
1351 const TGLEnableGuard alphaGuard(GL_BLEND);
1352 //TODO?
1353 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1354
1355 Rgl::DrawBoxWithGradientFill(gradBoxes[0], gradBoxes[1], xLeft, xRight, rgba, rgba);
1356 Rgl::DrawBoxWithGradientFill(gradBoxes[nEdges - 2], gradBoxes[nEdges - 1], xLeft, xRight,
1357 rgba + (nColors - 1) * 4, rgba + (nColors - 1) * 4);
1358
1359 for (unsigned i = 1; i < nEdges - 2; ++i)
1360 Rgl::DrawBoxWithGradientFill(gradBoxes[i], gradBoxes[i + 1], xLeft,
1361 xRight, rgba + (i - 1) * 4, rgba + i * 4);
1362
1365}
1366
1367////////////////////////////////////////////////////////////////////////////////
1368
1370{
1371 assert(n > 2 && "DrawTesselation, invalid number of points");
1372 assert(x != nullptr && "DrawTesselation, parameter 'x' is null");
1373 assert(y != nullptr && "DrawTesselation, parameter 'y' is null");
1374
1375 //Data for a tesselator:
1376 fVs.resize(n * 3);
1377
1378 for (Int_t i = 0; i < n; ++i) {
1379 fVs[i * 3] = x[i];
1380 fVs[i * 3 + 1] = y[i];
1381 fVs[i * 3 + 2] = 0.;
1382 }
1383
1384 //TODO: A very primitive way to tesselate - check what
1385 //kind of polygons we can really have from TPad/TCanvas.
1386 GLUtesselator *t = (GLUtesselator *)fTess.GetTess();
1387 gluBeginPolygon(t);
1388 gluNextContour(t, (GLenum)GLU_UNKNOWN);
1389
1390 for (Int_t i = 0; i < n; ++i)
1391 gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
1392
1393 gluEndPolygon(t);
1394}
1395
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
char * device
short Color_t
Color number (short)
Definition RtypesCore.h:100
unsigned char UChar_t
Unsigned Character 1 byte (unsigned char)
Definition RtypesCore.h:53
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
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:30
virtual UInt_t * GetArgbArray()
Definition TImage.h:255
virtual UInt_t GetWidth() const
Definition TImage.h:243
virtual Bool_t IsValid() const
Definition TImage.h:247
virtual UInt_t GetHeight() const
Definition TImage.h:244
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