ROOT  6.06/09
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(id, px, py);
327 }
328 
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 /// Close the current gVirtualX pixmap.
332 
334 {
335  gVirtualX->ClosePixmap();
336 }
337 
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// Select the window in which the graphics will go.
341 
343 {
344  gVirtualX->SelectWindow(device);
345 }
346 
347 ////////////////////////////////////////////////////////////////////////////////
348 ///Noop, for non-gl pad TASImage calls gVirtualX->CopyArea.
349 
350 void TPadPainter::DrawPixels(const unsigned char * /*pixelData*/, UInt_t /*width*/, UInt_t /*height*/,
351  Int_t /*dstX*/, Int_t /*dstY*/, Bool_t /*enableAlphaBlending*/)
352 {
353 }
354 
355 
356 ////////////////////////////////////////////////////////////////////////////////
357 /// Paint a simple line.
358 
360 {
361  if (GetLineWidth()<=0) return;
362 
363  const Int_t px1 = gPad->XtoPixel(x1);
364  const Int_t px2 = gPad->XtoPixel(x2);
365  const Int_t py1 = gPad->YtoPixel(y1);
366  const Int_t py2 = gPad->YtoPixel(y2);
367  gVirtualX->DrawLine(px1, py1, px2, py2);
368 }
369 
370 
371 ////////////////////////////////////////////////////////////////////////////////
372 /// Paint a simple line in normalized coordinates.
373 
375 {
376  if (GetLineWidth()<=0) return;
377 
378  const Int_t px1 = gPad->UtoPixel(u1);
379  const Int_t py1 = gPad->VtoPixel(v1);
380  const Int_t px2 = gPad->UtoPixel(u2);
381  const Int_t py2 = gPad->VtoPixel(v2);
382  gVirtualX->DrawLine(px1, py1, px2, py2);
383 }
384 
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Paint a simple box.
388 
390 {
391  if (GetLineWidth()<=0 && mode == TVirtualPadPainter::kHollow) return;
392 
393  Int_t px1 = gPad->XtoPixel(x1);
394  Int_t px2 = gPad->XtoPixel(x2);
395  Int_t py1 = gPad->YtoPixel(y1);
396  Int_t py2 = gPad->YtoPixel(y2);
397 
398  // Box width must be at least one pixel (WTF is this code???)
399  if (TMath::Abs(px2 - px1) < 1)
400  px2 = px1 + 1;
401  if (TMath::Abs(py1 - py2) < 1)
402  py1 = py2 + 1;
403 
404  gVirtualX->DrawBox(px1, py1, px2, py2, (TVirtualX::EBoxMode)mode);
405 }
406 
407 ////////////////////////////////////////////////////////////////////////////////
408 /// Paint filled area.
409 
410 void TPadPainter::DrawFillArea(Int_t nPoints, const Double_t *xs, const Double_t *ys)
411 {
412  if (nPoints < 3) {
413  ::Error("TPadPainter::DrawFillArea", "invalid number of points %d", nPoints);
414  return;
415  }
416 
417  DrawFillAreaAux(gPad, nPoints, xs, ys);
418 }
419 
420 
421 ////////////////////////////////////////////////////////////////////////////////
422 /// Paint filled area.
423 
424 void TPadPainter::DrawFillArea(Int_t nPoints, const Float_t *xs, const Float_t *ys)
425 {
426  if (nPoints < 3) {
427  ::Error("TPadPainter::DrawFillArea", "invalid number of points %d", nPoints);
428  return;
429  }
430 
431  DrawFillAreaAux(gPad, nPoints, xs, ys);
432 }
433 
434 ////////////////////////////////////////////////////////////////////////////////
435 /// Paint Polyline.
436 
437 void TPadPainter::DrawPolyLine(Int_t n, const Double_t *xs, const Double_t *ys)
438 {
439  if (GetLineWidth()<=0) return;
440 
441  if (n < 2) {
442  ::Error("TPadPainter::DrawPolyLine", "invalid number of points");
443  return;
444  }
445 
446  DrawPolyLineAux(gPad, n, xs, ys);
447 }
448 
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Paint polyline.
452 
453 void TPadPainter::DrawPolyLine(Int_t n, const Float_t *xs, const Float_t *ys)
454 {
455  if (GetLineWidth()<=0) return;
456 
457  if (n < 2) {
458  ::Error("TPadPainter::DrawPolyLine", "invalid number of points");
459  return;
460  }
461 
462  DrawPolyLineAux(gPad, n, xs, ys);
463 }
464 
465 
466 ////////////////////////////////////////////////////////////////////////////////
467 /// Paint polyline in normalized coordinates.
468 
470 {
471  if (GetLineWidth()<=0) return;
472 
473  if (n < 2) {
474  ::Error("TPadPainter::DrawPolyLineNDC", "invalid number of points %d", n);
475  return;
476  }
477 
478  std::vector<TPoint> xy(n);
479 
480  for (Int_t i = 0; i < n; ++i) {
481  xy[i].fX = (SCoord_t)gPad->UtoPixel(u[i]);
482  xy[i].fY = (SCoord_t)gPad->VtoPixel(v[i]);
483  }
484 
485  gVirtualX->DrawPolyLine(n, &xy[0]);
486 }
487 
488 
489 ////////////////////////////////////////////////////////////////////////////////
490 /// Paint polymarker.
491 
493 {
494  if (n < 1) {
495  ::Error("TPadPainter::DrawPolyMarker", "invalid number of points %d", n);
496  return;
497  }
498 
499  DrawPolyMarkerAux(gPad, n, x, y);
500 }
501 
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 /// Paint polymarker.
505 
507 {
508  if (n < 1) {
509  ::Error("TPadPainter::DrawPolyMarker", "invalid number of points %d", n);
510  return;
511  }
512 
513  DrawPolyMarkerAux(gPad, n, x, y);
514 }
515 
516 
517 ////////////////////////////////////////////////////////////////////////////////
518 /// Paint text.
519 
520 void TPadPainter::DrawText(Double_t x, Double_t y, const char *text, ETextMode mode)
521 {
522  const Int_t px = gPad->XtoPixel(x);
523  const Int_t py = gPad->YtoPixel(y);
524  const Double_t angle = GetTextAngle();
525  const Double_t mgn = GetTextMagnitude();
526  gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode);
527 }
528 
529 
530 ////////////////////////////////////////////////////////////////////////////////
531 /// Special version working with wchar_t and required by TMathText.
532 
533 void TPadPainter::DrawText(Double_t x, Double_t y, const wchar_t *text, ETextMode mode)
534 {
535  const Int_t px = gPad->XtoPixel(x);
536  const Int_t py = gPad->YtoPixel(y);
537  const Double_t angle = GetTextAngle();
538  const Double_t mgn = GetTextMagnitude();
539  gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode);
540 }
541 
542 
543 ////////////////////////////////////////////////////////////////////////////////
544 /// Paint text in normalized coordinates.
545 
547 {
548  const Int_t px = gPad->UtoPixel(u);
549  const Int_t py = gPad->VtoPixel(v);
550  const Double_t angle = GetTextAngle();
551  const Double_t mgn = GetTextMagnitude();
552  gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode);
553 }
554 
555 
556 ////////////////////////////////////////////////////////////////////////////////
557 /// Save the image displayed in the canvas pointed by "pad" into a binary file.
558 
559 void TPadPainter::SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const
560 {
561  if (gVirtualX->InheritsFrom("TGCocoa") && !gROOT->IsBatch() &&
562  pad->GetCanvas() && pad->GetCanvas()->GetCanvasID() != -1) {
563 
564  TCanvas * const canvas = pad->GetCanvas();
565  //Force TCanvas::CopyPixmaps.
566  canvas->Flush();
567 
568  const UInt_t w = canvas->GetWw();
569  const UInt_t h = canvas->GetWh();
570 
571  const std::unique_ptr<unsigned char[]>
572  pixelData(gVirtualX->GetColorBits(canvas->GetCanvasID(), 0, 0, w, h));
573 
574  if (pixelData.get()) {
575  const std::unique_ptr<TImage> image(TImage::Create());
576  if (image.get()) {
577  image->DrawRectangle(0, 0, w, h);
578  if (unsigned char *argb = (unsigned char *)image->GetArgbArray()) {
579  //Ohhh.
580  if (sizeof(UInt_t) == 4) {
581  //For sure the data returned from TGCocoa::GetColorBits,
582  //it's 4 * w * h bytes with what TASImage considers to be argb.
583  std::copy(pixelData.get(), pixelData.get() + 4 * w * h, argb);
584  } else {
585  //A bit paranoid, don't you think so?
586  //Will Quartz/TASImage work at all on such a fancy platform? ;)
587  const unsigned shift = std::numeric_limits<unsigned char>::digits;
588  //
589  unsigned *dstPixel = (unsigned *)argb, *end = dstPixel + w * h;
590  const unsigned char *srcPixel = pixelData.get();
591  for (;dstPixel != end; ++dstPixel, srcPixel += 4) {
592  //Looks fishy but should work, trust me :)
593  *dstPixel = srcPixel[0] & (srcPixel[1] << shift) &
594  (srcPixel[2] << 2 * shift) &
595  (srcPixel[3] << 3 * shift);
596  }
597  }
598 
599  image->WriteImage(fileName, (TImage::EImageFileTypes)type);
600  //Success.
601  return;
602  }
603  }
604  }
605  }
606 
607  if (type == TImage::kGif) {
608  gVirtualX->WriteGIF((char*)fileName);
609  } else {
610  const std::unique_ptr<TImage> img(TImage::Create());
611  if (img.get()) {
612  img->FromPad(pad);
613  img->WriteImage(fileName, (TImage::EImageFileTypes)type);
614  }
615  }
616 }
617 
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 /// Paint text in normalized coordinates.
621 
623 {
624  const Int_t px = gPad->UtoPixel(u);
625  const Int_t py = gPad->VtoPixel(v);
626  const Double_t angle = GetTextAngle();
627  const Double_t mgn = GetTextMagnitude();
628  gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode);
629 }
630 
631 //Aux. private functions.
632 namespace {
633 
634 ////////////////////////////////////////////////////////////////////////////////
635 ///I'm using 'pad' pointer to get rid of this damned gPad.
636 ///Unfortunately, TPadPainter itself still has to use it.
637 ///But at least this code does not have to be fixed.
638 
639 template<typename T>
640 void ConvertPoints(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y,
641  std::vector<TPoint> &dst)
642 {
643  if (!nPoints)
644  return;
645 
646  dst.resize(nPoints);
647 
648  for (unsigned i = 0; i < nPoints; ++i) {
649  dst[i].fX = (SCoord_t)pad->XtoPixel(x[i]);
650  dst[i].fY = (SCoord_t)pad->YtoPixel(y[i]);
651  }
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 
656 inline void MergePointsX(std::vector<TPoint> &points, unsigned nMerged, SCoord_t yMin,
657  SCoord_t yMax, SCoord_t yLast)
658 {
659  const auto firstPointX = points.back().fX;
660  const auto firstPointY = points.back().fY;
661 
662  if (nMerged == 2) {
663  points.push_back(TPoint(firstPointX, yLast));//We have not merge anything.
664  } else if (nMerged == 3) {
665  yMin == firstPointY ? points.push_back(TPoint(firstPointX, yMax)) :
666  points.push_back(TPoint(firstPointX, yMin));
667  points.push_back(TPoint(firstPointX, yLast));
668  } else {
669  points.push_back(TPoint(firstPointX, yMin));
670  points.push_back(TPoint(firstPointX, yMax));
671  points.push_back(TPoint(firstPointX, yLast));
672  }
673 }
674 
675 ////////////////////////////////////////////////////////////////////////////////
676 ///Indices below are _valid_.
677 
678 inline size_type MergePointsInplaceY(std::vector<TPoint> &dst, size_type nMerged, SCoord_t xMin,
679  SCoord_t xMax, SCoord_t xLast, size_type first)
680 {
681  const TPoint &firstPoint = dst[first];//This point is never updated.
682 
683  if (nMerged == 2) {
684  dst[first + 1].fX = xLast;
685  dst[first + 1].fY = firstPoint.fY;
686  } else if (nMerged == 3) {
687  dst[first + 1].fX = xMin == firstPoint.fX ? xMax : xMin;
688  dst[first + 1].fY = firstPoint.fY;
689  dst[first + 2].fX = xLast;
690  dst[first + 2].fY = firstPoint.fY;
691  } else {
692  dst[first + 1].fX = xMin;
693  dst[first + 1].fY = firstPoint.fY;
694  dst[first + 2].fX = xMax;
695  dst[first + 2].fY = firstPoint.fY;
696  dst[first + 3].fX = xLast;
697  dst[first + 3].fY = firstPoint.fY;
698  nMerged = 4;//Adjust the shift.
699  }
700 
701  return nMerged;
702 }
703 
704 ////////////////////////////////////////////////////////////////////////////////
705 /// I'm using 'pad' pointer to get rid of this damned gPad.
706 /// Unfortunately, TPadPainter itself still has to use it.
707 /// But at least this code does not have to be fixed.
708 
709 template<typename T>
710 void ConvertPointsAndMergePassX(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y,
711  std::vector<TPoint> &dst)
712 {
713  //The "first" pass along X axis.
714  TPoint currentPoint;
715  SCoord_t yMin = 0, yMax = 0, yLast = 0;
716  unsigned nMerged = 0;
717 
718  //The first pass along X.
719  for (unsigned i = 0; i < nPoints;) {
720  currentPoint.fX = (SCoord_t)pad->XtoPixel(x[i]);
721  currentPoint.fY = (SCoord_t)pad->YtoPixel(y[i]);
722 
723  yMin = currentPoint.fY;
724  yMax = yMin;
725 
726  dst.push_back(currentPoint);
727  bool merged = false;
728  nMerged = 1;
729 
730  for (unsigned j = i + 1; j < nPoints; ++j) {
731  const SCoord_t newX = pad->XtoPixel(x[j]);
732 
733  if (newX == currentPoint.fX) {
734  yLast = pad->YtoPixel(y[j]);
735  yMin = TMath::Min(yMin, yLast);
736  yMax = TMath::Max(yMax, yLast);//We continue.
737  ++nMerged;
738  } else {
739  if (nMerged > 1)
740  MergePointsX(dst, nMerged, yMin, yMax, yLast);
741  merged = true;
742  break;
743  }
744  }
745 
746  if (!merged && nMerged > 1)
747  MergePointsX(dst, nMerged, yMin, yMax, yLast);
748 
749  i += nMerged;
750  }
751 }
752 
753 ////////////////////////////////////////////////////////////////////////////////
754 /// This pass is a bit more complicated, since we have to 'compact' in-place.
755 
756 void ConvertPointsAndMergeInplacePassY(std::vector<TPoint> &dst)
757 {
758  size_type i = 0;
759  for (size_type j = 1, nPoints = dst.size(); i < nPoints;) {
760  //i is always less than j, so i is always valid here.
761  const TPoint &currentPoint = dst[i];
762 
763  SCoord_t xMin = currentPoint.fX;
764  SCoord_t xMax = xMin;
765  SCoord_t xLast = 0;
766 
767  bool merged = false;
768  size_type nMerged = 1;
769 
770  for (; j < nPoints; ++j) {
771  const TPoint &nextPoint = dst[j];
772 
773  if (nextPoint.fY == currentPoint.fY) {
774  xLast = nextPoint.fX;
775  xMin = TMath::Min(xMin, xLast);
776  xMax = TMath::Max(xMax, xLast);
777  ++nMerged;//and we continue ...
778  } else {
779  if (nMerged > 1)
780  nMerged = MergePointsInplaceY(dst, nMerged, xMin, xMax, xLast, i);
781  merged = true;
782  break;
783  }
784  }
785 
786  if (!merged && nMerged > 1)
787  nMerged = MergePointsInplaceY(dst, nMerged, xMin, xMax, xLast, i);
788 
789  i += nMerged;
790 
791  if (j < nPoints) {
792  dst[i] = dst[j];
793  ++j;
794  } else
795  break;
796  }
797 
798  dst.resize(i);
799 }
800 
801 ////////////////////////////////////////////////////////////////////////////////
802 /// This is a quite simple algorithm, using the fact, that after conversion many
803 /// subsequent vertices can have the same 'x' or 'y' coordinate and this part of
804 /// a polygon will look like a line on the screen.
805 
806 template<typename T>
807 void ConvertPointsAndMerge(TVirtualPad *pad, unsigned threshold, unsigned nPoints, const T *x,
808  const T *y, std::vector<TPoint> &dst)
809 {
810  //I'm using 'pad' pointer to get rid of this damned gPad.
811  //Unfortunately, TPadPainter itself still has to use it.
812  //But at least this code does not have to be fixed.
813 
814  if (!nPoints)
815  return;
816 
817  dst.clear();
818  dst.reserve(threshold);
819 
820  ConvertPointsAndMergePassX(pad, nPoints, x, y, dst);
821 
822  if (dst.size() < threshold)
823  return;
824 
825  ConvertPointsAndMergeInplacePassY(dst);
826 }
827 
828 ////////////////////////////////////////////////////////////////////////////////
829 
830 template<class T>
831 void DrawFillAreaAux(TVirtualPad *pad, Int_t nPoints, const T *xs, const T *ys)
832 {
833  std::vector<TPoint> xy;
834 
835  const Int_t threshold = Int_t(TMath::Min(pad->GetWw() * pad->GetAbsWNDC(),
836  pad->GetWh() * pad->GetAbsHNDC())) * 2;
837 
838  if (threshold <= 0) {
839  //Ooops, pad is invisible or something really bad and stupid happened.
840  ::Error("DrawFillAreaAux", "invalid pad's geometry");
841  return;
842  }
843 
844  if (nPoints < threshold)
845  ConvertPoints(gPad, nPoints, xs, ys, xy);
846  else
847  ConvertPointsAndMerge(gPad, threshold, nPoints, xs, ys, xy);
848 
849  //We close the 'polygon' and it'll be rendered as a polyline by gVirtualX.
850  if (!gVirtualX->GetFillStyle())
851  xy.push_back(xy.front());
852 
853  if (xy.size() > 2)
854  gVirtualX->DrawFillArea(xy.size(), &xy[0]);
855 }
856 
857 ////////////////////////////////////////////////////////////////////////////////
858 
859 template<typename T>
860 void DrawPolyLineAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys)
861 {
862  std::vector<TPoint> xy;
863 
864  const Int_t threshold = Int_t(TMath::Min(pad->GetWw() * pad->GetAbsWNDC(),
865  pad->GetWh() * pad->GetAbsHNDC())) * 2;
866 
867  if (threshold <= 0) {//Ooops, pad is invisible or something really bad and stupid happened.
868  ::Error("DrawPolyLineAux", "invalid pad's geometry");
869  return;
870  }
871 
872  if (nPoints < (unsigned)threshold)
873  ConvertPoints(pad, nPoints, xs, ys, xy);
874  else
875  ConvertPointsAndMerge(pad, threshold, nPoints, xs, ys, xy);
876 
877  if (xy.size() > 1)
878  gVirtualX->DrawPolyLine(xy.size(), &xy[0]);
879 
880 }
881 
882 ////////////////////////////////////////////////////////////////////////////////
883 
884 template<class T>
885 void DrawPolyMarkerAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys)
886 {
887  std::vector<TPoint> xy(nPoints);
888 
889  for (unsigned i = 0; i < nPoints; ++i) {
890  xy[i].fX = (SCoord_t)pad->XtoPixel(xs[i]);
891  xy[i].fY = (SCoord_t)pad->YtoPixel(ys[i]);
892  }
893 
894  gVirtualX->DrawPolyMarker(nPoints, &xy[0]);
895 }
896 
897 }
void DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y)
Paint polymarker.
void CopyDrawable(Int_t id, Int_t px, Int_t py)
Copy a gVirtualX pixmap.
EImageFileTypes
Definition: TImage.h:52
const Double_t * v1
Definition: TArcBall.cxx:33
short Style_t
Definition: RtypesCore.h:76
float Float_t
Definition: RtypesCore.h:53
Float_t GetTextMagnitude() 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:131
TH1 * h
Definition: legend2.C:5
Float_t GetTextAngle() const
Delegate to gVirtualX.
virtual Int_t XtoPixel(Double_t x) const =0
void SetFillStyle(Style_t fstyle)
Delegate to gVirtualX.
SCoord_t fX
Definition: TPoint.h:37
virtual UInt_t * GetArgbArray()
Definition: TImage.h:253
#define gROOT
Definition: TROOT.h:340
virtual Double_t GetAbsWNDC() const =0
virtual Int_t YtoPixel(Double_t y) const =0
SCoord_t fY
Definition: TPoint.h:38
void SetLineStyle(Style_t lstyle)
Delegate to gVirtualX.
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
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
Color_t GetTextColor() const
Delegate to gVirtualX.
void SetTextColor(Color_t tcolor)
Delegate to gVirtualX.
short Font_t
Definition: RtypesCore.h:75
void Flush()
Flush canvas buffers.
Definition: TCanvas.cxx:1053
void SetTextSizePixels(Int_t npixels)
Delegate to gVirtualX.
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
Style_t GetLineStyle() const
Delegate to gVirtualX.
Definition: TPadPainter.cxx:98
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.
short SCoord_t
Definition: RtypesCore.h:80
virtual void DrawRectangle(UInt_t, UInt_t, UInt_t, UInt_t, const char *="#000000", UInt_t=1)
Definition: TImage.h:206
Float_t GetTextSize() const
Delegate to gVirtualX.
void DrawText(Double_t x, Double_t y, const char *text, ETextMode mode)
Paint text.
UInt_t GetWw() const
Get Ww.
Definition: TCanvas.h:186
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:59
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:33
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.
void SetFillColor(Color_t fcolor)
Delegate to gVirtualX.
void SetTextAlign(Short_t align)
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.
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:362
static TImage * Create()
short Width_t
Definition: RtypesCore.h:78
void DestroyDrawable()
Close the current gVirtualX pixmap.
The Canvas class.
Definition: TCanvas.h:48
static const double x1[5]
#define ClassImp(name)
Definition: Rtypes.h:279
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:138
int type
Definition: TGX11.cxx:120
Int_t CreateDrawable(UInt_t w, UInt_t h)
Create a gVirtualX Pixmap.
void SetLineColor(Color_t lcolor)
Delegate to gVirtualX.
Color_t GetFillColor() const
Delegate to gVirtualX.
Color_t GetLineColor() const
Delegate to gVirtualX.
Definition: TPadPainter.cxx:89
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.
void DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y)
Paint Polyline.
Int_t GetCanvasID() const
Get canvas identifier.
Definition: TCanvas.h:180
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
Width_t GetLineWidth() const
Delegate to gVirtualX.
#define gPad
Definition: TVirtualPad.h:288
Implement TVirtualPadPainter which abstracts painting operations.
Definition: TPadPainter.h:28
Short_t GetTextAlign() const
Delegate to gVirtualX.
Font_t GetTextFont() const
Delegate to gVirtualX.
const Int_t n
Definition: legend1.C:16
Style_t GetFillStyle() const
Delegate to gVirtualX.
void SetTextFont(Font_t tfont)
Delegate to gVirtualX.
UInt_t GetWh() const
Get Wh.
Definition: TCanvas.h:187
Bool_t IsTransparent() const
Delegate to gVirtualX.
const char Int_t const char * image
Definition: TXSlave.cxx:46
virtual TCanvas * GetCanvas() const =0