FINAL CUT
frect.h
1 /***********************************************************************
2 * frect.h - Rectangle with position and size *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2014-2026 Markus Gans *
7 * *
8 * FINAL CUT is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as *
10 * published by the Free Software Foundation; either version 3 of *
11 * the License, or (at your option) any later version. *
12 * *
13 * FINAL CUT is distributed in the hope that it will be useful, but *
14 * WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this program. If not, see *
20 * <http://www.gnu.org/licenses/>. *
21 ***********************************************************************/
22 
23 /* Standalone class
24  * ════════════════
25  *
26  * ▕▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▏
27  * ▕ FRect ▏-┬- - -▕ FPoint ▏
28  * ▕▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▏
29  * :
30  * : 1▕▔▔▔▔▔▔▔▏
31  * └- - -▕ FSize ▏
32  * ▕▁▁▁▁▁▁▁▏
33  */
34 
35 #ifndef FRECT_H
36 #define FRECT_H
37 
38 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
39  #error "Only <final/final.h> can be included directly."
40 #endif
41 
42 #include <algorithm>
43 #include <utility>
44 
45 #include "final/util/fpoint.h"
46 #include "final/util/fsize.h"
47 #include "final/util/fstring.h"
48 
49 namespace finalcut
50 {
51 
52 //----------------------------------------------------------------------
53 // class FRect
54 //----------------------------------------------------------------------
55 
56 class FRect
57 {
58  public:
59  // Using-declarations
60  using coordinate_type = int;
61  using coordinate_reference = coordinate_type&;
62  using size_type = std::size_t;
63 
64  // Constructors
65  constexpr FRect () noexcept = default;
66 
67  constexpr FRect (coordinate_type, coordinate_type, size_type, size_type) noexcept;
68  constexpr FRect (const FPoint&, const FSize&) noexcept;
69  constexpr FRect (const FPoint&, const FPoint&) noexcept;
70 
71  // Copy constructor
72  constexpr FRect(const FRect&) noexcept = default;
73 
74  // Move constructor
75  constexpr FRect(FRect&&) noexcept = default;
76 
77  // Destructor
78  ~FRect() noexcept = default;
79 
80  // Copy assignment operator (=)
81  constexpr auto operator = (const FRect&) noexcept -> FRect& = default;
82 
83  // Move assignment operator (=)
84  constexpr auto operator = (FRect&&) noexcept -> FRect& = default;
85 
86  // Accessors
87  auto getClassName() const -> FString;
88  constexpr auto getX1() const noexcept -> coordinate_type;
89  constexpr auto getY1() const noexcept -> coordinate_type;
90  constexpr auto getX2() const noexcept -> coordinate_type;
91  constexpr auto getY2() const noexcept -> coordinate_type;
92  constexpr auto getX() const noexcept -> coordinate_type;
93  constexpr auto getY() const noexcept -> coordinate_type;
94  constexpr auto getPos() const noexcept -> FPoint;
95  constexpr auto getUpperLeftPos() const noexcept -> FPoint;
96  constexpr auto getUpperRightPos() const noexcept -> FPoint;
97  constexpr auto getLowerLeftPos() const noexcept -> FPoint;
98  constexpr auto getLowerRightPos() const noexcept -> FPoint;
99  constexpr auto getWidth() const noexcept -> size_type;
100  constexpr auto getHeight() const noexcept -> size_type;
101  constexpr auto getSize() const noexcept -> FSize;
102 
103  // Mutators
104  constexpr void setX1 (coordinate_type) noexcept;
105  constexpr void setY1 (coordinate_type) noexcept;
106  constexpr void setX2 (coordinate_type) noexcept;
107  constexpr void setY2 (coordinate_type) noexcept;
108  constexpr void setX (coordinate_type) noexcept;
109  constexpr void setY (coordinate_type) noexcept;
110  constexpr void setPos (coordinate_type, coordinate_type) noexcept;
111  constexpr void setPos (const FPoint&) noexcept;
112  constexpr void setWidth (size_type) noexcept;
113  constexpr void setHeight (size_type) noexcept;
114  constexpr void setSize (size_type, size_type) noexcept;
115  constexpr void setSize (const FSize&) noexcept;
116  constexpr void setRect (const FRect&) noexcept;
117  constexpr void setRect (const FPoint&, const FSize&) noexcept;
118  constexpr void setRect (coordinate_type, coordinate_type, size_type, size_type) noexcept;
119  constexpr void setCoordinates (const FPoint&, const FPoint&) noexcept;
120  constexpr void setCoordinates ( coordinate_type, coordinate_type
121  , coordinate_type, coordinate_type ) noexcept;
122 
123  // Predicate
124  constexpr auto isEmpty() const -> bool;
125 
126  // Coordinate references
127  constexpr auto x1_ref() & noexcept -> coordinate_reference;
128  constexpr auto y1_ref() & noexcept -> coordinate_reference;
129  constexpr auto x2_ref() & noexcept -> coordinate_reference;
130  constexpr auto y2_ref() & noexcept -> coordinate_reference;
131 
132  // Methods
133  constexpr void move (coordinate_type, coordinate_type) noexcept;
134  constexpr void move (const FPoint&) noexcept;
135  constexpr void scaleBy (coordinate_type, coordinate_type) noexcept;
136  constexpr void scaleBy (const FPoint&) noexcept;
137  constexpr auto contains (coordinate_type, coordinate_type) const noexcept -> bool;
138  constexpr auto contains (const FPoint&) const noexcept -> bool;
139  constexpr auto contains (const FRect&) const noexcept -> bool;
140  constexpr auto overlap (const FRect&) const noexcept -> bool;
141  auto intersect (const FRect&) const noexcept -> FRect;
142  auto combined (const FRect&) const noexcept -> FRect;
143  constexpr void swap (FRect&) noexcept;
144 
145  private:
146  // Data members
147  coordinate_type X1{0};
148  coordinate_type Y1{0};
149  coordinate_type X2{-1};
150  coordinate_type Y2{-1};
151 
152  // Friend operator functions
153  friend constexpr auto operator + (const FRect& r, const FSize& s) -> FRect
154  {
155  return { r.X1
156  , r.Y1
157  , size_type(r.X2 - r.X1) + 1 + s.getWidth()
158  , size_type(r.Y2 - r.Y1) + 1 + s.getHeight() };
159  }
160 
161  friend constexpr auto operator - (const FRect& r, const FSize& s) -> FRect
162  {
163  return { r.X1
164  , r.Y1
165  , size_type(r.X2 - r.X1) + 1 - s.getWidth()
166  , size_type(r.Y2 - r.Y1) + 1 - s.getHeight() };
167  }
168 
169  friend constexpr auto operator == (const FRect& r1, const FRect& r2) -> bool
170  {
171  return r1.X1 == r2.X1
172  && r1.Y1 == r2.Y1
173  && r1.X2 == r2.X2
174  && r1.Y2 == r2.Y2;
175  }
176 
177  friend constexpr auto operator != (const FRect& r1, const FRect& r2) -> bool
178  {
179  return r1.X1 != r2.X1
180  || r1.Y1 != r2.Y1
181  || r1.X2 != r2.X2
182  || r1.Y2 != r2.Y2;
183  }
184 
185  friend inline auto operator << (std::ostream& outstr, const FRect& r) -> std::ostream&
186  {
187  outstr << r.X1 << " "
188  << r.Y1 << " "
189  << r.X2 << " "
190  << r.Y2;
191  return outstr;
192  }
193 
194  friend inline auto operator >> (std::istream& instr, FRect& r) -> std::istream&
195  {
196  coordinate_type x1{};
197  coordinate_type y1{};
198  coordinate_type x2{};
199  coordinate_type y2{};
200 
201  if ( instr >> x1 >> y1 >> x2 >> y2 )
202  r.setCoordinates (x1, y1, x2, y2);
203 
204  return instr;
205  }
206 };
207 
208 // FRect inline functions
209 //----------------------------------------------------------------------
210 constexpr FRect::FRect ( coordinate_type x, coordinate_type y
211  , size_type width, size_type height ) noexcept
212  : X1{x}
213  , Y1{y}
214  , X2{x + coordinate_type(width) - 1}
215  , Y2{y + coordinate_type(height) - 1}
216 { }
217 
218 //----------------------------------------------------------------------
219 constexpr FRect::FRect (const FPoint& p, const FSize& s) noexcept
220  : X1{p.getX()}
221  , Y1{p.getY()}
222  , X2{p.getX() + int(s.getWidth()) - 1}
223  , Y2{p.getY() + int(s.getHeight()) - 1}
224 { }
225 
226 //----------------------------------------------------------------------
227 constexpr FRect::FRect (const FPoint& p1, const FPoint& p2) noexcept
228  : X1{p1.getX()}
229  , Y1{p1.getY()}
230  , X2{p2.getX()}
231  , Y2{p2.getY()}
232 { }
233 
234 //----------------------------------------------------------------------
235 inline auto FRect::getClassName() const -> FString
236 { return "FRect"; }
237 
238 //----------------------------------------------------------------------
239 constexpr auto FRect::getX1() const noexcept -> coordinate_type
240 { return X1; }
241 
242 //----------------------------------------------------------------------
243 constexpr auto FRect::getY1() const noexcept -> coordinate_type
244 { return Y1; }
245 
246 //----------------------------------------------------------------------
247 constexpr auto FRect::getX2() const noexcept -> coordinate_type
248 { return X2; }
249 
250 //----------------------------------------------------------------------
251 constexpr auto FRect::getY2() const noexcept -> coordinate_type
252 { return Y2; }
253 
254 //----------------------------------------------------------------------
255 constexpr auto FRect::getX() const noexcept -> coordinate_type
256 { return X1; }
257 
258 //----------------------------------------------------------------------
259 constexpr auto FRect::getY() const noexcept -> coordinate_type
260 { return Y1; }
261 
262 //----------------------------------------------------------------------
263 constexpr auto FRect::getPos() const noexcept -> FPoint
264 { return { X1, Y1 }; }
265 
266 //----------------------------------------------------------------------
267 constexpr auto FRect::getUpperLeftPos() const noexcept -> FPoint
268 { return { X1, Y1 }; }
269 
270 //----------------------------------------------------------------------
271 constexpr auto FRect::getUpperRightPos() const noexcept -> FPoint
272 { return { X2, Y1 }; }
273 
274 //----------------------------------------------------------------------
275 constexpr auto FRect::getLowerLeftPos() const noexcept -> FPoint
276 { return { X1, Y2 }; }
277 
278 //----------------------------------------------------------------------
279 constexpr auto FRect::getLowerRightPos() const noexcept -> FPoint
280 { return { X2, Y2 }; }
281 
282 //----------------------------------------------------------------------
283 constexpr auto FRect::getWidth() const noexcept -> size_type
284 {
285  return ( X2 >= X1 )
286  ? static_cast<size_type>(X2 - X1 + 1)
287  : 0; // overflow save
288 }
289 
290 //----------------------------------------------------------------------
291 constexpr auto FRect::getHeight() const noexcept -> size_type
292 {
293  return ( Y2 >= Y1 )
294  ? static_cast<size_type>(Y2 - Y1 + 1)
295  : 0; // overflow save
296 }
297 
298 //----------------------------------------------------------------------
299 constexpr auto FRect::getSize() const noexcept -> FSize
300 { return { FSize{getWidth(), getHeight()} }; }
301 
302 //----------------------------------------------------------------------
303 constexpr void FRect::setX1 (coordinate_type n) noexcept
304 { X1 = n; }
305 
306 //----------------------------------------------------------------------
307 constexpr void FRect::setY1 (coordinate_type n) noexcept
308 { Y1 = n; }
309 
310 //----------------------------------------------------------------------
311 constexpr void FRect::setX2 (coordinate_type n) noexcept
312 { X2 = n; }
313 
314 //----------------------------------------------------------------------
315 constexpr void FRect::setY2 (coordinate_type n) noexcept
316 { Y2 = n; }
317 
318 //----------------------------------------------------------------------
319 constexpr void FRect::setX (coordinate_type n) noexcept
320 {
321  const coordinate_type dX = X2 - X1;
322  X1 = n;
323  X2 = X1 + dX;
324 }
325 
326 //----------------------------------------------------------------------
327 constexpr void FRect::setY (coordinate_type n) noexcept
328 {
329  const coordinate_type dY = Y2 - Y1;
330  Y1 = n;
331  Y2 = Y1 + dY;
332 }
333 
334 //----------------------------------------------------------------------
335 constexpr void FRect::setPos (coordinate_type x, coordinate_type y) noexcept
336 {
337  const coordinate_type dX = X2 - X1;
338  const coordinate_type dY = Y2 - Y1;
339  X1 = x;
340  Y1 = y;
341  X2 = X1 + dX;
342  Y2 = Y1 + dY;
343 }
344 
345 //----------------------------------------------------------------------
346 constexpr void FRect::setPos (const FPoint& p) noexcept
347 {
348  const coordinate_type dX = X2 - X1;
349  const coordinate_type dY = Y2 - Y1;
350  X1 = p.getX();
351  Y1 = p.getY();
352  X2 = X1 + dX;
353  Y2 = Y1 + dY;
354 }
355 
356 //----------------------------------------------------------------------
357 constexpr void FRect::setWidth (size_type w) noexcept
358 { X2 = X1 + coordinate_type(w) - 1; }
359 
360 //----------------------------------------------------------------------
361 constexpr void FRect::setHeight (size_type h) noexcept
362 { Y2 = Y1 + coordinate_type(h) - 1; }
363 
364 //----------------------------------------------------------------------
365 constexpr void FRect::setSize (size_type width, size_type height) noexcept
366 {
367  X2 = X1 + coordinate_type(width) - 1;
368  Y2 = Y1 + coordinate_type(height) - 1;
369 }
370 
371 //----------------------------------------------------------------------
372 constexpr void FRect::setSize (const FSize& s) noexcept
373 {
374  X2 = X1 + coordinate_type(s.getWidth()) - 1;
375  Y2 = Y1 + coordinate_type(s.getHeight()) - 1;
376 }
377 
378 //----------------------------------------------------------------------
379 constexpr void FRect::setRect (const FRect& r) noexcept
380 {
381  X1 = r.X1;
382  Y1 = r.Y1;
383  X2 = r.X2;
384  Y2 = r.Y2;
385 }
386 
387 //----------------------------------------------------------------------
388 constexpr void FRect::setRect (const FPoint& p, const FSize& s) noexcept
389 {
390  X1 = p.getX();
391  Y1 = p.getY();
392  X2 = p.getX() + coordinate_type(s.getWidth()) - 1;
393  Y2 = p.getY() + coordinate_type(s.getHeight()) - 1;
394 }
395 
396 //----------------------------------------------------------------------
397 constexpr void FRect::setRect ( coordinate_type x, coordinate_type y
398  , size_type width, size_type height ) noexcept
399 {
400  X1 = x;
401  Y1 = y;
402  X2 = x + coordinate_type(width) - 1;
403  Y2 = y + coordinate_type(height) - 1;
404 }
405 
406 //----------------------------------------------------------------------
407 constexpr void FRect::setCoordinates (const FPoint& p1, const FPoint& p2) noexcept
408 {
409  setCoordinates (p1.getX(), p1.getY(), p2.getX(), p2.getY());
410 }
411 
412 //----------------------------------------------------------------------
413 constexpr void FRect::setCoordinates ( coordinate_type x1, coordinate_type y1
414  , coordinate_type x2, coordinate_type y2 ) noexcept
415 {
416  X1 = x1;
417  Y1 = y1;
418  X2 = x2;
419  Y2 = y2;
420 }
421 
422 //----------------------------------------------------------------------
423 constexpr auto FRect::isEmpty() const -> bool
424 { return X2 == X1 - 1 && Y2 == Y1 - 1; }
425 
426 //----------------------------------------------------------------------
427 constexpr auto FRect::x1_ref() & noexcept -> coordinate_reference
428 { return X1; }
429 
430 //----------------------------------------------------------------------
431 constexpr auto FRect::y1_ref() & noexcept -> coordinate_reference
432 { return Y1; }
433 
434 //----------------------------------------------------------------------
435 constexpr auto FRect::x2_ref() & noexcept -> coordinate_reference
436 { return X2; }
437 
438 //----------------------------------------------------------------------
439 constexpr auto FRect::y2_ref() & noexcept -> coordinate_reference
440 { return Y2; }
441 
442 //----------------------------------------------------------------------
443 constexpr void FRect::move (coordinate_type dx, coordinate_type dy) noexcept
444 {
445  X1 += dx;
446  Y1 += dy;
447  X2 += dx;
448  Y2 += dy;
449 }
450 
451 //----------------------------------------------------------------------
452 constexpr void FRect::move (const FPoint& d) noexcept
453 {
454  X1 += d.getX();
455  Y1 += d.getY();
456  X2 += d.getX();
457  Y2 += d.getY();
458 }
459 
460 //----------------------------------------------------------------------
461 constexpr void FRect::scaleBy (int dx, int dy) noexcept
462 {
463  X2 += dx;
464  Y2 += dy;
465 }
466 
467 //----------------------------------------------------------------------
468 constexpr void FRect::scaleBy (const FPoint& d) noexcept
469 {
470  X2 += d.getX();
471  Y2 += d.getY();
472 }
473 
474 //----------------------------------------------------------------------
475 constexpr auto FRect::contains (coordinate_type x, coordinate_type y) const noexcept -> bool
476 {
477  return x >= X1 && x <= X2
478  && y >= Y1 && y <= Y2;
479 }
480 
481 //----------------------------------------------------------------------
482 constexpr auto FRect::contains (const FPoint& p) const noexcept -> bool
483 {
484  return p.getX() >= X1 && p.getX() <= X2
485  && p.getY() >= Y1 && p.getY() <= Y2;
486 }
487 
488 //----------------------------------------------------------------------
489 constexpr auto FRect::contains (const FRect& r) const noexcept -> bool
490 {
491  return r.X1 >= X1 && r.X2 <= X2
492  && r.Y1 >= Y1 && r.Y2 <= Y2;
493 }
494 
495 //----------------------------------------------------------------------
496 constexpr auto FRect::overlap (const FRect& r) const noexcept -> bool
497 {
498  return ! (X2 < r.X1 || X1 > r.X2 || Y2 < r.Y1 || Y1 > r.Y2);
499 }
500 
501 //----------------------------------------------------------------------
502 constexpr void FRect::swap (FRect& r) noexcept
503 {
504  coordinate_type tmp_X1{X1};
505  coordinate_type tmp_Y1{Y1};
506  coordinate_type tmp_X2{X2};
507  coordinate_type tmp_Y2{Y2};
508  X1 = r.X1;
509  Y1 = r.Y1;
510  X2 = r.X2;
511  Y2 = r.Y2;
512  r.X1 = tmp_X1;
513  r.Y1 = tmp_Y1;
514  r.X2 = tmp_X2;
515  r.Y2 = tmp_Y2;
516 }
517 
518 } // namespace finalcut
519 
520 #endif // FRECT_H
Definition: frect.h:56
Definition: class_template.cpp:25
Definition: fpoint.h:50
Definition: fsize.h:55
Definition: fstring.h:82