Add remaining files
[juce-lv2.git] / juce / source / src / gui / graphics / geometry / juce_RectangleList.cpp
blob1a65e4ec4356c7fda11f1b0e5e2566e3049549ab
1 /*
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"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_RectangleList.h"
33 //==============================================================================
34 RectangleList::RectangleList() noexcept
38 RectangleList::RectangleList (const Rectangle<int>& rect)
40 if (! rect.isEmpty())
41 rects.add (rect);
44 RectangleList::RectangleList (const RectangleList& other)
45 : rects (other.rects)
49 RectangleList& RectangleList::operator= (const RectangleList& other)
51 rects = other.rects;
52 return *this;
55 RectangleList::~RectangleList()
59 //==============================================================================
60 void RectangleList::clear()
62 rects.clearQuick();
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
80 : current (nullptr),
81 owner (list),
82 index (list.rects.size())
86 RectangleList::Iterator::~Iterator()
90 bool RectangleList::Iterator::next() noexcept
92 if (--index >= 0)
94 current = & (owner.rects.getReference (index));
95 return true;
98 return false;
102 //==============================================================================
103 void RectangleList::add (const Rectangle<int>& rect)
105 if (! rect.isEmpty())
107 if (rects.size() == 0)
109 rects.add (rect);
111 else
113 bool anyOverlaps = false;
115 int i;
116 for (i = rects.size(); --i >= 0;)
118 Rectangle<int>& ourRect = rects.getReference (i);
120 if (rect.intersects (ourRect))
122 if (rect.contains (ourRect))
123 rects.remove (i);
124 else if (! ourRect.reduceIfPartlyContainedIn (rect))
125 anyOverlaps = true;
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)
142 return;
146 for (i = r.getNumRectangles(); --i >= 0;)
147 rects.add (r.rects.getReference (i));
149 else
151 rects.add (rect);
157 void RectangleList::addWithoutMerging (const Rectangle<int>& rect)
159 if (! rect.isEmpty())
160 rects.add (rect);
163 void RectangleList::add (const int x, const int y, const int w, const int h)
165 if (rects.size() == 0)
167 if (w > 0 && h > 0)
168 rects.add (Rectangle<int> (x, y, w, h));
170 else
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);
197 const int rx1 = r.x;
198 const int ry1 = r.y;
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)
208 r.w = x1 - rx1;
210 else
212 r.x = x1;
213 r.w = rx2 - x1;
215 rects.insert (i + 1, Rectangle<int> (rx1, ry1, x1 - rx1, ry2 - ry1));
216 i += 2;
219 else if (x2 > rx1 && x2 < rx2)
221 r.x = x2;
222 r.w = rx2 - x2;
224 if (y1 > ry1 || y2 < ry2 || x1 > rx1)
226 rects.insert (i + 1, Rectangle<int> (rx1, ry1, x2 - rx1, ry2 - ry1));
227 i += 2;
230 else if (y1 > ry1 && y1 < ry2)
232 if (x1 <= rx1 && x2 >= rx2 && y2 >= ry2)
234 r.h = y1 - ry1;
236 else
238 r.y = y1;
239 r.h = ry2 - y1;
241 rects.insert (i + 1, Rectangle<int> (rx1, ry1, rx2 - rx1, y1 - ry1));
242 i += 2;
245 else if (y2 > ry1 && y2 < ry2)
247 r.y = y2;
248 r.h = ry2 - y2;
250 if (x1 > rx1 || x2 < rx2 || y1 > ry1)
252 rects.insert (i + 1, Rectangle<int> (rx1, ry1, rx2 - rx1, y2 - ry1));
253 i += 2;
256 else
258 rects.remove (i);
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;
277 if (rect.isEmpty())
279 clear();
281 else
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))
288 rects.remove (i);
289 else
290 notEmpty = true;
294 return notEmpty;
297 bool RectangleList::clipTo (const RectangleList& other)
299 if (rects.size() == 0)
300 return false;
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);
317 swapWith (result);
319 return ! isEmpty();
322 bool RectangleList::getIntersectionWith (const Rectangle<int>& rect, RectangleList& destRegion) const
324 destRegion.clear();
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()
349 int i;
350 for (i = 0; i < getNumRectangles() - 1; ++i)
352 Rectangle<int>& r = rects.getReference (i);
353 const int rx1 = r.x;
354 const int ry1 = r.y;
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)
372 r.h = jry1 - ry1;
373 rects.add (Rectangle<int> (rx1, jry1, rx2 - rx1, ry2 - jry1));
374 i = -1;
375 break;
378 if (jry2 > ry1 && jry2 < ry2)
380 r.h = jry2 - ry1;
381 rects.add (Rectangle<int> (rx1, jry2, rx2 - rx1, ry2 - jry2));
382 i = -1;
383 break;
385 else if (ry1 > jry1 && ry1 < jry2)
387 r2.h = ry1 - jry1;
388 rects.add (Rectangle<int> (jrx1, ry1, jrx2 - jrx1, jry2 - ry1));
389 i = -1;
390 break;
392 else if (ry2 > jry1 && ry2 < jry2)
394 r2.h = ry2 - jry1;
395 rects.add (Rectangle<int> (jrx1, ry2, jrx2 - jrx1, jry2 - ry2));
396 i = -1;
397 break;
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)))
411 rects.remove (j);
412 i = -1;
413 break;
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))
424 return true;
426 return false;
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)
440 return true;
443 else if (rects.size() > 0)
445 return rects.getReference (0).contains (rectangleToCheck);
448 return false;
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))
455 return true;
457 return false;
460 bool RectangleList::intersects (const RectangleList& other) const noexcept
462 for (int i = rects.size(); --i >= 0;)
463 if (other.intersectsRectangle (rects.getReference (i)))
464 return true;
466 return false;
469 Rectangle<int> RectangleList::getBounds() const noexcept
471 if (rects.size() <= 1)
473 if (rects.size() == 0)
474 return Rectangle<int>();
475 else
476 return rects.getReference (0);
478 else
480 const Rectangle<int>& r = rects.getReference (0);
482 int minX = r.x;
483 int minY = r.y;
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);
507 r.x += dx;
508 r.y += dy;
512 //==============================================================================
513 Path RectangleList::toPath() const
515 Path p;
517 for (int i = rects.size(); --i >= 0;)
519 const Rectangle<int>& r = rects.getReference (i);
521 p.addRectangle ((float) r.x,
522 (float) r.y,
523 (float) r.w,
524 (float) r.h);
527 return p;
531 END_JUCE_NAMESPACE