Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TPadPainter.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Olivier Couet, Timur Pocheptsov (vertex merge) 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 <algorithm>
13#include <limits>
14#include <memory>
15#include <vector>
16
17#include "TPadPainter.h"
18#include "TVirtualX.h"
19#include "TSystem.h"
20#include "TCanvas.h"
21#include "TPoint.h"
22#include "TError.h"
23#include "TImage.h"
24#include "TROOT.h"
25#include "TMath.h"
26#include "TPad.h"
27
28namespace {
29
30//Typedef is fine, but let's pretend we look cool and modern:
31using size_type = std::vector<TPoint>::size_type;
32
33template<typename T>
34void ConvertPoints(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys,
35 std::vector<TPoint> &dst, Bool_t absCoord = kFALSE);
36inline
37void MergePointsX(std::vector<TPoint> &points, unsigned nMerged, SCoord_t yMin,
38 SCoord_t yMax, SCoord_t yLast);
39
40inline
41size_type MergePointsInplaceY(std::vector<TPoint> &dst, size_type nMerged, SCoord_t xMin,
42 SCoord_t xMax, SCoord_t xLast, size_type first);
43
44template<typename T>
45void ConvertPointsAndMergePassX(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y,
46 std::vector<TPoint> &dst);
47
48void ConvertPointsAndMergeInplacePassY(std::vector<TPoint> &dst);
49
50template<class T>
51void DrawFillAreaAux(TVirtualPad *pad, WinContext_t cont, Bool_t absCoord, Int_t nPoints, const T *xs, const T *ys, Bool_t add_first_point);
52
53template<typename T>
54void DrawPolyLineAux(TVirtualPad *pad, WinContext_t cont, Bool_t absCoord, unsigned nPoints, const T *xs, const T *ys);
55
56template<class T>
57void DrawPolyMarkerAux(TVirtualPad *pad, WinContext_t cont, Bool_t absCoord, unsigned nPoints, const T *xs, const T *ys);
58
59
60}
61
62
63/** \class TPadPainter
64\ingroup gpad
65
66Implement TVirtualPadPainter which abstracts painting operations.
67*/
68
69////////////////////////////////////////////////////////////////////////////////
70///Empty ctor. We need it only because of explicit copy ctor.
71
75
76/*
77Line/fill/etc. attributes can be set inside TPad, but not only where:
78many of them are set by base sub-objects of 2d primitives
79(2d primitives usually inherit TAttLine or TAttFill etc.). And these sub-objects
80call gVirtualX->SetLineWidth ... etc. So, if I save some attributes in my painter,
81it will be mess - at any moment I do not know, where to take line attribute - from
82gVirtualX or from my own member. So! All attributed, _ALL_ go to/from gVirtualX.
83*/
84
85
86////////////////////////////////////////////////////////////////////////////////
87/// Delegate to gVirtualX.
88
93
94////////////////////////////////////////////////////////////////////////////////
95/// Delegate to gVirtualX.
96
98{
99 return gVirtualX->GetTextMagnitude();
100}
101
102////////////////////////////////////////////////////////////////////////////////
103/// Create a gVirtualX Pixmap.
104
106{
107 return gVirtualX->OpenPixmap(Int_t(w), Int_t(h));
108}
109
110////////////////////////////////////////////////////////////////////////////////
111/// Resize a gVirtualX Pixmap.
112
114{
115 return gVirtualX->ResizePixmap(device, w, h);
116}
117
118////////////////////////////////////////////////////////////////////////////////
119/// Returns true when X11 backend is used
120
122{
123 return gVirtualX->InheritsFrom("TGX11");
124}
125
126////////////////////////////////////////////////////////////////////////////////
127/// Returns true when cocoa backend is used
128
130{
131 return gVirtualX->InheritsFrom("TGCocoa");
132}
133
134////////////////////////////////////////////////////////////////////////////////
135/// Returns true if transparent colors are supported
136
138{
139 return gVirtualX->InheritsFrom("TGQuartz");
140}
141
142////////////////////////////////////////////////////////////////////////////////
143/// Clear the current gVirtualX window - calling gVirtualX->ClearWindowW
144
146{
147 if (fWinContext)
148 gVirtualX->ClearWindowW(fWinContext);
149}
150
151////////////////////////////////////////////////////////////////////////////////
152/// Clear specified window - calling gVirtualX->ClearWindowW
153
155{
156 auto ctxt = gVirtualX->GetWindowContext(device);
157 if (ctxt)
158 gVirtualX->ClearWindowW(ctxt);
159}
160
161////////////////////////////////////////////////////////////////////////////////
162/// Copy a gVirtualX pixmap.
163
165{
166 gVirtualX->CopyPixmapW(fWinContext, device, px, py);
167}
168
169////////////////////////////////////////////////////////////////////////////////
170/// Close the current gVirtualX pixmap.
171
173{
174 gVirtualX->SelectWindow(device);
175 gVirtualX->ClosePixmap();
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// Select the window in which the graphics will go.
181
183{
184 gVirtualX->SelectWindow(device);
185 fWinContext = gVirtualX->GetWindowContext(device);
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Call low-level update of selected drawable, redirect to gVirtualX.
190
192{
193 gVirtualX->UpdateWindowW(fWinContext, mode);
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Set drawing mode for specified device
198
200{
201 gVirtualX->SetDrawModeW(gVirtualX->GetWindowContext(device), (TVirtualX::EDrawMode) mode);
202}
203
204////////////////////////////////////////////////////////////////////////////////
205/// Set double buffer mode for specified device
206
208{
209 // important flag - when disabled canvas pixmap used directly
210 // so one need to use absolute coordinates
212
213 gVirtualX->SetDoubleBuffer(device, mode);
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Return true if TTF font can be used
218
220{
221 return gVirtualX->HasTTFonts();
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Draw image on the gVirtualX window
226
228{
229 Window_t wid = (Window_t)gVirtualX->GetWindowID(fPad->GetPixmapID());
230 // use old API to draw image on gVirtualX window
231 img->PaintImage(wid, x, y, 0, 0, 0, 0, flags ? "" : "opaque");
232}
233
234////////////////////////////////////////////////////////////////////////////////
235///Noop, for non-gl pad TASImage calls gVirtualX->CopyArea.
236
237void TPadPainter::DrawPixels(const unsigned char * /*pixelData*/, UInt_t /*width*/, UInt_t /*height*/,
238 Int_t /*dstX*/, Int_t /*dstY*/, Bool_t /*enableAlphaBlending*/)
239{
240}
241
242////////////////////////////////////////////////////////////////////////////////
243/// Set fill attributes
244
246{
248
250
251 gVirtualX->SetAttFill(fWinContext, fill);
252}
253
254////////////////////////////////////////////////////////////////////////////////
255/// Set line attributes
256
258{
260
261 gVirtualX->SetAttLine(fWinContext, att);
262}
263
264////////////////////////////////////////////////////////////////////////////////
265/// Set marker attributes
266
268{
270
271 gVirtualX->SetAttMarker(fWinContext, att);
272}
273
274////////////////////////////////////////////////////////////////////////////////
275/// Set text attributes
276
278{
280
281 // TODO: in ROOT7 move text size handling directly to correspondent PS engine
282 // One not need to recalculate text size many time back and forth
283
284 if (!fPad)
285 Fatal("SetAttText", "Pad not specified");
286
287 TAttText attm(att);
289
290 gVirtualX->SetAttText(fWinContext, attm);
291}
292
293////////////////////////////////////////////////////////////////////////////////
294/// Paint a simple line.
295
297{
298 if (fAttLine.GetLineWidth() <= 0)
299 return;
300
301 const Int_t px1 = fDoubleBuffer ? gPad->XtoPixel(x1) : gPad->XtoAbsPixel(x1);
302 const Int_t px2 = fDoubleBuffer ? gPad->XtoPixel(x2) : gPad->XtoAbsPixel(x2);
303 const Int_t py1 = fDoubleBuffer ? gPad->YtoPixel(y1) : gPad->YtoAbsPixel(y1);
304 const Int_t py2 = fDoubleBuffer ? gPad->YtoPixel(y2) : gPad->YtoAbsPixel(y2);
305 gVirtualX->DrawLineW(fWinContext, px1, py1, px2, py2);
306}
307
308
309////////////////////////////////////////////////////////////////////////////////
310/// Paint a simple line in normalized coordinates.
311
313{
314 if (fAttLine.GetLineWidth() <= 0)
315 return;
316
317 const Int_t px1 = fDoubleBuffer ? gPad->UtoPixel(u1) : gPad->UtoAbsPixel(u1);
318 const Int_t py1 = fDoubleBuffer ? gPad->VtoPixel(v1) : gPad->VtoAbsPixel(v1);
319 const Int_t px2 = fDoubleBuffer ? gPad->UtoPixel(u2) : gPad->UtoAbsPixel(u2);
320 const Int_t py2 = fDoubleBuffer ? gPad->VtoPixel(v2) : gPad->VtoAbsPixel(v2);
321 gVirtualX->DrawLineW(fWinContext, px1, py1, px2, py2);
322}
323
324
325////////////////////////////////////////////////////////////////////////////////
326/// Paint a simple box.
327
329{
331 return;
332
334 return;
335
336 Int_t px1 = fDoubleBuffer ? gPad->XtoPixel(x1) : gPad->XtoAbsPixel(x1);
337 Int_t px2 = fDoubleBuffer ? gPad->XtoPixel(x2) : gPad->XtoAbsPixel(x2);
338 Int_t py1 = fDoubleBuffer ? gPad->YtoPixel(y1) : gPad->YtoAbsPixel(y1);
339 Int_t py2 = fDoubleBuffer ? gPad->YtoPixel(y2) : gPad->YtoAbsPixel(y2);
340
341 // Box width must be at least one pixel (WTF is this code???)
342 if (TMath::Abs(px2 - px1) < 1)
343 px2 = px1 + 1;
344 if (TMath::Abs(py1 - py2) < 1)
345 py1 = py2 + 1;
346
347 gVirtualX->DrawBoxW(fWinContext, px1, py1, px2, py2, (TVirtualX::EBoxMode)mode);
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Paint filled area.
352
353void TPadPainter::DrawFillArea(Int_t nPoints, const Double_t *xs, const Double_t *ys)
354{
355 if (nPoints < 3) {
356 ::Error("TPadPainter::DrawFillArea", "invalid number of points %d", nPoints);
357 return;
358 }
359
360 // if fully transparent, add first point to draw line
361 DrawFillAreaAux(gPad, fWinContext, !fDoubleBuffer, nPoints, xs, ys, fFullyTransparent);
362}
363
364
365////////////////////////////////////////////////////////////////////////////////
366/// Paint filled area.
367
368void TPadPainter::DrawFillArea(Int_t nPoints, const Float_t *xs, const Float_t *ys)
369{
370 if (nPoints < 3) {
371 ::Error("TPadPainter::DrawFillArea", "invalid number of points %d", nPoints);
372 return;
373 }
374
375 // if fully transparent, add first point to draw line
376 DrawFillAreaAux(gPad, fWinContext, !fDoubleBuffer, nPoints, xs, ys, fFullyTransparent);
377}
378
379////////////////////////////////////////////////////////////////////////////////
380/// Paint Polyline.
381
383{
384 if (fAttLine.GetLineWidth() <= 0)
385 return;
386
387 if (n < 2) {
388 ::Error("TPadPainter::DrawPolyLine", "invalid number of points");
389 return;
390 }
391
392 DrawPolyLineAux(gPad, fWinContext, !fDoubleBuffer, n, xs, ys);
393}
394
395
396////////////////////////////////////////////////////////////////////////////////
397/// Paint polyline.
398
400{
401 if (fAttLine.GetLineWidth() <= 0)
402 return;
403
404 if (n < 2) {
405 ::Error("TPadPainter::DrawPolyLine", "invalid number of points");
406 return;
407 }
408
409 DrawPolyLineAux(gPad, fWinContext, !fDoubleBuffer, n, xs, ys);
410}
411
412
413////////////////////////////////////////////////////////////////////////////////
414/// Paint polyline in normalized coordinates.
415
417{
418 if (fAttLine.GetLineWidth() <= 0)
419 return;
420
421 if (n < 2) {
422 ::Error("TPadPainter::DrawPolyLineNDC", "invalid number of points %d", n);
423 return;
424 }
425
426 std::vector<TPoint> xy(n);
427
428 for (Int_t i = 0; i < n; ++i) {
429 xy[i].fX = (SCoord_t)gPad->UtoPixel(u[i]);
430 xy[i].fY = (SCoord_t)gPad->VtoPixel(v[i]);
431 }
432
433 gVirtualX->DrawPolyLineW(fWinContext, n, &xy[0]);
434}
435
436////////////////////////////////////////////////////////////////////////////////
437/// Paint N segments on the pad
438
440{
441 if (fAttLine.GetLineWidth() <= 0)
442 return;
443
444 if (n < 1) {
445 ::Error("TPadPainter::DrawSegments", "invalid number of segments %d", n);
446 return;
447 }
448
449 std::vector<TPoint> xy(n*2);
450 Int_t cnt = 0;
451 for (Int_t i = 0; i < n*2; ++i) {
452 if ((i % 2 == 0) && (x[i] == x[i+1]) && (y[i] == y[i+1])) {
453 // exclude empty segment
454 i++;
455 continue;
456 }
457
458 xy[cnt].fX = (SCoord_t)gPad->XtoPixel(x[i]);
459 xy[cnt].fY = (SCoord_t)gPad->YtoPixel(y[i]);
460 cnt++;
461 }
462
463 if (cnt > 1)
464 gVirtualX->DrawLinesSegmentsW(fWinContext, cnt/2, &xy[0]);
465}
466
467////////////////////////////////////////////////////////////////////////////////
468/// Paint N segments in normalized coordinates on the pad
469
471{
472 if (fAttLine.GetLineWidth() <= 0)
473 return;
474
475 if (n < 1) {
476 ::Error("TPadPainter::DrawSegmentsNDC", "invalid number of segments %d", n);
477 return;
478 }
479
480 std::vector<TPoint> xy(n*2);
481 Int_t cnt = 0;
482 for (Int_t i = 0; i < n*2; ++i) {
483 if ((i % 2 == 0) && (u[i] == u[i+1]) && (v[i] == v[i+1])) {
484 // exclude empty segment
485 i++;
486 continue;
487 }
488
489 xy[cnt].fX = (SCoord_t)gPad->UtoPixel(u[i]);
490 xy[cnt].fY = (SCoord_t)gPad->VtoPixel(v[i]);
491 cnt++;
492 }
493
494 if (cnt > 1)
495 gVirtualX->DrawLinesSegmentsW(fWinContext, cnt/2, &xy[0]);
496}
497
498
499
500////////////////////////////////////////////////////////////////////////////////
501/// Paint polymarker.
502
504{
505 if (n < 1) {
506 ::Error("TPadPainter::DrawPolyMarker", "invalid number of points %d", n);
507 return;
508 }
509
510 DrawPolyMarkerAux(gPad, fWinContext, !fDoubleBuffer, n, x, y);
511}
512
513////////////////////////////////////////////////////////////////////////////////
514/// Paint polymarker.
515
517{
518 if (n < 1) {
519 ::Error("TPadPainter::DrawPolyMarker", "invalid number of points %d", n);
520 return;
521 }
522
523 DrawPolyMarkerAux(gPad, fWinContext, !fDoubleBuffer, n, x, y);
524}
525
526////////////////////////////////////////////////////////////////////////////////
527/// Paint TTF glyps on virtualx device
528
533
534////////////////////////////////////////////////////////////////////////////////
535/// Helper method to check if TImage is present in list of primitives
536
538{
539 TIter next(pad->GetListOfPrimitives());
540
541 while (auto obj = next()) {
542 if (obj->InheritsFrom(TImage::Class()))
543 return kTRUE;
544 if (auto subpad = dynamic_cast<TPad *>(obj))
545 if (ContainsTImage(subpad))
546 return kTRUE;
547 }
548 return kFALSE;
549}
550
551////////////////////////////////////////////////////////////////////////////////
552/// Save the image displayed in the canvas pointed by "pad" into a binary file.
553
555{
556 // for X11 and Winows there is special GIF, which works only with maximal 256-colors
557 // Do not try to use it for pads with TImage inside - it most probably fails
558 if ((type == TImage::kGif) && pad && !IsCocoa() && !ContainsTImage(pad)) {
559 gVirtualX->Update(1);
560 gSystem->Sleep(30);
562
563 Int_t wid = (pad == pad->GetCanvas()) ? pad->GetCanvasID() : pad->GetPixmapID();
564 auto ctxt = gVirtualX->GetWindowContext(wid);
565 // TODO: GIF image is special, if fail - try use TImage functionality
566 Int_t res = gVirtualX->WriteGIFW(ctxt, fileName);
567 if (res > 0)
568 return kSaveOk;
569 }
570
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// Fill image object with the pixel data from the pad
576/// Implements special handling for X11 where ASImage has native implementation
577
579{
580 if (!image || !pad)
581 return kFALSE;
582
583 gVirtualX->Update(1);
584 if (!gThreadXAR) {
585 gSystem->Sleep(10);
587 gSystem->Sleep(10);
589 }
590
591 auto width = pad->GetPadWidth();
592 auto height = pad->GetPadHeight();
593
594 Int_t wid = (pad == pad->GetCanvas()) ? pad->GetCanvasID() : pad->GetPixmapID();
595 gVirtualX->SelectWindow(wid);
596
597 Window_t wd = (Window_t)gVirtualX->GetCurrentWindow();
598
599 if (IsX11()) { //use built-in optimized version
600 image->FromX11Window(wd, 0, 0, width, height);
601 } else {
602 unsigned char *bits = gVirtualX->GetColorBits(wd, 0, 0, width, height);
603 if (!bits)
604 return kFALSE;
605
606 image->FromBitmap(bits, width, height);
607 delete [] bits;
608 }
609
610 return image->IsValid();
611}
612
613
614//Aux. private functions.
615namespace {
616
617////////////////////////////////////////////////////////////////////////////////
618///I'm using 'pad' pointer to get rid of this damned gPad.
619///Unfortunately, TPadPainter itself still has to use it.
620///But at least this code does not have to be fixed.
621
622template<typename T>
623void ConvertPoints(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y,
624 std::vector<TPoint> &dst, Bool_t absCoord)
625{
626 if (!nPoints)
627 return;
628
629 dst.resize(nPoints);
630
631 if (absCoord) {
632 for (unsigned i = 0; i < nPoints; ++i) {
633 dst[i].fX = (SCoord_t) pad->XtoAbsPixel(x[i]);
634 dst[i].fY = (SCoord_t) pad->YtoAbsPixel(y[i]);
635 }
636 } else {
637 for (unsigned i = 0; i < nPoints; ++i) {
638 dst[i].fX = (SCoord_t) pad->XtoPixel(x[i]);
639 dst[i].fY = (SCoord_t) pad->YtoPixel(y[i]);
640 }
641 }
642}
643
644////////////////////////////////////////////////////////////////////////////////
645
646inline void MergePointsX(std::vector<TPoint> &points, unsigned nMerged, SCoord_t yMin,
647 SCoord_t yMax, SCoord_t yLast)
648{
649 const auto firstPointX = points.back().fX;
650 const auto firstPointY = points.back().fY;
651
652 if (nMerged == 2) {
653 points.push_back(TPoint(firstPointX, yLast));//We have not merge anything.
654 } else if (nMerged == 3) {
655 yMin == firstPointY ? points.push_back(TPoint(firstPointX, yMax)) :
656 points.push_back(TPoint(firstPointX, yMin));
657 points.push_back(TPoint(firstPointX, yLast));
658 } else {
659 points.push_back(TPoint(firstPointX, yMin));
660 points.push_back(TPoint(firstPointX, yMax));
661 points.push_back(TPoint(firstPointX, yLast));
662 }
663}
664
665////////////////////////////////////////////////////////////////////////////////
666///Indices below are _valid_.
667
668inline size_type MergePointsInplaceY(std::vector<TPoint> &dst, size_type nMerged, SCoord_t xMin,
669 SCoord_t xMax, SCoord_t xLast, size_type first)
670{
671 const TPoint &firstPoint = dst[first];//This point is never updated.
672
673 if (nMerged == 2) {
674 dst[first + 1].fX = xLast;
675 dst[first + 1].fY = firstPoint.fY;
676 } else if (nMerged == 3) {
677 dst[first + 1].fX = xMin == firstPoint.fX ? xMax : xMin;
678 dst[first + 1].fY = firstPoint.fY;
679 dst[first + 2].fX = xLast;
680 dst[first + 2].fY = firstPoint.fY;
681 } else {
682 dst[first + 1].fX = xMin;
683 dst[first + 1].fY = firstPoint.fY;
684 dst[first + 2].fX = xMax;
685 dst[first + 2].fY = firstPoint.fY;
686 dst[first + 3].fX = xLast;
687 dst[first + 3].fY = firstPoint.fY;
688 nMerged = 4;//Adjust the shift.
689 }
690
691 return nMerged;
692}
693
694////////////////////////////////////////////////////////////////////////////////
695/// I'm using 'pad' pointer to get rid of this damned gPad.
696/// Unfortunately, TPadPainter itself still has to use it.
697/// But at least this code does not have to be fixed.
698
699template<typename T>
700void ConvertPointsAndMergePassX(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y,
701 std::vector<TPoint> &dst)
702{
703 //The "first" pass along X axis.
704 TPoint currentPoint;
705 SCoord_t yMin = 0, yMax = 0, yLast = 0;
706 unsigned nMerged = 0;
707
708 //The first pass along X.
709 for (unsigned i = 0; i < nPoints;) {
710 currentPoint.fX = (SCoord_t)pad->XtoPixel(x[i]);
711 currentPoint.fY = (SCoord_t)pad->YtoPixel(y[i]);
712
713 yMin = currentPoint.fY;
714 yMax = yMin;
715
716 dst.push_back(currentPoint);
717 bool merged = false;
718 nMerged = 1;
719
720 for (unsigned j = i + 1; j < nPoints; ++j) {
721 const SCoord_t newX = pad->XtoPixel(x[j]);
722
723 if (newX == currentPoint.fX) {
724 yLast = pad->YtoPixel(y[j]);
725 yMin = TMath::Min(yMin, yLast);
726 yMax = TMath::Max(yMax, yLast);//We continue.
727 ++nMerged;
728 } else {
729 if (nMerged > 1)
730 MergePointsX(dst, nMerged, yMin, yMax, yLast);
731 merged = true;
732 break;
733 }
734 }
735
736 if (!merged && nMerged > 1)
737 MergePointsX(dst, nMerged, yMin, yMax, yLast);
738
739 i += nMerged;
740 }
741}
742
743////////////////////////////////////////////////////////////////////////////////
744/// This pass is a bit more complicated, since we have to 'compact' in-place.
745
746void ConvertPointsAndMergeInplacePassY(std::vector<TPoint> &dst)
747{
748 size_type i = 0;
749 for (size_type j = 1, nPoints = dst.size(); i < nPoints;) {
750 //i is always less than j, so i is always valid here.
751 const TPoint &currentPoint = dst[i];
752
753 SCoord_t xMin = currentPoint.fX;
754 SCoord_t xMax = xMin;
755 SCoord_t xLast = 0;
756
757 bool merged = false;
758 size_type nMerged = 1;
759
760 for (; j < nPoints; ++j) {
761 const TPoint &nextPoint = dst[j];
762
763 if (nextPoint.fY == currentPoint.fY) {
764 xLast = nextPoint.fX;
765 xMin = TMath::Min(xMin, xLast);
766 xMax = TMath::Max(xMax, xLast);
767 ++nMerged;//and we continue ...
768 } else {
769 if (nMerged > 1)
770 nMerged = MergePointsInplaceY(dst, nMerged, xMin, xMax, xLast, i);
771 merged = true;
772 break;
773 }
774 }
775
776 if (!merged && nMerged > 1)
777 nMerged = MergePointsInplaceY(dst, nMerged, xMin, xMax, xLast, i);
778
779 i += nMerged;
780
781 if (j < nPoints) {
782 dst[i] = dst[j];
783 ++j;
784 } else
785 break;
786 }
787
788 dst.resize(i);
789}
790
791////////////////////////////////////////////////////////////////////////////////
792/// This is a quite simple algorithm, using the fact, that after conversion many
793/// subsequent vertices can have the same 'x' or 'y' coordinate and this part of
794/// a polygon will look like a line on the screen.
795
796template<typename T>
797void ConvertPointsAndMerge(TVirtualPad *pad, unsigned threshold, unsigned nPoints, const T *x,
798 const T *y, std::vector<TPoint> &dst)
799{
800 //I'm using 'pad' pointer to get rid of this damned gPad.
801 //Unfortunately, TPadPainter itself still has to use it.
802 //But at least this code does not have to be fixed.
803
804 if (!nPoints)
805 return;
806
807 dst.clear();
808 dst.reserve(threshold);
809
810 ConvertPointsAndMergePassX(pad, nPoints, x, y, dst);
811
812 if (dst.size() < threshold)
813 return;
814
815 ConvertPointsAndMergeInplacePassY(dst);
816}
817
818////////////////////////////////////////////////////////////////////////////////
819
820template<class T>
821void DrawFillAreaAux(TVirtualPad *pad, WinContext_t cont, Bool_t absCoord, Int_t nPoints, const T *xs, const T *ys, Bool_t add_first_point)
822{
823 std::vector<TPoint> xy;
824
825 const Int_t threshold = Int_t(TMath::Min(pad->GetWw() * pad->GetAbsWNDC(),
826 pad->GetWh() * pad->GetAbsHNDC())) * 2;
827
828 if (threshold <= 0) {
829 //Ooops, pad is invisible or something really bad and stupid happened.
830 ::Error("DrawFillAreaAux", "invalid pad's geometry");
831 return;
832 }
833
834 if (absCoord || (nPoints < threshold))
835 ConvertPoints(pad, nPoints, xs, ys, xy, absCoord);
836 else
837 ConvertPointsAndMerge(pad, threshold, nPoints, xs, ys, xy);
838
839 //We close the 'polygon' so it can be rendered as a polyline by gVirtualX.
840 if (add_first_point)
841 xy.push_back(xy.front());
842
843 if (xy.size() > 2)
844 gVirtualX->DrawFillAreaW(cont, xy.size(), xy.data());
845}
846
847////////////////////////////////////////////////////////////////////////////////
848
849template <typename T>
850void DrawPolyLineAux(TVirtualPad *pad, WinContext_t cont, Bool_t absCoord, unsigned nPoints, const T *xs, const T *ys)
851{
852 std::vector<TPoint> xy;
853
854 const UInt_t threshold = TMath::Min(pad->GetPadWidth(), pad->GetPadHeight()) * 2;
855
856 if (threshold == 0) {//Ooops, pad is invisible or something really bad and stupid happened.
857 ::Error("DrawPolyLineAux", "invalid pad's geometry");
858 return;
859 }
860
861 if (absCoord || (nPoints < threshold))
862 ConvertPoints(pad, nPoints, xs, ys, xy, absCoord);
863 else
864 ConvertPointsAndMerge(pad, threshold, nPoints, xs, ys, xy);
865
866 if (xy.size() > 1)
867 gVirtualX->DrawPolyLineW(cont, xy.size(), xy.data());
868}
869
870////////////////////////////////////////////////////////////////////////////////
871
872template<class T>
873void DrawPolyMarkerAux(TVirtualPad *pad, WinContext_t cont, Bool_t absCoord, unsigned nPoints, const T *xs, const T *ys)
874{
875 std::vector<TPoint> xy;
876
877 ConvertPoints(pad, nPoints, xs, ys, xy, absCoord);
878
879 gVirtualX->DrawPolyMarkerW(cont, nPoints, xy.data());
880}
881
882}
Handle_t WinContext_t
Window drawing context.
Definition GuiTypes.h:30
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
#define h(i)
Definition RSha256.hxx:106
double * dst
char * device
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:78
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
short SCoord_t
Screen coordinates (short)
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:267
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
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 TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
Option_t Option_t width
Option_t Option_t TPoint TPoint percent
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint 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 y1
static Bool_t ContainsTImage(const TVirtualPad *pad)
Helper method to check if TImage is present in list of primitives.
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define gPad
R__EXTERN Int_t(* gThreadXAR)(const char *xact, Int_t nb, void **ar, Int_t *iret)
#define gVirtualX
Definition TVirtualX.h:379
Fill Area Attributes class.
Definition TAttFill.h:21
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
Text Attributes class.
Definition TAttText.h:21
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:53
virtual Float_t GetTextSizePixels(TVirtualPad &pad) const
Return the text size in pixels for specified pad.
Definition TAttText.cxx:350
An abstract interface to image processing library.
Definition TImage.h:30
@ kGif
Definition TImage.h:49
virtual void FromX11Window(Window_t, Int_t, Int_t, Int_t, Int_t)
Definition TImage.h:133
virtual Bool_t IsValid() const
Definition TImage.h:250
virtual void FromBitmap(const UChar_t *, UInt_t, UInt_t)
Definition TImage.h:127
static TClass * Class()
virtual void PaintImage(Drawable_t, Int_t, Int_t, Int_t=0, Int_t=0, UInt_t=0, UInt_t=0, Option_t *="")
Definition TImage.h:265
void SetAttFill(const TAttFill &att) override
Set fill attributes.
ESaveImageResult SaveAsImage(TVirtualPad *pad, const char *fileName, Int_t type) const override
Store pad image into the file One should provide FillImageFromPad implementation in the subclass.
void SetAttText(const TAttText &att) override
Set text attributes.
TAttLine fAttLine
current line attributes
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.
WinContext_t fWinContext
TVirtualPad * fPad
TAttFill GetAttFillInternal(Bool_t with_transparency)
Returns fill attributes after modification Checks for special fill styles 4000 .
void DrawSegments(Int_t n, Double_t *x, Double_t *y) override
Paint N segments on the pad.
TPadPainter()
Empty ctor. We need it only because of explicit copy ctor.
void DrawFillArea(Int_t n, const Double_t *x, const Double_t *y) override
Paint filled area.
void SetAttText(const TAttText &att) override
Set text attributes.
void DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height, Int_t dstX, Int_t dstY, Bool_t enableAlphaBlending) override
Noop, for non-gl pad TASImage calls gVirtualX->CopyArea.
void UpdateDrawable(Int_t mode) override
Call low-level update of selected drawable, redirect to gVirtualX.
void CopyDrawable(Int_t device, Int_t px, Int_t py) override
Copy a gVirtualX pixmap.
void SetAttMarker(const TAttMarker &att) override
Set marker attributes.
void DrawTTFglyphs(Int_t x, Int_t y, TTFhandle &ttf, ETextMode mode) override
Paint TTF glyps on virtualx device.
void DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) override
Paint Polyline.
Int_t fDoubleBuffer
Definition TPadPainter.h:27
Int_t ResizeDrawable(Int_t device, UInt_t w, UInt_t h) override
Resize a gVirtualX Pixmap.
Float_t GetTextMagnitude() const override
Delegate to gVirtualX.
Bool_t IsX11() const override
Returns true when X11 backend is used.
Bool_t IsSupportAlpha() const override
Returns true if transparent colors are supported.
void ClearWindow(Int_t device) override
Clear specified window - calling gVirtualX->ClearWindowW.
Int_t CreateDrawable(UInt_t w, UInt_t h) override
Create a gVirtualX Pixmap.
void SetAttFill(const TAttFill &att) override
Set fill attributes.
void DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y) override
Paint polymarker.
void SetOpacity(Int_t percent) override
Delegate to gVirtualX.
Bool_t IsCocoa() const override
Returns true when cocoa backend is used.
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 DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v) override
Paint polyline in normalized coordinates.
Bool_t HasTTFonts() const override
Return true if TTF font can be used.
void SetDrawMode(Int_t device, Int_t mode) override
Set drawing mode for specified device.
void ClearDrawable() override
Clear the current gVirtualX window - calling gVirtualX->ClearWindowW.
void DestroyDrawable(Int_t device) override
Close the current gVirtualX pixmap.
void DrawSegmentsNDC(Int_t n, Double_t *u, Double_t *v) override
Paint N segments in normalized coordinates on the pad.
void SetAttLine(const TAttLine &att) override
Set line attributes.
void SelectDrawable(Int_t device) override
Select the window in which the graphics will go.
void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode) override
Paint a simple box.
void DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) override
Paint a simple line.
ESaveImageResult SaveAsImage(TVirtualPad *pad, const char *fileName, Int_t type) const override
Save the image displayed in the canvas pointed by "pad" into a binary file.
void DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) override
Paint a simple line in normalized coordinates.
void DrawImage(TImage *img, Int_t x, Int_t y, Int_t flags=0) override
Draw image on the gVirtualX window.
void SetDoubleBuffer(Int_t device, Int_t mode) override
Set double buffer mode for specified device.
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
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:440
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:419
Dynamic handle to work with freetype 2 library.
Definition TTFhandle.h:21
virtual void const char * fileName
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:53
virtual Int_t YtoAbsPixel(Double_t y) const =0
virtual TList * GetListOfPrimitives() const =0
virtual Int_t YtoPixel(Double_t y) const =0
virtual UInt_t GetWh() const =0
virtual Int_t XtoAbsPixel(Double_t x) const =0
virtual UInt_t GetPadWidth() const =0
virtual Int_t GetPixmapID() const =0
virtual Double_t GetAbsWNDC() const =0
virtual UInt_t GetPadHeight() const =0
virtual Double_t GetAbsHNDC() const =0
virtual Int_t XtoPixel(Double_t x) const =0
virtual UInt_t GetWw() 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
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122