openshot-audio  0.1.2
juce_RectangleList.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2015 - ROLI Ltd.
6 
7  Permission is granted to use this software under the terms of either:
8  a) the GPL v2 (or any later version)
9  b) the Affero GPL v3
10 
11  Details of these licenses can be found at: www.gnu.org/licenses
12 
13  JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15  A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 
17  ------------------------------------------------------------------------------
18 
19  To release a closed-source product which uses JUCE, commercial licenses are
20  available: visit www.juce.com for more information.
21 
22  ==============================================================================
23 */
24 
25 #ifndef JUCE_RECTANGLELIST_H_INCLUDED
26 #define JUCE_RECTANGLELIST_H_INCLUDED
27 
28 
29 //==============================================================================
39 template <typename ValueType>
41 {
42 public:
44 
45  //==============================================================================
48 
50  RectangleList (const RectangleList& other) : rects (other.rects)
51  {
52  }
53 
55  RectangleList (const RectangleType& rect)
56  {
57  addWithoutMerging (rect);
58  }
59 
62  {
63  rects = other.rects;
64  return *this;
65  }
66 
67  #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
69  : rects (static_cast<Array<RectangleType>&&> (other.rects))
70  {
71  }
72 
74  {
75  rects = static_cast<Array<RectangleType>&&> (other.rects);
76  return *this;
77  }
78  #endif
79 
80  //==============================================================================
82  bool isEmpty() const noexcept { return rects.size() == 0; }
83 
85  int getNumRectangles() const noexcept { return rects.size(); }
86 
90  RectangleType getRectangle (int index) const noexcept { return rects[index]; }
91 
92  //==============================================================================
94  void clear()
95  {
96  rects.clearQuick();
97  }
98 
108  void add (const RectangleType& rect)
109  {
110  jassert (rect.isFinite()); // You must provide a valid rectangle to this method!
111 
112  if (! rect.isEmpty())
113  {
114  if (rects.size() == 0)
115  {
116  rects.add (rect);
117  }
118  else
119  {
120  bool anyOverlaps = false;
121 
122  for (int j = rects.size(); --j >= 0;)
123  {
124  RectangleType& ourRect = rects.getReference (j);
125 
126  if (rect.intersects (ourRect))
127  {
128  if (rect.contains (ourRect))
129  rects.remove (j);
130  else if (! ourRect.reduceIfPartlyContainedIn (rect))
131  anyOverlaps = true;
132  }
133  }
134 
135  if (anyOverlaps && rects.size() > 0)
136  {
137  RectangleList r (rect);
138 
139  for (int i = rects.size(); --i >= 0;)
140  {
141  const RectangleType& ourRect = rects.getReference (i);
142 
143  if (rect.intersects (ourRect))
144  {
145  r.subtract (ourRect);
146 
147  if (r.rects.size() == 0)
148  return;
149  }
150  }
151 
152  rects.addArray (r.rects);
153  }
154  else
155  {
156  rects.add (rect);
157  }
158  }
159  }
160  }
161 
167  void add (ValueType x, ValueType y, ValueType width, ValueType height)
168  {
169  add (RectangleType (x, y, width, height));
170  }
171 
180  void addWithoutMerging (const RectangleType& rect)
181  {
182  jassert (rect.isFinite()); // You must provide a valid rectangle to this method!
183 
184  if (! rect.isEmpty())
185  rects.add (rect);
186  }
187 
193  void add (const RectangleList& other)
194  {
195  for (const RectangleType* r = other.begin(), * const e = other.end(); r != e; ++r)
196  add (*r);
197  }
198 
204  void subtract (const RectangleType& rect)
205  {
206  const int originalNumRects = rects.size();
207 
208  if (originalNumRects > 0)
209  {
210  const ValueType x1 = rect.getX();
211  const ValueType y1 = rect.getY();
212  const ValueType x2 = x1 + rect.getWidth();
213  const ValueType y2 = y1 + rect.getHeight();
214 
215  for (int i = getNumRectangles(); --i >= 0;)
216  {
217  RectangleType& r = rects.getReference (i);
218 
219  const ValueType rx1 = r.getX();
220  const ValueType ry1 = r.getY();
221  const ValueType rx2 = rx1 + r.getWidth();
222  const ValueType ry2 = ry1 + r.getHeight();
223 
224  if (! (x2 <= rx1 || x1 >= rx2 || y2 <= ry1 || y1 >= ry2))
225  {
226  if (x1 > rx1 && x1 < rx2)
227  {
228  if (y1 <= ry1 && y2 >= ry2 && x2 >= rx2)
229  {
230  r.setWidth (x1 - rx1);
231  }
232  else
233  {
234  r.setX (x1);
235  r.setWidth (rx2 - x1);
236 
237  rects.insert (++i, RectangleType (rx1, ry1, x1 - rx1, ry2 - ry1));
238  ++i;
239  }
240  }
241  else if (x2 > rx1 && x2 < rx2)
242  {
243  r.setX (x2);
244  r.setWidth (rx2 - x2);
245 
246  if (y1 > ry1 || y2 < ry2 || x1 > rx1)
247  {
248  rects.insert (++i, RectangleType (rx1, ry1, x2 - rx1, ry2 - ry1));
249  ++i;
250  }
251  }
252  else if (y1 > ry1 && y1 < ry2)
253  {
254  if (x1 <= rx1 && x2 >= rx2 && y2 >= ry2)
255  {
256  r.setHeight (y1 - ry1);
257  }
258  else
259  {
260  r.setY (y1);
261  r.setHeight (ry2 - y1);
262 
263  rects.insert (++i, RectangleType (rx1, ry1, rx2 - rx1, y1 - ry1));
264  ++i;
265  }
266  }
267  else if (y2 > ry1 && y2 < ry2)
268  {
269  r.setY (y2);
270  r.setHeight (ry2 - y2);
271 
272  if (x1 > rx1 || x2 < rx2 || y1 > ry1)
273  {
274  rects.insert (++i, RectangleType (rx1, ry1, rx2 - rx1, y2 - ry1));
275  ++i;
276  }
277  }
278  else
279  {
280  rects.remove (i);
281  }
282  }
283  }
284  }
285  }
286 
294  bool subtract (const RectangleList& otherList)
295  {
296  for (int i = otherList.rects.size(); --i >= 0 && rects.size() > 0;)
297  subtract (otherList.rects.getReference (i));
298 
299  return rects.size() > 0;
300  }
301 
311  bool clipTo (const RectangleType& rect)
312  {
313  jassert (rect.isFinite()); // You must provide a valid rectangle to this method!
314 
315  bool notEmpty = false;
316 
317  if (rect.isEmpty())
318  {
319  clear();
320  }
321  else
322  {
323  for (int i = rects.size(); --i >= 0;)
324  {
325  RectangleType& r = rects.getReference (i);
326 
327  if (! rect.intersectRectangle (r))
328  rects.remove (i);
329  else
330  notEmpty = true;
331  }
332  }
333 
334  return notEmpty;
335  }
336 
346  template <typename OtherValueType>
348  {
349  if (rects.size() == 0)
350  return false;
351 
352  RectangleList result;
353 
354  for (int j = 0; j < rects.size(); ++j)
355  {
356  const RectangleType& rect = rects.getReference (j);
357 
358  for (const Rectangle<OtherValueType>* r = other.begin(), * const e = other.end(); r != e; ++r)
359  {
360  RectangleType clipped (r->template toType<ValueType>());
361 
362  if (rect.intersectRectangle (clipped))
363  result.rects.add (clipped);
364  }
365  }
366 
367  swapWith (result);
368  return ! isEmpty();
369  }
370 
380  bool getIntersectionWith (const RectangleType& rect, RectangleList& destRegion) const
381  {
382  jassert (rect.isFinite()); // You must provide a valid rectangle to this method!
383 
384  destRegion.clear();
385 
386  if (! rect.isEmpty())
387  {
388  for (int i = rects.size(); --i >= 0;)
389  {
390  RectangleType r (rects.getReference (i));
391 
392  if (rect.intersectRectangle (r))
393  destRegion.rects.add (r);
394  }
395  }
396 
397  return destRegion.rects.size() > 0;
398  }
399 
405  void swapWith (RectangleList& otherList) noexcept
406  {
407  rects.swapWith (otherList.rects);
408  }
409 
410  //==============================================================================
415  {
416  for (const RectangleType* r = rects.begin(), * const e = rects.end(); r != e; ++r)
417  if (r->contains (point))
418  return true;
419 
420  return false;
421  }
422 
426  bool containsPoint (ValueType x, ValueType y) const noexcept
427  {
428  return containsPoint (Point<ValueType> (x, y));
429  }
430 
437  bool containsRectangle (const RectangleType& rectangleToCheck) const
438  {
439  if (rects.size() > 1)
440  {
441  RectangleList r (rectangleToCheck);
442 
443  for (int i = rects.size(); --i >= 0;)
444  {
445  r.subtract (rects.getReference (i));
446 
447  if (r.rects.size() == 0)
448  return true;
449  }
450  }
451  else if (rects.size() > 0)
452  {
453  return rects.getReference (0).contains (rectangleToCheck);
454  }
455 
456  return false;
457  }
458 
465  bool intersectsRectangle (const RectangleType& rectangleToCheck) const noexcept
466  {
467  for (const RectangleType* r = rects.begin(), * const e = rects.end(); r != e; ++r)
468  if (r->intersects (rectangleToCheck))
469  return true;
470 
471  return false;
472  }
473 
478  bool intersects (const RectangleList& other) const noexcept
479  {
480  for (const RectangleType* r = rects.begin(), * const e = rects.end(); r != e; ++r)
481  if (other.intersectsRectangle (*r))
482  return true;
483 
484  return false;
485  }
486 
487  //==============================================================================
489  RectangleType getBounds() const noexcept
490  {
491  if (rects.size() <= 1)
492  {
493  if (rects.size() == 0)
494  return RectangleType();
495 
496  return rects.getReference (0);
497  }
498 
499  const RectangleType& r = rects.getReference (0);
500 
501  ValueType minX = r.getX();
502  ValueType minY = r.getY();
503  ValueType maxX = minX + r.getWidth();
504  ValueType maxY = minY + r.getHeight();
505 
506  for (int i = rects.size(); --i > 0;)
507  {
508  const RectangleType& r2 = rects.getReference (i);
509 
510  minX = jmin (minX, r2.getX());
511  minY = jmin (minY, r2.getY());
512  maxX = jmax (maxX, r2.getRight());
513  maxY = jmax (maxY, r2.getBottom());
514  }
515 
516  return RectangleType (minX, minY, maxX - minX, maxY - minY);
517  }
518 
525  void consolidate()
526  {
527  for (int i = 0; i < getNumRectangles() - 1; ++i)
528  {
529  RectangleType& r = rects.getReference (i);
530  const ValueType rx1 = r.getX();
531  const ValueType ry1 = r.getY();
532  const ValueType rx2 = rx1 + r.getWidth();
533  const ValueType ry2 = ry1 + r.getHeight();
534 
535  for (int j = rects.size(); --j > i;)
536  {
537  RectangleType& r2 = rects.getReference (j);
538  const ValueType jrx1 = r2.getX();
539  const ValueType jry1 = r2.getY();
540  const ValueType jrx2 = jrx1 + r2.getWidth();
541  const ValueType jry2 = jry1 + r2.getHeight();
542 
543  // if the vertical edges of any blocks are touching and their horizontals don't
544  // line up, split them horizontally..
545  if (jrx1 == rx2 || jrx2 == rx1)
546  {
547  if (jry1 > ry1 && jry1 < ry2)
548  {
549  r.setHeight (jry1 - ry1);
550  rects.add (RectangleType (rx1, jry1, rx2 - rx1, ry2 - jry1));
551  i = -1;
552  break;
553  }
554 
555  if (jry2 > ry1 && jry2 < ry2)
556  {
557  r.setHeight (jry2 - ry1);
558  rects.add (RectangleType (rx1, jry2, rx2 - rx1, ry2 - jry2));
559  i = -1;
560  break;
561  }
562  else if (ry1 > jry1 && ry1 < jry2)
563  {
564  r2.setHeight (ry1 - jry1);
565  rects.add (RectangleType (jrx1, ry1, jrx2 - jrx1, jry2 - ry1));
566  i = -1;
567  break;
568  }
569  else if (ry2 > jry1 && ry2 < jry2)
570  {
571  r2.setHeight (ry2 - jry1);
572  rects.add (RectangleType (jrx1, ry2, jrx2 - jrx1, jry2 - ry2));
573  i = -1;
574  break;
575  }
576  }
577  }
578  }
579 
580  for (int i = 0; i < rects.size() - 1; ++i)
581  {
582  RectangleType& r = rects.getReference (i);
583 
584  for (int j = rects.size(); --j > i;)
585  {
586  if (r.enlargeIfAdjacent (rects.getReference (j)))
587  {
588  rects.remove (j);
589  i = -1;
590  break;
591  }
592  }
593  }
594  }
595 
598  {
599  for (RectangleType* r = rects.begin(), * const e = rects.end(); r != e; ++r)
600  *r += offset;
601  }
602 
604  void offsetAll (ValueType dx, ValueType dy) noexcept
605  {
606  offsetAll (Point<ValueType> (dx, dy));
607  }
608 
610  template <typename ScaleType>
611  void scaleAll (ScaleType scaleFactor) noexcept
612  {
613  for (RectangleType* r = rects.begin(), * const e = rects.end(); r != e; ++r)
614  *r *= scaleFactor;
615  }
616 
621  void transformAll (const AffineTransform& transform) noexcept
622  {
623  for (RectangleType* r = rects.begin(), * const e = rects.end(); r != e; ++r)
624  *r = r->transformedBy (transform);
625  }
626 
627  //==============================================================================
629  Path toPath() const
630  {
631  Path p;
632 
633  for (int i = 0; i < rects.size(); ++i)
634  p.addRectangle (rects.getReference (i));
635 
636  return p;
637  }
638 
639  //==============================================================================
641  const RectangleType* begin() const noexcept { return rects.begin(); }
643  const RectangleType* end() const noexcept { return rects.end(); }
644 
651  void ensureStorageAllocated (int minNumRectangles)
652  {
653  rects.ensureStorageAllocated (minNumRectangles);
654  }
655 
656 private:
657  //==============================================================================
658  Array<RectangleType> rects;
659 };
660 
661 
662 #endif // JUCE_RECTANGLELIST_H_INCLUDED
ValueType getWidth() const noexcept
Definition: juce_Rectangle.h:113
bool clipTo(const RectangleList< OtherValueType > &other)
Definition: juce_RectangleList.h:347
void subtract(const RectangleType &rect)
Definition: juce_RectangleList.h:204
ValueType getRight() const noexcept
Definition: juce_Rectangle.h:119
void consolidate()
Definition: juce_RectangleList.h:525
void setHeight(ValueType newHeight) noexcept
Definition: juce_Rectangle.h:184
RectangleList & operator=(const RectangleList &other)
Definition: juce_RectangleList.h:61
bool containsRectangle(const RectangleType &rectangleToCheck) const
Definition: juce_RectangleList.h:437
void offsetAll(Point< ValueType > offset) noexcept
Definition: juce_RectangleList.h:597
#define noexcept
Definition: juce_CompilerSupport.h:141
bool reduceIfPartlyContainedIn(const Rectangle &other) noexcept
Definition: juce_Rectangle.h:708
ValueType getX() const noexcept
Definition: juce_Rectangle.h:107
bool intersects(const RectangleList &other) const noexcept
Definition: juce_RectangleList.h:478
void ensureStorageAllocated(int minNumRectangles)
Definition: juce_RectangleList.h:651
ValueType getHeight() const noexcept
Definition: juce_Rectangle.h:116
Type jmin(const Type a, const Type b)
Definition: juce_core.h:113
void offsetAll(ValueType dx, ValueType dy) noexcept
Definition: juce_RectangleList.h:604
Definition: juce_RectangleList.h:40
RectangleList() noexcept
Definition: juce_RectangleList.h:47
bool intersects(const Rectangle &other) const noexcept
Definition: juce_Rectangle.h:586
bool intersectsRectangle(const RectangleType &rectangleToCheck) const noexcept
Definition: juce_RectangleList.h:465
bool contains(ValueType xCoord, ValueType yCoord) const noexcept
Definition: juce_Rectangle.h:549
Definition: juce_Point.h:39
Path toPath() const
Definition: juce_RectangleList.h:629
void clear()
Definition: juce_RectangleList.h:94
bool getIntersectionWith(const RectangleType &rect, RectangleList &destRegion) const
Definition: juce_RectangleList.h:380
Rectangle< ValueType > RectangleType
Definition: juce_RectangleList.h:43
void addWithoutMerging(const RectangleType &rect)
Definition: juce_RectangleList.h:180
#define const
void add(ValueType x, ValueType y, ValueType width, ValueType height)
Definition: juce_RectangleList.h:167
void transformAll(const AffineTransform &transform) noexcept
Definition: juce_RectangleList.h:621
ValueType getBottom() const noexcept
Definition: juce_Rectangle.h:122
RectangleType getRectangle(int index) const noexcept
Definition: juce_RectangleList.h:90
void setX(ValueType newX) noexcept
Definition: juce_Rectangle.h:175
RectangleList(const RectangleType &rect)
Definition: juce_RectangleList.h:55
Definition: juce_Rectangle.h:36
void addRectangle(float x, float y, float width, float height)
Definition: juce_Path.cpp:399
Definition: juce_Path.h:62
const RectangleType * begin() const noexcept
Definition: juce_RectangleList.h:641
bool isFinite() const noexcept
Definition: juce_Rectangle.h:104
void add(const RectangleList &other)
Definition: juce_RectangleList.h:193
void setY(ValueType newY) noexcept
Definition: juce_Rectangle.h:178
int getNumRectangles() const noexcept
Definition: juce_RectangleList.h:85
bool isEmpty() const noexcept
Definition: juce_RectangleList.h:82
bool intersectRectangle(ValueType &otherX, ValueType &otherY, ValueType &otherW, ValueType &otherH) const noexcept
Definition: juce_Rectangle.h:626
Type jmax(const Type a, const Type b)
Definition: juce_core.h:101
bool enlargeIfAdjacent(const Rectangle &other) noexcept
Definition: juce_Rectangle.h:679
const RectangleType * end() const noexcept
Definition: juce_RectangleList.h:643
void add(const RectangleType &rect)
Definition: juce_RectangleList.h:108
RectangleType getBounds() const noexcept
Definition: juce_RectangleList.h:489
png_const_structrp png_const_inforp int png_fixed_point * width
Definition: juce_PNGLoader.cpp:2339
bool subtract(const RectangleList &otherList)
Definition: juce_RectangleList.h:294
Definition: juce_Array.h:60
void swapWith(RectangleList &otherList) noexcept
Definition: juce_RectangleList.h:405
#define jassert(a)
Definition: juce_PlatformDefs.h:146
ValueType getY() const noexcept
Definition: juce_Rectangle.h:110
void setWidth(ValueType newWidth) noexcept
Definition: juce_Rectangle.h:181
bool clipTo(const RectangleType &rect)
Definition: juce_RectangleList.h:311
Definition: juce_AffineTransform.h:40
bool containsPoint(Point< ValueType > point) const noexcept
Definition: juce_RectangleList.h:414
void scaleAll(ScaleType scaleFactor) noexcept
Definition: juce_RectangleList.h:611
RectangleList(const RectangleList &other)
Definition: juce_RectangleList.h:50
bool containsPoint(ValueType x, ValueType y) const noexcept
Definition: juce_RectangleList.h:426
bool isEmpty() const noexcept
Definition: juce_Rectangle.h:101