2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../../core/juce_StandardHeader.h"
30 #include "juce_RectangleList.h"
33 //==============================================================================
34 RectangleList::RectangleList() noexcept
38 RectangleList::RectangleList (const Rectangle
<int>& rect
)
44 RectangleList::RectangleList (const RectangleList
& other
)
49 RectangleList
& RectangleList::operator= (const RectangleList
& other
)
55 RectangleList::~RectangleList()
59 //==============================================================================
60 void RectangleList::clear()
65 Rectangle
<int> RectangleList::getRectangle (const int index
) const noexcept
67 if (isPositiveAndBelow (index
, rects
.size()))
68 return rects
.getReference (index
);
70 return Rectangle
<int>();
73 bool RectangleList::isEmpty() const noexcept
75 return rects
.size() == 0;
78 //==============================================================================
79 RectangleList::Iterator::Iterator (const RectangleList
& list
) noexcept
82 index (list
.rects
.size())
86 RectangleList::Iterator::~Iterator()
90 bool RectangleList::Iterator::next() noexcept
94 current
= & (owner
.rects
.getReference (index
));
102 //==============================================================================
103 void RectangleList::add (const Rectangle
<int>& rect
)
105 if (! rect
.isEmpty())
107 if (rects
.size() == 0)
113 bool anyOverlaps
= false;
116 for (i
= rects
.size(); --i
>= 0;)
118 Rectangle
<int>& ourRect
= rects
.getReference (i
);
120 if (rect
.intersects (ourRect
))
122 if (rect
.contains (ourRect
))
124 else if (! ourRect
.reduceIfPartlyContainedIn (rect
))
129 if (anyOverlaps
&& rects
.size() > 0)
131 RectangleList
r (rect
);
133 for (i
= rects
.size(); --i
>= 0;)
135 const Rectangle
<int>& ourRect
= rects
.getReference (i
);
137 if (rect
.intersects (ourRect
))
139 r
.subtract (ourRect
);
141 if (r
.rects
.size() == 0)
146 for (i
= r
.getNumRectangles(); --i
>= 0;)
147 rects
.add (r
.rects
.getReference (i
));
157 void RectangleList::addWithoutMerging (const Rectangle
<int>& rect
)
159 if (! rect
.isEmpty())
163 void RectangleList::add (const int x
, const int y
, const int w
, const int h
)
165 if (rects
.size() == 0)
168 rects
.add (Rectangle
<int> (x
, y
, w
, h
));
172 add (Rectangle
<int> (x
, y
, w
, h
));
176 void RectangleList::add (const RectangleList
& other
)
178 for (int i
= 0; i
< other
.rects
.size(); ++i
)
179 add (other
.rects
.getReference (i
));
182 void RectangleList::subtract (const Rectangle
<int>& rect
)
184 const int originalNumRects
= rects
.size();
186 if (originalNumRects
> 0)
188 const int x1
= rect
.x
;
189 const int y1
= rect
.y
;
190 const int x2
= x1
+ rect
.w
;
191 const int y2
= y1
+ rect
.h
;
193 for (int i
= getNumRectangles(); --i
>= 0;)
195 Rectangle
<int>& r
= rects
.getReference (i
);
199 const int rx2
= rx1
+ r
.w
;
200 const int ry2
= ry1
+ r
.h
;
202 if (! (x2
<= rx1
|| x1
>= rx2
|| y2
<= ry1
|| y1
>= ry2
))
204 if (x1
> rx1
&& x1
< rx2
)
206 if (y1
<= ry1
&& y2
>= ry2
&& x2
>= rx2
)
215 rects
.insert (i
+ 1, Rectangle
<int> (rx1
, ry1
, x1
- rx1
, ry2
- ry1
));
219 else if (x2
> rx1
&& x2
< rx2
)
224 if (y1
> ry1
|| y2
< ry2
|| x1
> rx1
)
226 rects
.insert (i
+ 1, Rectangle
<int> (rx1
, ry1
, x2
- rx1
, ry2
- ry1
));
230 else if (y1
> ry1
&& y1
< ry2
)
232 if (x1
<= rx1
&& x2
>= rx2
&& y2
>= ry2
)
241 rects
.insert (i
+ 1, Rectangle
<int> (rx1
, ry1
, rx2
- rx1
, y1
- ry1
));
245 else if (y2
> ry1
&& y2
< ry2
)
250 if (x1
> rx1
|| x2
< rx2
|| y1
> ry1
)
252 rects
.insert (i
+ 1, Rectangle
<int> (rx1
, ry1
, rx2
- rx1
, y2
- ry1
));
265 bool RectangleList::subtract (const RectangleList
& otherList
)
267 for (int i
= otherList
.rects
.size(); --i
>= 0 && rects
.size() > 0;)
268 subtract (otherList
.rects
.getReference (i
));
270 return rects
.size() > 0;
273 bool RectangleList::clipTo (const Rectangle
<int>& rect
)
275 bool notEmpty
= false;
283 for (int i
= rects
.size(); --i
>= 0;)
285 Rectangle
<int>& r
= rects
.getReference (i
);
287 if (! rect
.intersectRectangle (r
.x
, r
.y
, r
.w
, r
.h
))
297 bool RectangleList::clipTo (const RectangleList
& other
)
299 if (rects
.size() == 0)
302 RectangleList result
;
304 for (int j
= 0; j
< rects
.size(); ++j
)
306 const Rectangle
<int>& rect
= rects
.getReference (j
);
308 for (int i
= other
.rects
.size(); --i
>= 0;)
310 Rectangle
<int> r (other
.rects
.getReference (i
));
312 if (rect
.intersectRectangle (r
.x
, r
.y
, r
.w
, r
.h
))
313 result
.rects
.add (r
);
322 bool RectangleList::getIntersectionWith (const Rectangle
<int>& rect
, RectangleList
& destRegion
) const
326 if (! rect
.isEmpty())
328 for (int i
= rects
.size(); --i
>= 0;)
330 Rectangle
<int> r (rects
.getReference (i
));
332 if (rect
.intersectRectangle (r
.x
, r
.y
, r
.w
, r
.h
))
333 destRegion
.rects
.add (r
);
337 return destRegion
.rects
.size() > 0;
340 void RectangleList::swapWith (RectangleList
& otherList
) noexcept
342 rects
.swapWithArray (otherList
.rects
);
346 //==============================================================================
347 void RectangleList::consolidate()
350 for (i
= 0; i
< getNumRectangles() - 1; ++i
)
352 Rectangle
<int>& r
= rects
.getReference (i
);
355 const int rx2
= rx1
+ r
.w
;
356 const int ry2
= ry1
+ r
.h
;
358 for (int j
= rects
.size(); --j
> i
;)
360 Rectangle
<int>& r2
= rects
.getReference (j
);
361 const int jrx1
= r2
.x
;
362 const int jry1
= r2
.y
;
363 const int jrx2
= jrx1
+ r2
.w
;
364 const int jry2
= jry1
+ r2
.h
;
366 // if the vertical edges of any blocks are touching and their horizontals don't
367 // line up, split them horizontally..
368 if (jrx1
== rx2
|| jrx2
== rx1
)
370 if (jry1
> ry1
&& jry1
< ry2
)
373 rects
.add (Rectangle
<int> (rx1
, jry1
, rx2
- rx1
, ry2
- jry1
));
378 if (jry2
> ry1
&& jry2
< ry2
)
381 rects
.add (Rectangle
<int> (rx1
, jry2
, rx2
- rx1
, ry2
- jry2
));
385 else if (ry1
> jry1
&& ry1
< jry2
)
388 rects
.add (Rectangle
<int> (jrx1
, ry1
, jrx2
- jrx1
, jry2
- ry1
));
392 else if (ry2
> jry1
&& ry2
< jry2
)
395 rects
.add (Rectangle
<int> (jrx1
, ry2
, jrx2
- jrx1
, jry2
- ry2
));
403 for (i
= 0; i
< rects
.size() - 1; ++i
)
405 Rectangle
<int>& r
= rects
.getReference (i
);
407 for (int j
= rects
.size(); --j
> i
;)
409 if (r
.enlargeIfAdjacent (rects
.getReference (j
)))
419 //==============================================================================
420 bool RectangleList::containsPoint (const int x
, const int y
) const noexcept
422 for (int i
= getNumRectangles(); --i
>= 0;)
423 if (rects
.getReference (i
).contains (x
, y
))
429 bool RectangleList::containsRectangle (const Rectangle
<int>& rectangleToCheck
) const
431 if (rects
.size() > 1)
433 RectangleList
r (rectangleToCheck
);
435 for (int i
= rects
.size(); --i
>= 0;)
437 r
.subtract (rects
.getReference (i
));
439 if (r
.rects
.size() == 0)
443 else if (rects
.size() > 0)
445 return rects
.getReference (0).contains (rectangleToCheck
);
451 bool RectangleList::intersectsRectangle (const Rectangle
<int>& rectangleToCheck
) const noexcept
453 for (int i
= rects
.size(); --i
>= 0;)
454 if (rects
.getReference (i
).intersects (rectangleToCheck
))
460 bool RectangleList::intersects (const RectangleList
& other
) const noexcept
462 for (int i
= rects
.size(); --i
>= 0;)
463 if (other
.intersectsRectangle (rects
.getReference (i
)))
469 Rectangle
<int> RectangleList::getBounds() const noexcept
471 if (rects
.size() <= 1)
473 if (rects
.size() == 0)
474 return Rectangle
<int>();
476 return rects
.getReference (0);
480 const Rectangle
<int>& r
= rects
.getReference (0);
484 int maxX
= minX
+ r
.w
;
485 int maxY
= minY
+ r
.h
;
487 for (int i
= rects
.size(); --i
> 0;)
489 const Rectangle
<int>& r2
= rects
.getReference (i
);
491 minX
= jmin (minX
, r2
.x
);
492 minY
= jmin (minY
, r2
.y
);
493 maxX
= jmax (maxX
, r2
.getRight());
494 maxY
= jmax (maxY
, r2
.getBottom());
497 return Rectangle
<int> (minX
, minY
, maxX
- minX
, maxY
- minY
);
501 void RectangleList::offsetAll (const int dx
, const int dy
) noexcept
503 for (int i
= rects
.size(); --i
>= 0;)
505 Rectangle
<int>& r
= rects
.getReference (i
);
512 //==============================================================================
513 Path
RectangleList::toPath() const
517 for (int i
= rects
.size(); --i
>= 0;)
519 const Rectangle
<int>& r
= rects
.getReference (i
);
521 p
.addRectangle ((float) r
.x
,