Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
X11Buffer.mm
Go to the documentation of this file.
1// @(#)root/graf2d:$Id$
2// Author: Timur Pocheptsov 29/02/2012
3
4/*************************************************************************
5 * Copyright (C) 1995-2012, 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//#define NDEBUG
13
14#include <algorithm>
15#include <stdexcept>
16#include <cstring>
17#include <cassert>
18#include <memory>
19
20#include <Cocoa/Cocoa.h>
21
22#include "ROOTOpenGLView.h"
23#include "CocoaPrivate.h"
24#include "QuartzWindow.h"
25#include "QuartzMarker.h"
26#include "QuartzPixmap.h"
27#include "QuartzUtils.h"
28#include "X11Drawable.h"
29#include "QuartzLine.h"
30#include "X11Buffer.h"
31#include "TGWindow.h"
32#include "TGClient.h"
33#include "TGCocoa.h"
34#include "TError.h"
35
36namespace ROOT {
37namespace MacOSX {
38namespace X11 {
39
40//______________________________________________________________________________
42 : fID(wid),
43 fGC(gc)
44{
45}
46
47//______________________________________________________________________________
49 : fID(wid),
50 fGC()
51{
52}
53
54//______________________________________________________________________________
58
59//______________________________________________________________________________
61{
62}
63
64//______________________________________________________________________________
66{
67 return wid == fID;
68}
69
70//______________________________________________________________________________
72{
73 return false;
74}
75
76//______________________________________________________________________________
78 : Command(wid, gc),
79 fP1(p1),
80 fP2(p2)
81{
82}
83
84//______________________________________________________________________________
86{
87 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
88 "Execute, gVirtualX is either null or not of TGCocoa type");
89 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
90 vx->DrawLineAux(fID, fGC, fP1.fX, fP1.fY, fP2.fX, fP2.fY);
91}
92
93//______________________________________________________________________________
96 : Command(wid, gc)
97{
98 assert(segments != 0 && "DrawSegments, segments parameter is null");
99 assert(nSegments > 0 && "DrawSegments, nSegments <= 0");
100
102}
103
104//______________________________________________________________________________
106{
107 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
108 "Execute, gVirtualX is either null or not of TGCocoa type");
109 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
110 vx->DrawSegmentsAux(fID, fGC, &fSegments[0], (Int_t)fSegments.size());
111}
112
113//______________________________________________________________________________
115 : Command(wid),
116 fArea(area)
117{
118}
119
120//______________________________________________________________________________
122{
123 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
124 "Execute, gVirtualX is either null or not of TGCocoa type");
125 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
126 vx->ClearAreaAux(fID, fArea.fX, fArea.fY, fArea.fWidth, fArea.fHeight);
127}
128
129//______________________________________________________________________________
131 const Rectangle_t &area, const Point &dstPoint)
132 : Command(dst, gc),
133 fSrc(src),
134 fArea(area),
135 fDstPoint(dstPoint)
136{
137}
138
139//______________________________________________________________________________
141{
142 return fID == drawable || fSrc == drawable || fGC.fClipMask == drawable;
143}
144
145//______________________________________________________________________________
147{
148 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
149 "Execute, gVirtualX is either null or not of TGCocoa type");
150
151 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
152 vx->CopyAreaAux(fSrc, fID, fGC, fArea.fX, fArea.fY, fArea.fWidth,
153 fArea.fHeight, fDstPoint.fX, fDstPoint.fY);
154}
155
156//______________________________________________________________________________
158 const std::string &text)
159 : Command(wid, gc),
160 fPoint(point),
161 fText(text)
162{
163}
164
165//______________________________________________________________________________
167{
168 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
169 "Execute, gVirtualX is either null or not of TGCocoa type");
170
171 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
172 vx->DrawStringAux(fID, fGC, fPoint.fX, fPoint.fY, fText.c_str(), fText.length());
173}
174
175//______________________________________________________________________________
177 const Rectangle_t &rectangle)
178 : Command(wid, gc),
179 fRectangle(rectangle)
180{
181}
182
183//______________________________________________________________________________
185{
186 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
187 "Execute, gVirtualX is either null or not of TGCocoa type");
188
189 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
190 vx->FillRectangleAux(fID, fGC, fRectangle.fX, fRectangle.fY,
191 fRectangle.fWidth, fRectangle.fHeight);
192}
193
194//______________________________________________________________________________
196 const Point_t *points, Int_t nPoints)
197 : Command(wid, gc)
198{
199 assert(points != 0 && "FillPolygon, points parameter is null");
200 assert(nPoints > 0 && "FillPolygon, nPoints <= 0");
201
202 fPolygon.assign(points, points + nPoints);
203}
204
205//______________________________________________________________________________
207{
208 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
209 "Execute, gVirtualX is either null or not of TGCocoa type");
210
211 ((TGCocoa *)gVirtualX)->FillPolygonAux(fID, fGC, &fPolygon[0], (Int_t)fPolygon.size());
212}
213
214//______________________________________________________________________________
216 const Rectangle_t &rectangle)
217 : Command(wid, gc),
218 fRectangle(rectangle)
219{
220}
221
222//______________________________________________________________________________
224{
225 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
226 "Execute, gVirtualX is either null or not of TGCocoa type");
227
228 TGCocoa * const vx = static_cast<TGCocoa *>(gVirtualX);
229 vx->DrawRectangleAux(fID, fGC, fRectangle.fX, fRectangle.fY,
231}
232
233//______________________________________________________________________________
235 : Command(view.fID),
236 fView(view)
237{
238 assert(view != nil && "UpdateWindow, view parameter is nil");//view.fID will be also 0.
239}
240
241//______________________________________________________________________________
243{
244 assert(fView.fContext != 0 && "Execute, view.fContext is null");
245
247 [fView copy : pixmap area : Rectangle(0, 0, pixmap.fWidth, pixmap.fHeight)
249}
250
251//______________________________________________________________________________
256
257//______________________________________________________________________________
259{
260 assert(dynamic_cast<TGCocoa *>(gVirtualX) != 0 &&
261 "Execute, gVirtualX is either null or not of TGCocoa type");
262
263 ((TGCocoa *)gVirtualX)->DeletePixmapAux(fID);
264}
265
266//______________________________________________________________________________
269 fP1(p1),
270 fP2(p2)
271{
272 if (fP1.fX > fP2.fX)
273 std::swap(fP1.fX, fP2.fX);
274 if (fP1.fY > fP2.fY)
275 std::swap(fP1.fY, fP2.fY);
276}
277
278//______________________________________________________________________________
279
280const auto rootToNs = [](Point rp) {
281 return NSPoint{CGFloat(rp.fX), CGFloat(rp.fY)};
282};
283
284//______________________________________________________________________________
286{
287 assert(ctx && "Execute, 'ctx' parameter is nullptr");
288 // XOR window/view is not flipped, thus this mess with coordinates :(
289 const auto height = fP2.fY - fP1.fY; // Presumably, cannot be negative?
290 NSPoint btLeft = [view convertPoint : rootToNs(fP1) toView : nil];
291 btLeft.y -= height;
293}
294
295//______________________________________________________________________________
298 fP1(p1),
299 fP2(p2)
300{
301}
302
303//______________________________________________________________________________
305{
306 assert(ctx && "Execute, invalid (nullptr) parameter 'ctx'");
307
308 // Line's colour and thickness were set elsewhere.
309 NSPoint line[] = {rootToNs(fP1), rootToNs(fP2)};
310 for (auto &point : line) {
311 // From the view's coordinates to window's:
312 point = [view convertPoint : point toView : nil];
313 };
314
316 CGContextMoveToPoint(ctx, line[0].x, line[0].y);
317 CGContextAddLineToPoint(ctx, line[1].x, line[1].y);
319}
320
321//______________________________________________________________________________
323{
324 fPnts.resize(n);
325 for (Int_t i = 0; i < n; ++i) {
326 auto point = NSPoint{CGFloat(xy[i].fX), CGFloat(xy[i].fY)};
327 point = [view convertPoint : point toView : nil];
328 fPnts[i].fX = (SCoord_t) point.x;
329 fPnts[i].fY = (SCoord_t) point.y;
330 }
331}
332
333//______________________________________________________________________________
335{
336 assert(ctx && "Execute, invalid (nullptr) parameter 'ctx'");
337
339
341 return;
342
345
346 if (fScaleFactor > 1.)
348
349 Quartz::DrawPolyLine(ctx, fPnts.size(), fPnts.data());
350}
351
352//______________________________________________________________________________
354{
355 fPnts.resize(n);
356 for (Int_t i = 0; i < n; ++i) {
357 auto point = NSPoint{CGFloat(xy[i].fX), CGFloat(xy[i].fY)};
358 point = [view convertPoint : point toView : nil];
359 fPnts[i].fX = (SCoord_t) point.x;
360 fPnts[i].fY = (SCoord_t) point.y;
361 }
362}
363
364//______________________________________________________________________________
366{
367 assert(ctx && "Execute, invalid (nullptr) parameter 'ctx'");
368
370
371 Quartz::DrawPolyMarker(ctx, fPnts.size(), fPnts.data(), fAtt, fScaleFactor);
372}
373
374//______________________________________________________________________________
378
379//______________________________________________________________________________
384
385//______________________________________________________________________________
388{
389 try {
390 //if this throws, I do not care.
391 std::unique_ptr<DrawLine> cmd(new DrawLine(wid, gc, Point(x1, y1), Point(x2, y2)));
392 fCommands.push_back(cmd.get());//this can throw.
393 cmd.release();
394 } catch (const std::exception &) {
395 throw;
396 }
397}
398
399//______________________________________________________________________________
402{
403 assert(segments != 0 && "AddDrawSegments, segments parameter is null");
404 assert(nSegments > 0 && "AddDrawSegments, nSegments <= 0");
405
406 try {
407 std::unique_ptr<DrawSegments> cmd(new DrawSegments(wid, gc, segments, nSegments));
408 fCommands.push_back(cmd.get());
409 cmd.release();
410 } catch (const std::exception &) {
411 throw;
412 }
413}
414
415//______________________________________________________________________________
417{
418 try {
419 Rectangle_t r = {};//To be replaced with X11::Rectangle.
420 r.fX = x;
421 r.fY = y;
422 r.fWidth = (UShort_t)w;
423 r.fHeight = (UShort_t)h;
424 std::unique_ptr<ClearArea> cmd(new ClearArea(wid, r));//Can throw, nothing leaks.
425 fCommands.push_back(cmd.get());//this can throw.
426 cmd.release();
427 } catch (const std::exception &) {
428 throw;
429 }
430}
431
432//______________________________________________________________________________
436{
437 try {
438 Rectangle_t area = {};
439 area.fX = srcX;
440 area.fY = srcY;
441 area.fWidth = (UShort_t)width;
442 area.fHeight = (UShort_t)height;
443 //Can throw, nothing leaks.
444 std::unique_ptr<CopyArea> cmd(new CopyArea(src, dst, gc, area, Point(dstX, dstY)));
445 fCommands.push_back(cmd.get());//this can throw.
446 cmd.release();
447 } catch (const std::exception &) {
448 throw;
449 }
450}
451
452//______________________________________________________________________________
454 const char *text, Int_t len)
455{
456 try {
457 if (len < 0)//Negative length can come from caller.
458 len = std::strlen(text);
459 const std::string substr(text, len);//Can throw.
460 std::unique_ptr<DrawString> cmd(new DrawString(wid, gc, Point(x, y), substr));//Can throw.
461 fCommands.push_back(cmd.get());//can throw.
462 cmd.release();
463 } catch (const std::exception &) {
464 throw;
465 }
466}
467
468//______________________________________________________________________________
471{
472 try {
473 Rectangle_t r = {};
474 r.fX = x;
475 r.fY = y;
476 r.fWidth = (UShort_t)w;
477 r.fHeight = (UShort_t)h;
478 std::unique_ptr<FillRectangle> cmd(new FillRectangle(wid, gc, r));
479 fCommands.push_back(cmd.get());
480 cmd.release();
481 } catch (const std::exception &) {
482 throw;
483 }
484}
485
486//______________________________________________________________________________
489{
490 try {
491 Rectangle_t r = {};
492 r.fX = x;
493 r.fY = y;
494 r.fWidth = (UShort_t)w;
495 r.fHeight = (UShort_t)h;
496 std::unique_ptr<DrawRectangle> cmd(new DrawRectangle(wid, gc, r));
497 fCommands.push_back(cmd.get());
498 cmd.release();
499 } catch (const std::exception &) {
500 throw;
501 }
502}
503
504//______________________________________________________________________________
507{
508 assert(polygon != 0 && "AddFillPolygon, polygon parameter is null");
509 assert(nPoints > 0 && "AddFillPolygon, nPoints <= 0");
510
511 try {
512 std::unique_ptr<FillPolygon> cmd(new FillPolygon(wid, gc, polygon, nPoints));
513 fCommands.push_back(cmd.get());
514 cmd.release();
515 } catch (const std::exception &) {
516 throw;
517 }
518}
519
520//______________________________________________________________________________
522{
523 assert(view != nil && "AddUpdateWindow, view parameter is nil");
524
525 try {
526 std::unique_ptr<UpdateWindow> cmd(new UpdateWindow(view));
527 fCommands.push_back(cmd.get());
528 cmd.release();
529 } catch (const std::exception &) {
530 throw;
531 }
532}
533
534//______________________________________________________________________________
536{
537 try {
538 std::unique_ptr<DeletePixmap> cmd(new DeletePixmap(pixmapID));
539 fCommands.push_back(cmd.get());
540 cmd.release();
541 } catch (const std::exception &) {
542 throw;
543 }
544}
545
546//______________________________________________________________________________
548{
549 assert(impl != 0 && "Flush, impl parameter is null");
550
551 //Basic es-guarantee: state is unknown, but valid, no
552 //resource leaks, no locked focus.
553
554 //All magic is here.
558
559 for (size_type i = 0, e = fCommands.size(); i < e; ++i) {
560 const Command *cmd = fCommands[i];
561 if (!cmd)//Command was deleted by RemoveOperation/RemoveGraphicsOperation.
562 continue;
563
564 NSObject<X11Drawable> *drawable = impl->GetDrawable(cmd->fID);
565 if (drawable.fIsPixmap) {
566 cmd->Execute();//Can throw, ok.
567 continue;
568 }
569
570 QuartzView *view = (QuartzView *)impl->GetWindow(cmd->fID).fContentView;
571
572 if (prevView != view)
573 ClipOverlaps(view);//Can throw, ok.
574
575 prevView = view;
576
577 try {
578 if ([view lockFocusIfCanDraw]) {
580 assert(nsContext != nil && "Flush, currentContext is nil");
582 assert(currContext != 0 && "Flush, graphicsPort is null");//remove this assert?
583
584 view.fContext = currContext;
588
590
591 //Clip regions first.
592 if (fClippedRegion.size())
594
595 //Now add also shape combine mask.
598
599 cmd->Execute();//This can throw, we should restore as much as we can here.
600
601 if (view.fBackBuffer) {
602 //Very "special" window.
603 const Rectangle copyArea(0, 0, view.fBackBuffer.fWidth, view.fBackBuffer.fHeight);
604 [view copy : view.fBackBuffer area : copyArea
606 }
607
608 [view unlockFocus];
609
610 view.fContext = 0;
611 }
612 } catch (const std::exception &) {
613 //Focus was locked, roll-back:
614 [view unlockFocus];
615 //View's context was modified, roll-back:
616 view.fContext = 0;
617 //Re-throw, something really bad happened (std::bad_alloc).
618 throw;
619 }
620 }
621
622 if (currContext)
624
626}
627
628//______________________________________________________________________________
630{
631 for (size_type i = 0; i < fCommands.size(); ++i) {
632 if (fCommands[i] && fCommands[i]->HasOperand(drawable)) {
633 delete fCommands[i];
634 fCommands[i] = 0;
635 }
636 }
637}
638
639//______________________________________________________________________________
641{
642 for (size_type i = 0; i < fCommands.size(); ++i) {
643 if (fCommands[i] && fCommands[i]->HasOperand(wid) &&
644 fCommands[i]->IsGraphicsCommand())
645 {
646 delete fCommands[i];
647 fCommands[i] = 0;
648 }
649 }
650}
651
652//______________________________________________________________________________
654{
655 for (size_type i = 0, e = fCommands.size(); i < e; ++i)
656 delete fCommands[i];
657
658 fCommands.clear();
659}
660
661//Clipping machinery.
662
663namespace {
664
665//________________________________________________________________________________________
666bool RectsOverlap(const NSRect &r1, const NSRect &r2)
667{
668 if (r2.origin.x >= r1.origin.x + r1.size.width)
669 return false;
670 if (r2.origin.x + r2.size.width <= r1.origin.x)
671 return false;
672 if (r2.origin.y >= r1.origin.y + r1.size.height)
673 return false;
674 if (r2.origin.y + r2.size.height <= r1.origin.y)
675 return false;
676
677 return true;
678}
679
680}
681
682//______________________________________________________________________________
684{
685 //QuartzViews do not have backing store.
686 //But ROOT calls gClient->NeedRedraw ignoring
687 //children or overlapping siblings. This leads
688 //to obvious problems, for example, parent
689 //erasing every child inside while repainting itself.
690 //To fix this and emulate window with backing store
691 //without real backing store, I'm calculating the
692 //area of a view this is visible and not overlapped.
693
694 //Who can overlap our view?
695 //1. Its own siblings and, probably, siblings of its ancestors.
696 //2. Children views.
697
698 assert(view != nil && "ClipOverlaps, view parameter is nil");
699
700 typedef std::vector<QuartzView *>::reverse_iterator reverse_iterator;
701 typedef std::vector<CGRect>::iterator rect_iterator;
702
703 fRectsToClip.clear();
704 fClippedRegion.clear();
705
706 //Check siblings and ancestors' siblings:
707
708 //1. Remember the whole branch starting from our view
709 //up to a top-level window.
710 fViewBranch.clear();
711 for (QuartzView *v = view; v; v = v.fParentView)
712 fViewBranch.push_back(v);
713
714 //We do not need content view, since it does not have any siblings.
715 if (fViewBranch.size())
716 fViewBranch.pop_back();
717
718 //For every fViewBranch[i] in our branch, we're looking for overlapping siblings.
719 //Calculations are in view.fParentView's coordinate system.
720
722 NSRect frame1 = {};
723
724 const NSRect frame2 = view.frame;
725
726 for (reverse_iterator it = fViewBranch.rbegin(), eIt = fViewBranch.rend(); it != eIt; ++it) {
727 QuartzView *ancestorView = *it;//This is either one of ancestors, or a view itself.
728 bool doCheck = false;
729 for (QuartzView *sibling in [ancestorView.fParentView subviews]) {
730 if (ancestorView == sibling) {
731 //View has its children in an array, and for every subviews[i] in this array,
732 //only views with index > i can overlap subviews[i].
733 doCheck = true;//all views after this must be checked.
734 continue;
735 } else if (!doCheck || sibling.fMapState != kIsViewable) {
736 continue;
737 }
738
739 frame1 = sibling.frame;
740
741 if (!frame1.size.width || !frame1.size.height)
742 continue;
743
744 frame1.origin = [sibling.fParentView convertPoint : frame1.origin
745 toView : view.fParentView];
746
747 //Check if two rects intersect.
748 if (RectsOverlap(frame2, frame1)) {
749 //Substruct frame1 from our view's rect.
750 clipRect.fX1 = frame1.origin.x;
751 clipRect.fX2 = clipRect.fX1 + frame1.size.width;
752 clipRect.fY1 = frame1.origin.y;
753 clipRect.fY2 = clipRect.fY1 + frame1.size.height;
754 fRectsToClip.push_back(clipRect);
755 }
756 }
757 }
758
759 //Substruct children.
760
761 for (QuartzView *child in [view subviews]) {
762 if (child.fMapState != kIsViewable)
763 continue;
764
765 frame1 = child.frame;
766
767 if (!frame1.size.width || !frame1.size.height)
768 continue;
769
770 if (view.fParentView)//view can also be a content view.
771 frame1.origin = [view convertPoint : frame1.origin toView : view.fParentView];
772
773 if (RectsOverlap(frame2, frame1)) {
774 clipRect.fX1 = frame1.origin.x;
775 clipRect.fX2 = clipRect.fX1 + frame1.size.width;
776 clipRect.fY1 = frame1.origin.y;
777 clipRect.fY2 = clipRect.fY1 + frame1.size.height;
778 fRectsToClip.push_back(clipRect);
779 }
780 }
781
782 if (fRectsToClip.size()) {
783 //Now, if we have any rectanges to substruct them from our view's frame,
784 //we are building a set of rectangles, which represents visible part of view.
785
786 WidgetRect rect(frame2.origin.x, frame2.origin.y, frame2.origin.x + frame2.size.width,
787 frame2.origin.y + frame2.size.height);
788
790
791 if (view.fParentView) {
792 //To able to use this set of rectangles with CGContextClipToRects,
793 //convert them (if needed) into view's own coordinate system.
795 for (; recIt != eIt; ++recIt) {
796 if (!recIt->size.width && !recIt->size.height) {
797 //This is a special 'empty' rectangle, which means our view is completely hidden.
798 assert(fClippedRegion.size() == 1 && "ClipOverlaps, internal logic error");
799 break;
800 }
802 NSPointFromCGPoint(recIt->origin) toView : view]);
803 }
804 }
805 }
806}
807
808namespace {
809
810typedef std::vector<int>::iterator int_iterator;
811
812//_____________________________________________________________________________________________________
814{
815 if (first == last)
816 return last;
817
818 const int_iterator it = std::lower_bound(first, last, value);
819 assert(it != last && (it == first || *it == value) && "internal logic error");
820
821 //If value < *first, return last (not found).
822 return it == first && *it != value ? last : it;
823}
824
825//_____________________________________________________________________________________________________
827{
828 if (first == last)
829 return last;
830
831 const int_iterator it = std::lower_bound(first, last, value);
832 assert((it == last || *it == value) && "internal logic error");
833
834 return it;
835}
836
837}//unnamed namespace.
838
839//_____________________________________________________________________________________________________
841{
842 //Input requirements:
843 // 1) all rects are valid (non-empty and x1 < x2, y1 < y2);
844 // 2) all rects intersect with widget's rect.
845 //I do not check these conditions here, this is done when filling rectsToClip.
846
847 //I did not find any reasonable algorithm (have to search better?),
848 //code in gdk and pixman has to many dependencies and is lib-specific +
849 //they require input to be quite special:
850 // a) no overlaps (in my case I have overlaps)
851 // b) sorted in a special way.
852 //To convert my input into such a format
853 //means to implement everything myself (for example, to work out overlaps).
854
855 //Also, my case is more simple: gdk and pixman substract region (== set of rectangles)
856 //from another region, I have to substract region from _one_ rectangle.
857
858 //This is quite straightforward implementation - I'm calculation rectangles, which are part of
859 //a widget's rect, not hidden by any of fRectsToClip.
860
861 typedef std::vector<WidgetRect>::const_iterator rect_const_iterator;
862
863 assert(fRectsToClip.size() != 0 && "BuildClipRegion, nothing to clip");
864
865 fClippedRegion.clear();
866 fXBounds.clear();
867 fYBounds.clear();
868
869 //[First, we "cut" the original rect into stripes.
871 for (; recIt != endIt; ++recIt) {
872 if (recIt->fX1 <= rect.fX1 && recIt->fX2 >= rect.fX2 &&
873 recIt->fY1 <= rect.fY1 && recIt->fY2 >= rect.fY2) {
874 //this rect completely overlaps our view, not need to calculate anything at all.
875 fClippedRegion.push_back(CGRectMake(0., 0., 0., 0.));
876 return;
877 }
878
879 if (recIt->fX1 > rect.fX1)//recIt->x1 is always < rect.x2 (input validation).
880 fXBounds.push_back(recIt->fX1);
881
882 if (recIt->fX2 < rect.fX2)//recIt->x2 is always > rect.x1 (input validation).
883 fXBounds.push_back(recIt->fX2);
884
885 if (recIt->fY1 > rect.fY1)
886 fYBounds.push_back(recIt->fY1);
887
888 if (recIt->fY2 < rect.fY2)
889 fYBounds.push_back(recIt->fY2);
890 }
891
892 std::sort(fXBounds.begin(), fXBounds.end());
893 std::sort(fYBounds.begin(), fYBounds.end());
894
895 //We do not need duplicates.
896 const int_iterator xBoundsEnd = std::unique(fXBounds.begin(), fXBounds.end());
897 const int_iterator yBoundsEnd = std::unique(fYBounds.begin(), fYBounds.end());
898 //Rectangle is now "cut into pieces"].
899
900 const size_type nXBands = size_type(xBoundsEnd - fXBounds.begin()) + 1;
901 const size_type nYBands = size_type(yBoundsEnd - fYBounds.begin()) + 1;
902
903 fGrid.assign(nXBands * nYBands, false);
904
905 //Mark the overlapped parts.
907 for (; recIt != endIt; ++recIt) {
908 const int_iterator left = BinarySearchLeft(fXBounds.begin(), xBoundsEnd, recIt->fX1);
909 const size_type firstXBand = left == xBoundsEnd ? 0 : left - fXBounds.begin() + 1;
910
911 const int_iterator right = BinarySearchRight(fXBounds.begin(), xBoundsEnd, recIt->fX2);
912 const size_type lastXBand = right - fXBounds.begin() + 1;
913
914 const int_iterator bottom = BinarySearchLeft(fYBounds.begin(), yBoundsEnd, recIt->fY1);
915 const size_type firstYBand = bottom == yBoundsEnd ? 0 : bottom - fYBounds.begin() + 1;
916
917 const int_iterator top = BinarySearchRight(fYBounds.begin(), yBoundsEnd, recIt->fY2);
918 const size_type lastYBand = top - fYBounds.begin() + 1;
919
920 for (size_type i = firstYBand; i < lastYBand; ++i) {
921 const size_type baseIndex = i * nXBands;
922 for (size_type j = firstXBand; j < lastXBand; ++j)
923 fGrid[baseIndex + j] = true;
924 }
925 }
926
927 //I do not merge rectangles.
928 //Search for non-overlapped parts and create rectangles for them.
929 CGRect newRect = {};
930
931 for (size_type i = 0; i < nYBands; ++i) {
932 const size_type baseIndex = i * nXBands;
933 for (size_type j = 0; j < nXBands; ++j) {
934 if (!fGrid[baseIndex + j]) {
935 newRect.origin.x = j ? fXBounds[j - 1] : rect.fX1;
936 newRect.origin.y = i ? fYBounds[i - 1] : rect.fY1;
937
938 newRect.size.width = (j == nXBands - 1 ? rect.fX2 : fXBounds[j]) - newRect.origin.x;
939 newRect.size.height = (i == nYBands - 1 ? rect.fY2 : fYBounds[i]) - newRect.origin.y;
940
941 fClippedRegion.push_back(newRect);
942 }
943 }
944 }
945
946 if (!fClippedRegion.size())//Completely hidden
947 fClippedRegion.push_back(CGRectMake(0., 0., 0., 0.));
948}
949
950}//X11
951}//MacOSX
952}//ROOT
Handle_t Pixmap_t
Pixmap handle.
Definition GuiTypes.h:31
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
Handle_t Drawable_t
Drawable handle.
Definition GuiTypes.h:32
@ kIsViewable
Definition GuiTypes.h:47
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
unsigned short UShort_t
Unsigned Short integer 2 bytes (unsigned short)
Definition RtypesCore.h:54
short SCoord_t
Screen coordinates (short)
Definition RtypesCore.h:100
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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 GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char 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 rect
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 child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t CopyArea
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char FillPolygon
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 UChar_t len
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 y2
Option_t Option_t TPoint TPoint const char DrawLine
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t FillRectangle
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 const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
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 GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void gc
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
#define gVirtualX
Definition TVirtualX.h:375
ClearArea(Window_t wid, const Rectangle_t &area)
Definition X11Buffer.mm:114
const Rectangle_t fArea
Definition X11Buffer.h:104
void Execute() const override
Definition X11Buffer.mm:121
std::vector< WidgetRect > fRectsToClip
Definition X11Buffer.h:332
std::vector< CGRect > fClippedRegion
Definition X11Buffer.h:333
std::vector< bool > fGrid
Definition X11Buffer.h:336
void Flush(Details::CocoaPrivate *impl)
Definition X11Buffer.mm:547
void AddDrawSegments(Drawable_t wid, const GCValues_t &gc, const Segment_t *segments, Int_t nSegments)
Definition X11Buffer.mm:400
void AddFillPolygon(Drawable_t wid, const GCValues_t &gc, const Point_t *polygon, Int_t nPoints)
Definition X11Buffer.mm:505
void ClipOverlaps(QuartzView *view)
Definition X11Buffer.mm:683
std::vector< QuartzView * > fViewBranch
Definition X11Buffer.h:282
void RemoveGraphicsOperationsForWindow(Window_t wid)
Definition X11Buffer.mm:640
void AddClearArea(Window_t wid, Int_t x, Int_t y, UInt_t w, UInt_t h)
Definition X11Buffer.mm:416
std::vector< int > fYBounds
Definition X11Buffer.h:335
void AddDrawRectangle(Drawable_t wid, const GCValues_t &gc, Int_t x, Int_t y, UInt_t w, UInt_t h)
Definition X11Buffer.mm:487
void AddDrawLine(Drawable_t wid, const GCValues_t &gc, Int_t x1, Int_t y1, Int_t x2, Int_t y2)
Definition X11Buffer.mm:386
void RemoveOperationsForDrawable(Drawable_t wid)
Definition X11Buffer.mm:629
std::vector< Command * >::size_type size_type
Definition X11Buffer.h:284
void AddDrawString(Drawable_t wid, const GCValues_t &gc, Int_t x, Int_t y, const char *text, Int_t len)
Definition X11Buffer.mm:453
void AddDeletePixmap(Pixmap_t pixmap)
Definition X11Buffer.mm:535
std::vector< Command * > fCommands
Definition X11Buffer.h:281
std::vector< int > fXBounds
Definition X11Buffer.h:334
void AddCopyArea(Drawable_t src, Drawable_t dst, const GCValues_t &gc, Int_t srcX, Int_t srcY, UInt_t width, UInt_t height, Int_t dstX, Int_t dstY)
Definition X11Buffer.mm:433
void AddUpdateWindow(QuartzView *view)
Definition X11Buffer.mm:521
void BuildClipRegion(const WidgetRect &rect)
Definition X11Buffer.mm:840
void AddFillRectangle(Drawable_t wid, const GCValues_t &gc, Int_t x, Int_t y, UInt_t w, UInt_t h)
Definition X11Buffer.mm:469
const GCValues_t fGC
Definition X11Buffer.h:53
Command(Drawable_t wid)
Definition X11Buffer.mm:48
const Drawable_t fID
Definition X11Buffer.h:52
virtual bool IsGraphicsCommand() const
Definition X11Buffer.mm:71
virtual void Execute() const =0
virtual bool HasOperand(Drawable_t drawable) const
Definition X11Buffer.mm:65
const Drawable_t fSrc
Definition X11Buffer.h:117
bool HasOperand(Drawable_t drawable) const override
Definition X11Buffer.mm:140
CopyArea(Drawable_t src, Drawable_t dst, const GCValues_t &gc, const Rectangle_t &area, const Point &dstPoint)
Definition X11Buffer.mm:130
const Rectangle_t fArea
Definition X11Buffer.h:118
void Execute() const override
Definition X11Buffer.mm:146
void Execute() const override
Definition X11Buffer.mm:258
void Execute() const override
Definition X11Buffer.h:225
DrawBoxXor(Window_t windowID, const Point &p1, const Point &p2)
Definition X11Buffer.mm:267
DrawLineXor(Window_t windowID, const Point &p1, const Point &p2)
Definition X11Buffer.mm:296
void Execute() const override
Definition X11Buffer.h:237
void Execute() const override
Definition X11Buffer.mm:85
DrawLine(Drawable_t wid, const GCValues_t &gc, const Point &p1, const Point &p2)
Definition X11Buffer.mm:77
void setPoints(Int_t n, TPoint *xy)
Definition X11Buffer.mm:353
std::vector< TPoint > fPnts
Definition X11Buffer.h:262
void Execute() const override
Definition X11Buffer.h:271
std::vector< TPoint > fPnts
Definition X11Buffer.h:246
void setPoints(Int_t n, TPoint *xy)
Definition X11Buffer.mm:322
void Execute() const override
Definition X11Buffer.h:255
DrawRectangle(Drawable_t wid, const GCValues_t &gc, const Rectangle_t &rectangle)
Definition X11Buffer.mm:215
void Execute() const override
Definition X11Buffer.mm:223
std::vector< Segment_t > fSegments
Definition X11Buffer.h:91
DrawSegments(Drawable_t wid, const GCValues_t &gc, const Segment_t *segments, Int_t nSegments)
Definition X11Buffer.mm:94
void Execute() const override
Definition X11Buffer.mm:105
DrawString(Drawable_t wid, const GCValues_t &gc, const Point &point, const std::string &text)
Definition X11Buffer.mm:157
void Execute() const override
Definition X11Buffer.mm:166
const std::string fText
Definition X11Buffer.h:137
std::vector< Point_t > fPolygon
Definition X11Buffer.h:167
void Execute() const override
Definition X11Buffer.mm:206
FillPolygon(Drawable_t wid, const GCValues_t &gc, const Point_t *points, Int_t nPoints)
Definition X11Buffer.mm:195
void Execute() const override
Definition X11Buffer.mm:184
FillRectangle(Drawable_t wid, const GCValues_t &gc, const Rectangle_t &rectangle)
Definition X11Buffer.mm:176
void Execute() const override
Definition X11Buffer.mm:242
UpdateWindow(QuartzView *view)
Definition X11Buffer.mm:234
const_iterator begin() const
const_iterator end() const
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:37
This class implements TVirtualX interface for MacOS X, using Cocoa and Quartz 2D.
Definition TGCocoa.h:57
SCoord_t fY
Definition TPoint.h:36
SCoord_t fX
Definition TPoint.h:35
TLine * line
unsigned fHeight
unsigned fWidth
QuartzPixmap * fBackBuffer
QuartzWindow * fQuartzWindow
CGContextRef fContext
QuartzView * fParentView
QuartzImage * fShapeCombineMask
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
const auto rootToNs
Definition X11Buffer.mm:280
void ClipToShapeMask(NSView< X11Window > *view, CGContextRef ctx)
Bool_t SetLineColor(CGContextRef ctx, Color_t colorIndex)
Definition QuartzLine.mm:29
void DrawPolyMarker(CGContextRef ctx, unsigned nPoints, const TPoint *marker, const TAttMarker &attmark, float scaleFactor)
void DrawPolyLine(CGContextRef ctx, Int_t n, const TPoint *xy)
void SetLineWidth(CGContextRef ctx, Int_t width)
void SetLineStyle(CGContextRef ctx, Int_t lstyle)
Definition QuartzLine.mm:75
Graphics context structure.
Definition GuiTypes.h:225
Point structure (maps to the X11 XPoint structure)
Definition GuiTypes.h:357
Rectangle structure (maps to the X11 XRectangle structure)
Definition GuiTypes.h:362
Short_t fX
Definition GuiTypes.h:363
UShort_t fHeight
Definition GuiTypes.h:364
Short_t fY
Definition GuiTypes.h:363
UShort_t fWidth
Definition GuiTypes.h:364
Used for drawing line segments (maps to the X11 XSegments structure)
Definition GuiTypes.h:352