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