add headers to all canvas .cc and .h files
[ardour.git] / libs / canvas / rectangle.cc
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 #include <iostream>
21 #include <cairomm/context.h>
22 #include "pbd/stacktrace.h"
23 #include "pbd/compose.h"
24 #include "canvas/rectangle.h"
25 #include "canvas/debug.h"
26 #include "canvas/utils.h"
27
28 using namespace std;
29 using namespace ArdourCanvas;
30
31 Rectangle::Rectangle (Group* parent)
32         : Item (parent)
33         , Outline (parent)
34         , Fill (parent)
35         , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM))
36 {
37
38 }
39
40 Rectangle::Rectangle (Group* parent, Rect const & rect)
41         : Item (parent)
42         , Outline (parent)
43         , Fill (parent)
44         , _rect (rect)
45         , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM))
46 {
47         
48 }
49
50 void
51 Rectangle::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
52 {
53         Rect plot = _rect;
54
55         plot.x1 = min (plot.x1, CAIRO_MAX);
56         plot.y1 = min (plot.y1, CAIRO_MAX);
57
58         if (_fill) {
59                 setup_fill_context (context);
60                 context->rectangle (plot.x0, plot.y0, plot.width(), plot.height());
61                 
62                 if (!_outline) {
63                         context->fill ();
64                 } else {
65                         
66                         /* special/common case: outline the entire rectangle is
67                          * requested, so just use the same path for the fill
68                          * and stroke.
69                          */
70
71                         if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) {
72                                 context->fill_preserve();
73                                 setup_outline_context (context);
74                                 context->stroke ();
75                         } else {
76                                 context->fill ();
77                         }
78                 }
79         } 
80         
81         if (_outline) {
82                 
83                 if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) {
84
85                         /* if we filled and use full outline, we are already done */
86
87                         if (!_fill) { 
88                                 context->rectangle (plot.x0, plot.y0, plot.width(), plot.height());
89                                 setup_outline_context (context);
90                                 context->stroke ();
91                         }
92                         
93                 } else {
94                         
95                         if (_outline_what & LEFT) {
96                                 context->move_to (plot.x0, plot.y0);
97                                 context->line_to (plot.x0, plot.y1);
98                         }
99                         
100                         if (_outline_what & BOTTOM) {
101                                 context->move_to (plot.x0, plot.y1);
102                                 context->line_to (plot.x1, plot.y1);
103                         }
104                         
105                         if (_outline_what & RIGHT) {
106                                 context->move_to (plot.x1, plot.y0);
107                                 context->line_to (plot.x1, plot.y1);
108                         }
109                         
110                         if (_outline_what & TOP) {
111                                 context->move_to (plot.x0, plot.y0);
112                                 context->line_to (plot.x1, plot.y0);
113                         }
114                         
115                         setup_outline_context (context);
116                         context->stroke ();
117                 }
118         }
119 }
120
121 void
122 Rectangle::compute_bounding_box () const
123 {
124         Rect r = _rect.fix ();
125         _bounding_box = boost::optional<Rect> (r.expand (_outline_width / 2));
126         
127         _bounding_box_dirty = false;
128 }
129
130 void
131 Rectangle::set (Rect const & r)
132 {
133         /* We don't update the bounding box here; it's just
134            as cheap to do it when asked.
135         */
136         
137         begin_change ();
138         
139         _rect = r;
140         
141         _bounding_box_dirty = true;
142         end_change ();
143
144         DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (set)\n");
145 }
146
147 void
148 Rectangle::set_x0 (Coord x0)
149 {
150         begin_change ();
151
152         _rect.x0 = x0;
153
154         _bounding_box_dirty = true;
155         end_change ();
156
157         DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (x0)\n");
158 }
159
160 void
161 Rectangle::set_y0 (Coord y0)
162 {
163         begin_change ();
164         
165         _rect.y0 = y0;
166
167         _bounding_box_dirty = true;
168         end_change();
169
170         DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (y0)\n");
171 }
172
173 void
174 Rectangle::set_x1 (Coord x1)
175 {
176         begin_change ();
177         
178         _rect.x1 = x1;
179
180         _bounding_box_dirty = true;
181         end_change ();
182
183         DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (x1)\n");
184 }
185
186 void
187 Rectangle::set_y1 (Coord y1)
188 {
189         begin_change ();
190
191         _rect.y1 = y1;
192
193         _bounding_box_dirty = true;
194         end_change ();
195
196         DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (y1)\n");
197 }
198
199 void
200 Rectangle::set_outline_what (What what)
201 {
202         begin_change ();
203         
204         _outline_what = what;
205
206         end_change ();
207 }
208
209 void
210 Rectangle::set_outline_what (int what)
211 {
212         set_outline_what ((What) what);
213 }
214