Logo ROOT   6.14/05
Reference Guide
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 "TCanvas.h"
20 #include "TPoint.h"
21 #include "TError.h"
22 #include "TImage.h"
23 #include "TROOT.h"
24 #include "TMath.h"
25 #include "TPad.h"
26 
27 namespace {
28 
29 //Typedef is fine, but let's pretend we look cool and modern:
30 using size_type = std::vector<TPoint>::size_type;
31 
32 template<typename T>
33 void ConvertPoints(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys,
34  std::vector<TPoint> &dst);
35 inline
36 void MergePointsX(std::vector<TPoint> &points, unsigned nMerged, SCoord_t yMin,
37  SCoord_t yMax, SCoord_t yLast);
38 
39 inline
40 size_type MergePointsInplaceY(std::vector<TPoint> &dst, size_type nMerged, SCoord_t xMin,
41  SCoord_t xMax, SCoord_t xLast, size_type first);
42 
43 template<typename T>
44 void ConvertPointsAndMergePassX(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y,
45  std::vector<TPoint> &dst);
46 
47 void ConvertPointsAndMergeInplacePassY(std::vector<TPoint> &dst);
48 
49 template<class T>
50 void DrawFillAreaAux(TVirtualPad *pad, Int_t nPoints, const T *xs, const T *ys);
51 
52 template<typename T>
53 void DrawPolyLineAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys);
54 
55 template<class T>
56 void DrawPolyMarkerAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys);
57 
58 
59 }
60 
62 
63 /** \class TPadPainter
64 \ingroup gpad
65 
66 Implement TVirtualPadPainter which abstracts painting operations.
67 */
68 
69 ////////////////////////////////////////////////////////////////////////////////
70 ///Empty ctor. We need it only because of explicit copy ctor.
71 
73 {
74 }
75 
76 /*
77 Line/fill/etc. attributes can be set inside TPad, but not only where:
78 many of them are set by base sub-objects of 2d primitives
79 (2d primitives usually inherit TAttLine or TAttFill etc.). And these sub-objects
80 call gVirtualX->SetLineWidth ... etc. So, if I save some attributes in my painter,
81 it will be mess - at any moment I do not know, where to take line attribute - from
82 gVirtualX or from my own member. So! All attributed, _ALL_ go to/from gVirtualX.
83 */
84 
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// Delegate to gVirtualX.
88 
90 {
91  return gVirtualX->GetLineColor();
92 }
93 
94 
95 ////////////////////////////////////////////////////////////////////////////////
96 /// Delegate to gVirtualX.
97 
99 {
100  return gVirtualX->GetLineStyle();
101 }
102 
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Delegate to gVirtualX.
106 
108 {
109  return gVirtualX->GetLineWidth();
110 }
111 
112 
113 ////////////////////////////////////////////////////////////////////////////////
114 /// Delegate to gVirtualX.
115 
117 {
118  gVirtualX->SetLineColor(lcolor);
119 }
120 
121 
122 ////////////////////////////////////////////////////////////////////////////////
123 /// Delegate to gVirtualX.
124 
126 {
127  gVirtualX->SetLineStyle(lstyle);
128 }
129 
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// Delegate to gVirtualX.
133 
135 {
136  gVirtualX->SetLineWidth(lwidth);
137 }
138 
139 
140 ////////////////////////////////////////////////////////////////////////////////
141 /// Delegate to gVirtualX.
142 
144 {
145  return gVirtualX->GetFillColor();
146 }
147 
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Delegate to gVirtualX.
151 
153 {
154  return gVirtualX->GetFillStyle();
155 }
156 
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 /// Delegate to gVirtualX.
160 
162 {
163  //IsTransparent is implemented as inline function in TAttFill.
164  return gVirtualX->IsTransparent();
165 }
166 
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 /// Delegate to gVirtualX.
170 
172 {
173  gVirtualX->SetFillColor(fcolor);
174 }
175 
176 
177 ////////////////////////////////////////////////////////////////////////////////
178 /// Delegate to gVirtualX.
179 
181 {
182  gVirtualX->SetFillStyle(fstyle);
183 }
184 
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 /// Delegate to gVirtualX.
188 
190 {
191  gVirtualX->SetOpacity(percent);
192 }
193 
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Delegate to gVirtualX.
197 
199 {
200  return gVirtualX->GetTextAlign();
201 }
202 
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Delegate to gVirtualX.
206 
208 {
209  return gVirtualX->GetTextAngle();
210 }
211 
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 /// Delegate to gVirtualX.
215 
217 {
218  return gVirtualX->GetTextColor();
219 }
220 
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 /// Delegate to gVirtualX.
224 
226 {
227  return gVirtualX->GetTextFont();
228 }
229 
230 
231 ////////////////////////////////////////////////////////////////////////////////
232 /// Delegate to gVirtualX.
233 
235 {
236  return gVirtualX->GetTextSize();
237 }
238 
239 
240 ////////////////////////////////////////////////////////////////////////////////
241 /// Delegate to gVirtualX.
242 
244 {
245  return gVirtualX->GetTextMagnitude();
246 }
247 
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 /// Delegate to gVirtualX.
251 
253 {
254  gVirtualX->SetTextAlign(align);
255 }
256 
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// Delegate to gVirtualX.
260 
262 {
263  gVirtualX->SetTextAngle(tangle);
264 }
265 
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Delegate to gVirtualX.
269 
271 {
272  gVirtualX->SetTextColor(tcolor);
273 }
274 
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Delegate to gVirtualX.
278 
280 {
281  gVirtualX->SetTextFont(tfont);
282 }
283 
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 /// Delegate to gVirtualX.
287 
289 {
290  gVirtualX->SetTextSize(tsize);
291 }
292 
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 /// Delegate to gVirtualX.
296 
298 {
299  gVirtualX->SetTextSizePixels(npixels);
300 }
301 
302 
303 ////////////////////////////////////////////////////////////////////////////////
304 /// Create a gVirtualX Pixmap.
305 
307 {
308  return gVirtualX->OpenPixmap(Int_t(w), Int_t(h));
309 }
310 
311 
312 ////////////////////////////////////////////////////////////////////////////////
313 /// Clear the current gVirtualX window.
314 
316 {
317  gVirtualX->ClearWindow();
318 }
319 
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Copy a gVirtualX pixmap.
323 
325 {
326  gVirtualX->CopyPixmap(device, px, py);
327 }
328 
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 /// Close the current gVirtualX pixmap.
332 
334 {
335  gVirtualX->SelectWindow(device);
336  gVirtualX->ClosePixmap();
337 }
338 
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// Select the window in which the graphics will go.
342 
344 {
345  gVirtualX->SelectWindow(device);
346 }
347 
348 ////////////////////////////////////////////////////////////////////////////////
349 ///Noop, for non-gl pad TASImage calls gVirtualX->CopyArea.
350 
351 void TPadPainter::DrawPixels(const unsigned char * /*pixelData*/, UInt_t /*width*/, UInt_t /*height*/,
352  Int_t /*dstX*/, Int_t /*dstY*/, Bool_t /*enableAlphaBlending*/)
353 {
354 }
355 
356 
357 ////////////////////////////////////////////////////////////////////////////////
358 /// Paint a simple line.
359 
361 {
362  if (GetLineWidth()<=0) return;
363 
364  const Int_t px1 = gPad->XtoPixel(x1);
365  const Int_t px2 = gPad->XtoPixel(x2);
366  const Int_t py1 = gPad->YtoPixel(y1);
367  const Int_t py2 = gPad->YtoPixel(y2);
368  gVirtualX->DrawLine(px1, py1, px2, py2);
369 }
370 
371 
372 ////////////////////////////////////////////////////////////////////////////////
373 /// Paint a simple line in normalized coordinates.
374 
376 {
377  if (GetLineWidth()<=0) return;
378 
379  const Int_t px1 = gPad->UtoPixel(u1);
380  const Int_t py1 = gPad->VtoPixel(v1);
381  const Int_t px2 = gPad->UtoPixel(u2);
382  const Int_t py2 = gPad->VtoPixel(v2);
383  gVirtualX->DrawLine(px1, py1, px2, py2);
384 }
385 
386 
387 ////////////////////////////////////////////////////////////////////////////////
388 /// Paint a simple box.
389 
391 {
392  if (GetLineWidth()<=0 && mode == TVirtualPadPainter::kHollow) return;
393 
394  Int_t px1 = gPad->XtoPixel(x1);
395  Int_t px2 = gPad->XtoPixel(x2);
396  Int_t py1 = gPad->YtoPixel(y1);
397  Int_t py2 = gPad->YtoPixel(y2);
398 
399  // Box width must be at least one pixel (WTF is this code???)
400  if (TMath::Abs(px2 - px1) < 1)
401  px2 = px1 + 1;
402  if (TMath::Abs(py1 - py2) < 1)
403  py1 = py2 + 1;
404 
405  gVirtualX->DrawBox(px1, py1, px2, py2, (TVirtualX::EBoxMode)mode);
406 }
407 
408 ////////////////////////////////////////////////////////////////////////////////
409 /// Paint filled area.
410 
411 void TPadPainter::DrawFillArea(Int_t nPoints, const Double_t *xs, const Double_t *ys)
412 {
413  if (nPoints < 3) {
414  ::Error("TPadPainter::DrawFillArea", "invalid number of points %d", nPoints);
415  return;
416  }
417 
418  DrawFillAreaAux(gPad, nPoints, xs, ys);
419 }
420 
421 
422 ////////////////////////////////////////////////////////////////////////////////
423 /// Paint filled area.
424 
425 void TPadPainter::DrawFillArea(Int_t nPoints, const Float_t *xs, const Float_t *ys)
426 {
427  if (nPoints < 3) {
428  ::Error("TPadPainter::DrawFillArea", "invalid number of points %d", nPoints);
429  return;
430  }
431 
432  DrawFillAreaAux(gPad, nPoints, xs, ys);
433 }
434 
435 ////////////////////////////////////////////////////////////////////////////////
436 /// Paint Polyline.
437 
438 void TPadPainter::DrawPolyLine(Int_t n, const Double_t *xs, const Double_t *ys)
439 {
440  if (GetLineWidth()<=0) return;
441 
442  if (n < 2) {
443  ::Error("TPadPainter::DrawPolyLine", "invalid number of points");
444  return;
445  }
446 
447  DrawPolyLineAux(gPad, n, xs, ys);
448 }
449 
450 
451 ////////////////////////////////////////////////////////////////////////////////
452 /// Paint polyline.
453 
454 void TPadPainter::DrawPolyLine(Int_t n, const Float_t *xs, const Float_t *ys)
455 {
456  if (GetLineWidth()<=0) return;
457 
458  if (n < 2) {
459  ::Error("TPadPainter::DrawPolyLine", "invalid number of points");
460  return;
461  }
462 
463  DrawPolyLineAux(gPad, n, xs, ys);
464 }
465 
466 
467 ////////////////////////////////////////////////////////////////////////////////
468 /// Paint polyline in normalized coordinates.
469 
471 {
472  if (GetLineWidth()<=0) return;
473 
474  if (n < 2) {
475  ::Error("TPadPainter::DrawPolyLineNDC", "invalid number of points %d", n);
476  return;
477  }
478 
479  std::vector<TPoint> xy(n);
480 
481  for (Int_t i = 0; i < n; ++i) {
482  xy[i].fX = (SCoord_t)gPad->UtoPixel(u[i]);
483  xy[i].fY = (SCoord_t)gPad->VtoPixel(v[i]);
484  }
485 
486  gVirtualX->DrawPolyLine(n, &xy[0]);
487 }
488 
489 
490 ////////////////////////////////////////////////////////////////////////////////
491 /// Paint polymarker.
492 
494 {
495  if (n < 1) {
496  ::Error("TPadPainter::DrawPolyMarker", "invalid number of points %d", n);
497  return;
498  }
499 
500  DrawPolyMarkerAux(gPad, n, x, y);
501 }
502 
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Paint polymarker.
506 
508 {
509  if (n < 1) {
510  ::Error("TPadPainter::DrawPolyMarker", "invalid number of points %d", n);
511  return;
512  }
513 
514  DrawPolyMarkerAux(gPad, n, x, y);
515 }
516 
517 
518 ////////////////////////////////////////////////////////////////////////////////
519 /// Paint text.
520 
522 {
523  const Int_t px = gPad->XtoPixel(x);
524  const Int_t py = gPad->YtoPixel(y);
525  const Double_t angle = GetTextAngle();
526  const Double_t mgn = GetTextMagnitude();
527  gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode);
528 }
529 
530 
531 ////////////////////////////////////////////////////////////////////////////////
532 /// Special version working with wchar_t and required by TMathText.
533 
535 {
536  const Int_t px = gPad->XtoPixel(x);
537  const Int_t py = gPad->YtoPixel(y);
538  const Double_t angle = GetTextAngle();
539  const Double_t mgn = GetTextMagnitude();
540  gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode);
541 }
542 
543 
544 ////////////////////////////////////////////////////////////////////////////////
545 /// Paint text in normalized coordinates.
546 
548 {
549  const Int_t px = gPad->UtoPixel(u);
550  const Int_t py = gPad->VtoPixel(v);
551  const Double_t angle = GetTextAngle();
552  const Double_t mgn = GetTextMagnitude();
553  gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode);
554 }
555 
556 
557 ////////////////////////////////////////////////////////////////////////////////
558 /// Save the image displayed in the canvas pointed by "pad" into a binary file.
559 
560 void TPadPainter::SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const
561 {
562  if (gVirtualX->InheritsFrom("TGCocoa") && !gROOT->IsBatch() &&
563  pad->GetCanvas() && pad->GetCanvas()->GetCanvasID() != -1) {
564 
565  TCanvas * const canvas = pad->GetCanvas();
566  //Force TCanvas::CopyPixmaps.
567  canvas->Flush();
568 
569  const UInt_t w = canvas->GetWw();
570  const UInt_t h = canvas->GetWh();
571 
572  const std::unique_ptr<unsigned char[]>
573  pixelData(gVirtualX->GetColorBits(canvas->GetCanvasID(), 0, 0, w, h));
574 
575  if (pixelData.get()) {
576  const std::unique_ptr<TImage> image(TImage::Create());
577  if (image.get()) {
578  image->DrawRectangle(0, 0, w, h);
579  if (unsigned char *argb = (unsigned char *)image->GetArgbArray()) {
580  //Ohhh.
581  if (sizeof(UInt_t) == 4) {
582  //For sure the data returned from TGCocoa::GetColorBits,
583  //it's 4 * w * h bytes with what TASImage considers to be argb.
584  std::copy(pixelData.get(), pixelData.get() + 4 * w * h, argb);
585  } else {
586  //A bit paranoid, don't you think so?
587  //Will Quartz/TASImage work at all on such a fancy platform? ;)
588  const unsigned shift = std::numeric_limits<unsigned char>::digits;
589  //
590  unsigned *dstPixel = (unsigned *)argb, *end = dstPixel + w * h;
591  const unsigned char *srcPixel = pixelData.get();
592  for (;dstPixel != end; ++dstPixel, srcPixel += 4) {
593  //Looks fishy but should work, trust me :)
594  *dstPixel = srcPixel[0] & (srcPixel[1] << shift) &
595  (srcPixel[2] << 2 * shift) &
596  (srcPixel[3] << 3 * shift);
597  }
598  }
599 
600  image->WriteImage(fileName, (TImage::EImageFileTypes)type);
601  //Success.
602  return;
603  }
604  }
605  }
606  }
607 
608  if (type == TImage::kGif) {
609  gVirtualX->WriteGIF((char*)fileName);
610  } else {
611  const std::unique_ptr<TImage> img(TImage::Create());
612  if (img.get()) {
613  img->FromPad(pad);
614  img->WriteImage(fileName, (TImage::EImageFileTypes)type);
615  }
616  }
617 }
618 
619 
620 ////////////////////////////////////////////////////////////////////////////////
621 /// Paint text in normalized coordinates.
622 
624 {
625  const Int_t px = gPad->UtoPixel(u);
626  const Int_t py = gPad->VtoPixel(v);
627  const Double_t angle = GetTextAngle();
628  const Double_t mgn = GetTextMagnitude();
629  gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode);
630 }
631 
632 //Aux. private functions.
633 namespace {
634 
635 ////////////////////////////////////////////////////////////////////////////////
636 ///I'm using 'pad' pointer to get rid of this damned gPad.
637 ///Unfortunately, TPadPainter itself still has to use it.
638 ///But at least this code does not have to be fixed.
639 
640 template<typename T>
641 void ConvertPoints(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y,
642  std::vector<TPoint> &dst)
643 {
644  if (!nPoints)
645  return;
646 
647  dst.resize(nPoints);
648 
649  for (unsigned i = 0; i < nPoints; ++i) {
650  dst[i].fX = (SCoord_t)pad->XtoPixel(x[i]);
651  dst[i].fY = (SCoord_t)pad->YtoPixel(y[i]);
652  }
653 }
654 
655 ////////////////////////////////////////////////////////////////////////////////
656 
657 inline void MergePointsX(std::vector<TPoint> &points, unsigned nMerged, SCoord_t yMin,
658  SCoord_t yMax, SCoord_t yLast)
659 {
660  const auto firstPointX = points.back().fX;
661  const auto firstPointY = points.back().fY;
662 
663  if (nMerged == 2) {
664  points.push_back(TPoint(firstPointX, yLast));//We have not merge anything.
665  } else if (nMerged == 3) {
666  yMin == firstPointY ? points.push_back(TPoint(firstPointX, yMax)) :
667  points.push_back(TPoint(firstPointX, yMin));
668  points.push_back(TPoint(firstPointX, yLast));
669  } else {
670  points.push_back(TPoint(firstPointX, yMin));
671  points.push_back(TPoint(firstPointX, yMax));
672  points.push_back(TPoint(firstPointX, yLast));
673  }
674 }
675 
676 ////////////////////////////////////////////////////////////////////////////////
677 ///Indices below are _valid_.
678 
679 inline size_type MergePointsInplaceY(std::vector<TPoint> &dst, size_type nMerged, SCoord_t xMin,
680  SCoord_t xMax, SCoord_t xLast, size_type first)
681 {
682  const TPoint &firstPoint = dst[first];//This point is never updated.
683 
684  if (nMerged == 2) {
685  dst[first + 1].fX = xLast;
686  dst[first + 1].fY = firstPoint.fY;
687  } else if (nMerged == 3) {
688  dst[first + 1].fX = xMin == firstPoint.fX ? xMax : xMin;
689  dst[first + 1].fY = firstPoint.fY;
690  dst[first + 2].fX = xLast;
691  dst[first + 2].fY = firstPoint.fY;
692  } else {
693  dst[first + 1].fX = xMin;
694  dst[first + 1].fY = firstPoint.fY;
695  dst[first + 2].fX = xMax;
696  dst[first + 2].fY = firstPoint.fY;
697  dst[first + 3].fX = xLast;
698  dst[first + 3].fY = firstPoint.fY;
699  nMerged = 4;//Adjust the shift.
700  }
701 
702  return nMerged;
703 }
704 
705 ////////////////////////////////////////////////////////////////////////////////
706 /// I'm using 'pad' pointer to get rid of this damned gPad.
707 /// Unfortunately, TPadPainter itself still has to use it.
708 /// But at least this code does not have to be fixed.
709 
710 template<typename T>
711 void ConvertPointsAndMergePassX(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y,
712  std::vector<TPoint> &dst)
713 {
714  //The "first" pass along X axis.
715  TPoint currentPoint;
716  SCoord_t yMin = 0, yMax = 0, yLast = 0;
717  unsigned nMerged = 0;
718 
719  //The first pass along X.
720  for (unsigned i = 0; i < nPoints;) {
721  currentPoint.fX = (SCoord_t)pad->XtoPixel(x[i]);
722  currentPoint.fY = (SCoord_t)pad->YtoPixel(y[i]);
723 
724  yMin = currentPoint.fY;
725  yMax = yMin;
726 
727  dst.push_back(currentPoint);
728  bool merged = false;
729  nMerged = 1;
730 
731  for (unsigned j = i + 1; j < nPoints; ++j) {
732  const SCoord_t newX = pad->XtoPixel(x[j]);
733 
734  if (newX == currentPoint.fX) {
735  yLast = pad->YtoPixel(y[j]);
736  yMin = TMath::Min(yMin, yLast);
737  yMax = TMath::Max(yMax, yLast);//We continue.
738  ++nMerged;
739  } else {
740  if (nMerged > 1)
741  MergePointsX(dst, nMerged, yMin, yMax, yLast);
742  merged = true;
743  break;
744  }
745  }
746 
747  if (!merged && nMerged > 1)
748  MergePointsX(dst, nMerged, yMin, yMax, yLast);
749 
750  i += nMerged;
751  }
752 }
753 
754 ////////////////////////////////////////////////////////////////////////////////
755 /// This pass is a bit more complicated, since we have to 'compact' in-place.
756 
757 void ConvertPointsAndMergeInplacePassY(std::vector<TPoint> &dst)
758 {
759  size_type i = 0;
760  for (size_type j = 1, nPoints = dst.size(); i < nPoints;) {
761  //i is always less than j, so i is always valid here.
762  const TPoint &currentPoint = dst[i];
763 
764  SCoord_t xMin = currentPoint.fX;
765  SCoord_t xMax = xMin;
766  SCoord_t xLast = 0;
767 
768  bool merged = false;
769  size_type nMerged = 1;
770 
771  for (; j < nPoints; ++j) {
772  const TPoint &nextPoint = dst[j];
773 
774  if (nextPoint.fY == currentPoint.fY) {
775  xLast = nextPoint.fX;
776  xMin = TMath::Min(xMin, xLast);
777  xMax = TMath::Max(xMax, xLast);
778  ++nMerged;//and we continue ...
779  } else {
780  if (nMerged > 1)
781  nMerged = MergePointsInplaceY(dst, nMerged, xMin, xMax, xLast, i);
782  merged = true;
783  break;
784  }
785  }
786 
787  if (!merged && nMerged > 1)
788  nMerged = MergePointsInplaceY(dst, nMerged, xMin, xMax, xLast, i);
789 
790  i += nMerged;
791 
792  if (j < nPoints) {
793  dst[i] = dst[j];
794  ++j;
795  } else
796  break;
797  }
798 
799  dst.resize(i);
800 }
801 
802 ////////////////////////////////////////////////////////////////////////////////
803 /// This is a quite simple algorithm, using the fact, that after conversion many
804 /// subsequent vertices can have the same 'x' or 'y' coordinate and this part of
805 /// a polygon will look like a line on the screen.
806 
807 template<typename T>
808 void ConvertPointsAndMerge(TVirtualPad *pad, unsigned threshold, unsigned nPoints, const T *x,
809  const T *y, std::vector<TPoint> &dst)
810 {
811  //I'm using 'pad' pointer to get rid of this damned gPad.
812  //Unfortunately, TPadPainter itself still has to use it.
813  //But at least this code does not have to be fixed.
814 
815  if (!nPoints)
816  return;
817 
818  dst.clear();
819  dst.reserve(threshold);
820 
821  ConvertPointsAndMergePassX(pad, nPoints, x, y, dst);
822 
823  if (dst.size() < threshold)
824  return;
825 
826  ConvertPointsAndMergeInplacePassY(dst);
827 }
828 
829 ////////////////////////////////////////////////////////////////////////////////
830 
831 template<class T>
832 void DrawFillAreaAux(TVirtualPad *pad, Int_t nPoints, const T *xs, const T *ys)
833 {
834  std::vector<TPoint> xy;
835 
836  const Int_t threshold = Int_t(TMath::Min(pad->GetWw() * pad->GetAbsWNDC(),
837  pad->GetWh() * pad->GetAbsHNDC())) * 2;
838 
839  if (threshold <= 0) {
840  //Ooops, pad is invisible or something really bad and stupid happened.
841  ::Error("DrawFillAreaAux", "invalid pad's geometry");
842  return;
843  }
844 
845  if (nPoints < threshold)
846  ConvertPoints(gPad, nPoints, xs, ys, xy);
847  else
848  ConvertPointsAndMerge(gPad, threshold, nPoints, xs, ys, xy);
849 
850  //We close the 'polygon' and it'll be rendered as a polyline by gVirtualX.
851  if (!gVirtualX->GetFillStyle())
852  xy.push_back(xy.front());
853 
854  if (xy.size() > 2)
855  gVirtualX->DrawFillArea(xy.size(), &xy[0]);
856 }
857 
858 ////////////////////////////////////////////////////////////////////////////////
859 
860 template<typename T>
861 void DrawPolyLineAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys)
862 {
863  std::vector<TPoint> xy;
864 
865  const Int_t threshold = Int_t(TMath::Min(pad->GetWw() * pad->GetAbsWNDC(),
866  pad->GetWh() * pad->GetAbsHNDC())) * 2;
867 
868  if (threshold <= 0) {//Ooops, pad is invisible or something really bad and stupid happened.
869  ::Error("DrawPolyLineAux", "invalid pad's geometry");
870  return;
871  }
872 
873  if (nPoints < (unsigned)threshold)
874  ConvertPoints(pad, nPoints, xs, ys, xy);
875  else
876  ConvertPointsAndMerge(pad, threshold, nPoints, xs, ys, xy);
877 
878  if (xy.size() > 1)
879  gVirtualX->DrawPolyLine(xy.size(), &xy[0]);
880 
881 }
882 
883 ////////////////////////////////////////////////////////////////////////////////
884 
885 template<class T>
886 void DrawPolyMarkerAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys)
887 {
888  std::vector<TPoint> xy(nPoints);
889 
890  for (unsigned i = 0; i < nPoints; ++i) {
891  xy[i].fX = (SCoord_t)pad->XtoPixel(xs[i]);
892  xy[i].fY = (SCoord_t)pad->YtoPixel(ys[i]);
893  }
894 
895  gVirtualX->DrawPolyMarker(nPoints, &xy[0]);
896 }
897 
898 }
void DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y)
Paint polymarker.
void DestroyDrawable(Int_t device)
Close the current gVirtualX pixmap.
EImageFileTypes
Definition: TImage.h:36
Style_t GetLineStyle() const
Delegate to gVirtualX.
Definition: TPadPainter.cxx:98
short Style_t
Definition: RtypesCore.h:76
Float_t GetTextAngle() const
Delegate to gVirtualX.
float Float_t
Definition: RtypesCore.h:53
Int_t GetCanvasID() const
Get canvas identifier.
Definition: TCanvas.h:163
Float_t GetTextSize() const
Delegate to gVirtualX.
double T(double x)
Definition: ChebyshevPol.h:34
void DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v)
Paint polyline in normalized coordinates.
virtual void WriteImage(const char *, EImageFileTypes=TImage::kUnknown)
Definition: TImage.h:115
virtual Int_t XtoPixel(Double_t x) const =0
void SetFillStyle(Style_t fstyle)
Delegate to gVirtualX.
SCoord_t fX
Definition: TPoint.h:35
virtual UInt_t * GetArgbArray()
Definition: TImage.h:237
#define gROOT
Definition: TROOT.h:410
virtual Double_t GetAbsWNDC() const =0
virtual Int_t YtoPixel(Double_t y) const =0
SCoord_t fY
Definition: TPoint.h:36
void SetLineStyle(Style_t lstyle)
Delegate to gVirtualX.
void CopyDrawable(Int_t device, Int_t px, Int_t py)
Copy a gVirtualX pixmap.
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
void SelectDrawable(Int_t device)
Select the window in which the graphics will go.
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual UInt_t GetWh() const =0
void SetTextColor(Color_t tcolor)
Delegate to gVirtualX.
short Font_t
Definition: RtypesCore.h:75
void Flush()
Flush canvas buffers.
Definition: TCanvas.cxx:1085
TPadPainter()
Empty ctor. We need it only because of explicit copy ctor.
Definition: TPadPainter.cxx:72
void SetTextSizePixels(Int_t npixels)
Delegate to gVirtualX.
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
virtual Double_t GetAbsHNDC() const =0
static const double x2[5]
void DrawFillArea(Int_t n, const Double_t *x, const Double_t *y)
Paint filled area.
Double_t x[n]
Definition: legend1.C:17
short SCoord_t
Definition: RtypesCore.h:80
UInt_t GetWw() const
Get Ww.
Definition: TCanvas.h:169
virtual void DrawRectangle(UInt_t, UInt_t, UInt_t, UInt_t, const char *="#000000", UInt_t=1)
Definition: TImage.h:190
void DrawText(Double_t x, Double_t y, const char *text, ETextMode mode)
Paint text.
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:49
void ClearDrawable()
Clear the current gVirtualX window.
void Error(const char *location, const char *msgfmt,...)
short Color_t
Definition: RtypesCore.h:79
Definition: TPoint.h:31
point * points
Definition: X3DBuffer.c:20
Short_t GetTextAlign() const
Delegate to gVirtualX.
void SetFillColor(Color_t fcolor)
Delegate to gVirtualX.
void SetTextAlign(Short_t align)
Delegate to gVirtualX.
Color_t GetTextColor() const
Delegate to gVirtualX.
void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode)
Paint a simple box.
void SetLineWidth(Width_t lwidth)
Delegate to gVirtualX.
SVector< double, 2 > v
Definition: Dict.h:5
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
void DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height, Int_t dstX, Int_t dstY, Bool_t enableAlphaBlending)
Noop, for non-gl pad TASImage calls gVirtualX->CopyArea.
void DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2)
Paint a simple line in normalized coordinates.
Float_t GetTextMagnitude() const
Delegate to gVirtualX.
UInt_t GetWh() const
Get Wh.
Definition: TCanvas.h:170
void SetOpacity(Int_t percent)
Delegate to gVirtualX.
unsigned int UInt_t
Definition: RtypesCore.h:42
short Short_t
Definition: RtypesCore.h:35
virtual UInt_t GetWw() const =0
#define gVirtualX
Definition: TVirtualX.h:350
#define h(i)
Definition: RSha256.hxx:106
Color_t GetFillColor() const
Delegate to gVirtualX.
short Width_t
Definition: RtypesCore.h:78
void SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const
Save the image displayed in the canvas pointed by "pad" into a binary file.
Width_t GetLineWidth() const
Delegate to gVirtualX.
The Canvas class.
Definition: TCanvas.h:31
static const double x1[5]
#define ClassImp(name)
Definition: Rtypes.h:359
double Double_t
Definition: RtypesCore.h:55
void SetTextAngle(Float_t tangle)
Delegate to gVirtualX.
TText * text
void SetTextSize(Float_t tsize)
Delegate to gVirtualX.
virtual void FromPad(TVirtualPad *, Int_t=0, Int_t=0, UInt_t=0, UInt_t=0)
Definition: TImage.h:122
int type
Definition: TGX11.cxx:120
Double_t y[n]
Definition: legend1.C:17
Int_t CreateDrawable(UInt_t w, UInt_t h)
Create a gVirtualX Pixmap.
Bool_t IsTransparent() const
Delegate to gVirtualX.
void SetLineColor(Color_t lcolor)
Delegate to gVirtualX.
void DrawTextNDC(Double_t u, Double_t v, const char *text, ETextMode mode)
Paint text in normalized coordinates.
void DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Paint a simple line.
Color_t GetLineColor() const
Delegate to gVirtualX.
Definition: TPadPainter.cxx:89
void DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y)
Paint Polyline.
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
#define gPad
Definition: TVirtualPad.h:285
Font_t GetTextFont() const
Delegate to gVirtualX.
Implement TVirtualPadPainter which abstracts painting operations.
Definition: TPadPainter.h:26
Definition: first.py:1
static TImage * Create()
Create an image.
Definition: TImage.cxx:36
Style_t GetFillStyle() const
Delegate to gVirtualX.
const Int_t n
Definition: legend1.C:16
void SetTextFont(Font_t tfont)
Delegate to gVirtualX.
virtual TCanvas * GetCanvas() const =0