add variant of Rect::expand() that allows different amounts in each direction
[ardour.git] / libs / canvas / canvas / types.h
1 /*
2     Copyright (C) 2011-2013 Paul Davis
3     Author: Carl Hetherington <cth@carlh.net>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #ifndef __CANVAS_TYPES_H__
21 #define __CANVAS_TYPES_H__
22
23 #include <iostream>
24 #include <vector>
25 #include <stdint.h>
26 #include <algorithm>
27 #include <boost/optional.hpp>
28
29 #include <cairomm/refptr.h>
30
31 #include "canvas/visibility.h"
32
33 namespace Cairo {
34         class Context;
35 }
36
37 namespace ArdourCanvas
38 {
39
40 typedef double Coord;
41 typedef double Distance;
42 typedef uint32_t Color;
43
44 extern LIBCANVAS_API Coord const COORD_MAX;
45
46 inline Coord
47 canvas_safe_add (Coord a, Coord b)
48 {
49         if (((COORD_MAX - a) <= b) || ((COORD_MAX - b) <= a)) {
50                 return COORD_MAX;
51         }
52
53         return a + b;
54 }
55
56
57 struct LIBCANVAS_API Duple
58 {
59         Duple ()
60                 : x (0)
61                 , y (0)
62         {}
63
64         Duple (Coord x_, Coord y_)
65                 : x (x_)
66                 , y (y_)
67         {}
68
69         Coord x;
70         Coord y;
71
72         Duple translate (const Duple& t) const throw() {
73                 return Duple (canvas_safe_add (x, t.x), canvas_safe_add (y, t.y));
74         }
75
76         Duple operator- () const throw () {
77                 return Duple (-x, -y);
78         }
79         Duple operator+ (Duple const & o) const throw () {
80                 return Duple (canvas_safe_add (x, o.x), canvas_safe_add (y, o.y));
81         }
82         bool operator== (Duple const & o) const throw () {
83                 return x == o.x && y == o.y;
84         }
85         bool operator!= (Duple const & o) const throw () {
86                 return x != o.x || y != o.y;
87         }
88         Duple operator- (Duple const & o) const throw () {
89                 return Duple (x - o.x, y - o.y);
90         }
91         Duple operator/ (double b) const throw () {
92                 return Duple (x / b, y / b);
93         }
94 };
95
96
97 extern LIBCANVAS_API std::ostream & operator<< (std::ostream &, Duple const &);
98
99 struct LIBCANVAS_API Rect
100 {
101         Rect ()
102                 : x0 (0)
103                 , y0 (0)
104                 , x1 (0)
105                 , y1 (0)
106         {}
107
108         Rect (Coord x0_, Coord y0_, Coord x1_, Coord y1_)
109                 : x0 (x0_)
110                 , y0 (y0_)
111                 , x1 (x1_)
112                 , y1 (y1_)
113         {}
114
115         Coord x0;
116         Coord y0;
117         Coord x1;
118         Coord y1;
119
120         boost::optional<Rect> intersection (Rect const & o) const throw () {
121                 Rect i (std::max (x0, o.x0), std::max (y0, o.y0),
122                         std::min (x1, o.x1), std::min (y1, o.y1));
123
124                 if (i.x0 > i.x1 || i.y0 > i.y1) {
125                         return boost::optional<Rect> ();
126                 }
127
128                 return boost::optional<Rect> (i);
129         }
130
131         Rect extend (Rect const & o) const throw () {
132                 return Rect (std::min (x0, o.x0), std::min (y0, o.y0),
133                              std::max (x1, o.x1), std::max (y1, o.y1));
134         }
135         Rect translate (Duple const& t) const throw () {
136                 return Rect (canvas_safe_add (x0, t.x), canvas_safe_add (y0, t.y),
137                              canvas_safe_add (x1, t.x),canvas_safe_add (y1, t.y));
138         }
139         Rect expand (Distance amount) const throw () {
140                 return Rect (x0 - amount, y0 - amount,
141                              canvas_safe_add (x1, amount),
142                              canvas_safe_add (y1, amount));
143         }
144         Rect expand (Distance top, Distance right, Distance bottom, Distance left) const throw () {
145                 return Rect (x0 - left, y0 - top,
146                              canvas_safe_add (x1, right),
147                              canvas_safe_add (y1, bottom));
148         }
149
150         Rect shrink (Distance amount) const throw () {
151                 /* This isn't the equivalent of expand (-distance) because
152                    of the peculiarities of canvas_safe_add() with negative values.
153                    Maybe.
154                 */
155                 return Rect (canvas_safe_add (x0, amount), canvas_safe_add (y0, amount),
156                              x1 - amount, y1 - amount);
157         }
158
159         bool contains (Duple const & point) const throw () {
160                 return point.x >= x0 && point.x < x1 && point.y >= y0 && point.y < y1;
161         }
162         Rect fix () const throw () {
163                 return Rect (std::min (x0, x1), std::min (y0, y1),
164                              std::max (x0, x1), std::max (y0, y1));
165         }
166
167         bool empty() const throw () { return (x0 == x1 && y0 == y1); }
168
169         Distance width () const  throw () {
170                 return x1 - x0;
171         }
172
173         Distance height () const throw () {
174                 return y1 - y0;
175         }
176         bool operator!= (Rect const & o) const throw () {
177                 return x0 != o.x0 ||
178                         x1 != o.x1 ||
179                         y0 != o.y0 ||
180                         y1 != o.y1;
181         }
182 };
183
184 extern LIBCANVAS_API std::ostream & operator<< (std::ostream &, Rect const &);
185
186 typedef std::vector<Duple> Points;
187
188 }
189
190 #endif