xref: /haiku/src/servers/app/drawing/Painter/agg_renderer_region.h (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
1 /*
2  * Copyright 2005-2006, Stephan Aßmus <superstippi@gmx.de>.
3  * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
4  * All rights reserved. Distributed under the terms of the MIT License.
5  *
6  * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
7  *
8  *
9  * class renderer_region, slightly modified renderer_mclip which directly
10  * uses a BRegion for clipping info.
11  *
12  */
13 
14 #ifndef AGG_RENDERER_REGION_INCLUDED
15 #define AGG_RENDERER_REGION_INCLUDED
16 
17 #include <Region.h>
18 
19 #include "agg_basics.h"
20 #include "agg_array.h"
21 #include "agg_renderer_base.h"
22 
23 namespace agg
24 {
25 
26 	//----------------------------------------------------------renderer_region
27 	template<class PixelFormat> class renderer_region
28 	{
29 	public:
30 		typedef PixelFormat pixfmt_type;
31 		typedef typename pixfmt_type::color_type color_type;
32 		typedef renderer_base<pixfmt_type> base_ren_type;
33 
34 		//--------------------------------------------------------------------
35 		renderer_region(pixfmt_type& ren) :
36 			m_ren(ren),
37 			m_region(NULL),
38 			m_curr_cb(0),
39 			m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
40 		{
41 		}
42 
43 		//--------------------------------------------------------------------
44 		const pixfmt_type& ren() const { return m_ren.ren();  }
45 		pixfmt_type& ren() { return m_ren.ren();  }
46 
47 		//--------------------------------------------------------------------
48 		unsigned width()  const { return m_ren.width();	 }
49 		unsigned height() const { return m_ren.height(); }
50 
51 		//--------------------------------------------------------------------
52 		const rect_i& clip_box() const { return m_ren.clip_box(); }
53 		int			  xmin()	 const { return m_ren.xmin(); }
54 		int			  ymin()	 const { return m_ren.ymin(); }
55 		int			  xmax()	 const { return m_ren.xmax(); }
56 		int			  ymax()	 const { return m_ren.ymax(); }
57 
58 		//--------------------------------------------------------------------
59 		const rect_i& bounding_clip_box() const { return m_bounds;	  }
60 		int			  bounding_xmin()	  const { return m_bounds.x1; }
61 		int			  bounding_ymin()	  const { return m_bounds.y1; }
62 		int			  bounding_xmax()	  const { return m_bounds.x2; }
63 		int			  bounding_ymax()	  const { return m_bounds.y2; }
64 
65 		//--------------------------------------------------------------------
66 		void first_clip_box()
67 		{
68 			m_curr_cb = 0;
69 			if(m_region && m_region->CountRects() > 0)
70 			{
71 				clipping_rect cb = m_region->RectAtInt(0);
72 				m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom);
73 			}
74 			else
75 				m_ren.clip_box_naked(0, 0, -1, -1);
76 		}
77 
78 		//--------------------------------------------------------------------
79 		bool next_clip_box()
80 		{
81 			if(m_region && (int)(++m_curr_cb) < m_region->CountRects())
82 			{
83 				clipping_rect cb = m_region->RectAtInt(m_curr_cb);
84 				m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom);
85 				return true;
86 			}
87 			return false;
88 		}
89 
90 		//--------------------------------------------------------------------
91 		void reset_clipping(bool visibility)
92 		{
93 			m_ren.reset_clipping(visibility);
94 			m_region = NULL;
95 			m_curr_cb = 0;
96 			m_bounds = m_ren.clip_box();
97 		}
98 
99 		//--------------------------------------------------------------------
100 		void set_clipping_region(BRegion* region)
101 		{
102 			m_region = region;
103 			if (m_region) {
104 				clipping_rect r = m_region->FrameInt();
105 				if (r.left <= r.right && r.top <= r.bottom) {
106 					// clip rect_i to frame buffer bounds
107 					r.left = max_c(0, r.left);
108 					r.top = max_c(0, r.top);
109 					r.right = min_c((int)width() - 1, r.right);
110 					r.bottom = min_c((int)height() - 1, r.bottom);
111 
112 					if(r.left < m_bounds.x1) m_bounds.x1 = r.left;
113 					if(r.top < m_bounds.y1) m_bounds.y1 = r.top;
114 					if(r.right > m_bounds.x2) m_bounds.x2 = r.right;
115 					if(r.bottom > m_bounds.y2) m_bounds.y2 = r.bottom;
116 				}
117 			}
118 		}
119 
120 		//--------------------------------------------------------------------
121 		void clear(const color_type& c)
122 		{
123 			m_ren.clear(c);
124 		}
125 
126 		//--------------------------------------------------------------------
127 		void copy_pixel(int x, int y, const color_type& c)
128 		{
129 			first_clip_box();
130 			do
131 			{
132 				if(m_ren.inbox(x, y))
133 				{
134 					m_ren.ren().copy_pixel(x, y, c);
135 					break;
136 				}
137 			}
138 			while(next_clip_box());
139 		}
140 
141 		//--------------------------------------------------------------------
142 		void blend_pixel(int x, int y, const color_type& c, cover_type cover)
143 		{
144 			first_clip_box();
145 			do
146 			{
147 				if(m_ren.inbox(x, y))
148 				{
149 					m_ren.ren().blend_pixel(x, y, c, cover);
150 					break;
151 				}
152 			}
153 			while(next_clip_box());
154 		}
155 
156 		//--------------------------------------------------------------------
157 		color_type pixel(int x, int y) const
158 		{
159 			first_clip_box();
160 			do
161 			{
162 				if(m_ren.inbox(x, y))
163 				{
164 					return m_ren.ren().pixel(x, y);
165 				}
166 			}
167 			while(next_clip_box());
168 			return color_type::no_color();
169 		}
170 
171 		//--------------------------------------------------------------------
172 		void copy_hline(int x1, int y, int x2, const color_type& c)
173 		{
174 			first_clip_box();
175 			do
176 			{
177 				m_ren.copy_hline(x1, y, x2, c);
178 			}
179 			while(next_clip_box());
180 		}
181 
182 		//--------------------------------------------------------------------
183 		void copy_vline(int x, int y1, int y2, const color_type& c)
184 		{
185 			first_clip_box();
186 			do
187 			{
188 				m_ren.copy_vline(x, y1, y2, c);
189 			}
190 			while(next_clip_box());
191 		}
192 
193 		//--------------------------------------------------------------------
194 		void blend_hline(int x1, int y, int x2,
195 						 const color_type& c, cover_type cover)
196 		{
197 			first_clip_box();
198 			do
199 			{
200 				m_ren.blend_hline(x1, y, x2, c, cover);
201 			}
202 			while(next_clip_box());
203 		}
204 
205 		//--------------------------------------------------------------------
206 		void blend_vline(int x, int y1, int y2,
207 						 const color_type& c, cover_type cover)
208 		{
209 			first_clip_box();
210 			do
211 			{
212 				m_ren.blend_vline(x, y1, y2, c, cover);
213 			}
214 			while(next_clip_box());
215 		}
216 
217 		//--------------------------------------------------------------------
218 		void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
219 		{
220 			first_clip_box();
221 			do
222 			{
223 				m_ren.copy_bar(x1, y1, x2, y2, c);
224 			}
225 			while(next_clip_box());
226 		}
227 
228 		//--------------------------------------------------------------------
229 		void blend_bar(int x1, int y1, int x2, int y2,
230 					   const color_type& c, cover_type cover)
231 		{
232 			first_clip_box();
233 			do
234 			{
235 				m_ren.blend_bar(x1, y1, x2, y2, c, cover);
236 			}
237 			while(next_clip_box());
238 		}
239 
240 
241 		//--------------------------------------------------------------------
242 		void blend_solid_hspan(int x, int y, int len,
243 							   const color_type& c, const cover_type* covers)
244 		{
245 			first_clip_box();
246 			do
247 			{
248 				m_ren.blend_solid_hspan(x, y, len, c, covers);
249 			}
250 			while(next_clip_box());
251 		}
252 
253 		//--------------------------------------------------------------------
254 		void blend_solid_hspan_subpix(int x, int y, int len,
255 							   const color_type& c, const cover_type* covers)
256 		{
257 			first_clip_box();
258 			do
259 			{
260 				m_ren.blend_solid_hspan_subpix(x, y, len, c, covers);
261 			}
262 			while(next_clip_box());
263 		}
264 
265 		//--------------------------------------------------------------------
266 		void blend_solid_vspan(int x, int y, int len,
267 							   const color_type& c, const cover_type* covers)
268 		{
269 			first_clip_box();
270 			do
271 			{
272 				m_ren.blend_solid_vspan(x, y, len, c, covers);
273 			}
274 			while(next_clip_box());
275 		}
276 
277 		//--------------------------------------------------------------------
278 		void blend_color_hspan(int x, int y, int len,
279 							   const color_type* colors,
280 							   const cover_type* covers,
281 							   cover_type cover = cover_full)
282 		{
283 			first_clip_box();
284 			do
285 			{
286 				m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
287 			}
288 			while(next_clip_box());
289 		}
290 
291 		//--------------------------------------------------------------------
292 		void blend_color_vspan(int x, int y, int len,
293 							   const color_type* colors,
294 							   const cover_type* covers,
295 							   cover_type cover = cover_full)
296 		{
297 			first_clip_box();
298 			do
299 			{
300 				m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
301 			}
302 			while(next_clip_box());
303 		}
304 
305 		//--------------------------------------------------------------------
306 		void blend_color_hspan_no_clip(int x, int y, int len,
307 									   const color_type* colors,
308 									   const cover_type* covers,
309 									   cover_type cover = cover_full)
310 		{
311 			m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover);
312 		}
313 
314 		//--------------------------------------------------------------------
315 		void blend_color_vspan_no_clip(int x, int y, int len,
316 									   const color_type* colors,
317 									   const cover_type* covers,
318 									   cover_type cover = cover_full)
319 		{
320 			m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover);
321 		}
322 
323 		//--------------------------------------------------------------------
324 		void copy_from(const rendering_buffer& from,
325 					   const rect_i* rc=0,
326 					   int x_to=0,
327 					   int y_to=0)
328 		{
329 			first_clip_box();
330 			do
331 			{
332 				m_ren.copy_from(from, rc, x_to, y_to);
333 			}
334 			while(next_clip_box());
335 		}
336 
337 	private:
338 		renderer_region(const renderer_region<PixelFormat>&);
339 		const renderer_region<PixelFormat>&
340 			operator = (const renderer_region<PixelFormat>&);
341 
342 		base_ren_type	   m_ren;
343 		BRegion*		   m_region;
344 		unsigned		   m_curr_cb;
345 		rect_i			   m_bounds;
346 	};
347 
348 
349 }
350 
351 #endif
352