xref: /haiku/src/servers/app/drawing/Painter/agg_renderer_region.h (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright 2005-2006, Stephan Aßmus <superstippi@gmx.de>.
3  * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
4  * Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
5  * All rights reserved. Distributed under the terms of the MIT License.
6  *
7  * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
8  *
9  *
10  * class renderer_region, slightly modified renderer_mclip which directly
11  * uses a BRegion for clipping info.
12  *
13  */
14 
15 #ifndef AGG_RENDERER_REGION_INCLUDED
16 #define AGG_RENDERER_REGION_INCLUDED
17 
18 #include <Region.h>
19 
20 #include "agg_basics.h"
21 #include "agg_array.h"
22 #include "agg_renderer_base.h"
23 
24 namespace agg
25 {
26 
27 	//----------------------------------------------------------renderer_region
28 	template<class PixelFormat> class renderer_region
29 	{
30 	public:
31 		typedef PixelFormat pixfmt_type;
32 		typedef typename pixfmt_type::color_type color_type;
33 		typedef renderer_base<pixfmt_type> base_ren_type;
34 
35 		//--------------------------------------------------------------------
36 		renderer_region(pixfmt_type& ren) :
37 			m_ren(ren),
38 			m_region(NULL),
39 			m_curr_cb(0),
40 			m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()),
41 			m_offset_x(0),
42 			m_offset_y(0)
43 		{
44 		}
45 
46 		//--------------------------------------------------------------------
47 		const pixfmt_type& ren() const { return m_ren.ren();  }
48 		pixfmt_type& ren() { return m_ren.ren();  }
49 
50 		//--------------------------------------------------------------------
51 		unsigned width()  const { return m_ren.width();	 }
52 		unsigned height() const { return m_ren.height(); }
53 
54 		//--------------------------------------------------------------------
55 		const rect_i& clip_box() const { return m_bounds; }
56 		int			  xmin()	 const { return translate_from_base_ren_x(
57 											m_ren.xmin()); }
58 		int			  ymin()	 const { return translate_from_base_ren_y(
59 											m_ren.ymin()); }
60 		int			  xmax()	 const { return translate_from_base_ren_x(
61 											m_ren.xmax()); }
62 		int			  ymax()	 const { return translate_from_base_ren_y(
63 											m_ren.ymax()); }
64 
65 		//--------------------------------------------------------------------
66 		const rect_i& bounding_clip_box() const { return m_bounds;	  }
67 		int			  bounding_xmin()	  const { return m_bounds.x1; }
68 		int			  bounding_ymin()	  const { return m_bounds.y1; }
69 		int			  bounding_xmax()	  const { return m_bounds.x2; }
70 		int			  bounding_ymax()	  const { return m_bounds.y2; }
71 
72 		//--------------------------------------------------------------------
73 		void first_clip_box()
74 		{
75 			m_curr_cb = 0;
76 			if(m_region && m_region->CountRects() > 0)
77 			{
78 				clipping_rect cb = m_region->RectAtInt(0);
79 				translate_to_base_ren(cb);
80 				m_ren.clip_box_naked(
81 					cb.left,
82 					cb.top,
83 					cb.right,
84 					cb.bottom);
85 			}
86 			else
87 				m_ren.clip_box_naked(0, 0, -1, -1);
88 		}
89 
90 		//--------------------------------------------------------------------
91 		bool next_clip_box()
92 		{
93 			if(m_region && (int)(++m_curr_cb) < m_region->CountRects())
94 			{
95 				clipping_rect cb = m_region->RectAtInt(m_curr_cb);
96 				translate_to_base_ren(cb);
97 				m_ren.clip_box_naked(
98 					cb.left,
99 					cb.top,
100 					cb.right,
101 					cb.bottom);
102 				return true;
103 			}
104 			return false;
105 		}
106 
107 		//--------------------------------------------------------------------
108 		void reset_clipping(bool visibility)
109 		{
110 			m_ren.reset_clipping(visibility);
111 			m_region = NULL;
112 			m_curr_cb = 0;
113 			m_bounds = m_ren.clip_box();
114 			translate_from_base_ren(m_bounds);
115 		}
116 
117 		//--------------------------------------------------------------------
118 		void set_clipping_region(BRegion* region)
119 		{
120 			m_region = region;
121 			if (m_region) {
122 				clipping_rect r = m_region->FrameInt();
123 				if (r.left <= r.right && r.top <= r.bottom) {
124 					// clip rect_i to frame buffer bounds
125 					r.left = max_c(0, r.left);
126 					r.top = max_c(0, r.top);
127 					r.right = min_c((int)width() - 1, r.right);
128 					r.bottom = min_c((int)height() - 1, r.bottom);
129 
130 					if(r.left < m_bounds.x1) m_bounds.x1 = r.left;
131 					if(r.top < m_bounds.y1) m_bounds.y1 = r.top;
132 					if(r.right > m_bounds.x2) m_bounds.x2 = r.right;
133 					if(r.bottom > m_bounds.y2) m_bounds.y2 = r.bottom;
134 				}
135 			}
136 		}
137 
138 		//--------------------------------------------------------------------
139 		void set_offset(int offset_x, int offset_y)
140 		{
141 			m_offset_x = offset_x;
142 			m_offset_y = offset_y;
143 
144 			if (m_region == NULL) {
145 				m_bounds = m_ren.clip_box();
146 				translate_from_base_ren(m_bounds);
147 			}
148 		}
149 
150 		//--------------------------------------------------------------------
151 		void translate_to_base_ren_x(int& x)
152 		{
153 			x -= m_offset_x;
154 		}
155 
156 		void translate_to_base_ren_y(int& y)
157 		{
158 			y -= m_offset_y;
159 		}
160 
161 		void translate_to_base_ren(int& x, int&y)
162 		{
163 			x -= m_offset_x;
164 			y -= m_offset_y;
165 		}
166 
167 		void translate_to_base_ren(clipping_rect& clip)
168 		{
169 			clip.left   -= m_offset_x;
170 			clip.right  -= m_offset_x;
171 			clip.top    -= m_offset_y;
172 			clip.bottom -= m_offset_y;
173 		}
174 
175 		//--------------------------------------------------------------------
176 		int translate_from_base_ren_x(int x) const
177 		{
178 			return x + m_offset_x;
179 		}
180 
181 		int translate_from_base_ren_y(int y) const
182 		{
183 			return y + m_offset_y;
184 		}
185 
186 		void translate_from_base_ren(int& x, int& y)
187 		{
188 			x += m_offset_x;
189 			y += m_offset_y;
190 		}
191 
192 		void translate_from_base_ren(rect_i& rect)
193 		{
194 			rect.x1 += m_offset_x;
195 			rect.x2 += m_offset_x;
196 			rect.y1 += m_offset_y;
197 			rect.y2 += m_offset_y;
198 		}
199 
200 		//--------------------------------------------------------------------
201 		void clear(const color_type& c)
202 		{
203 			m_ren.clear(c);
204 		}
205 
206 		//--------------------------------------------------------------------
207 		void copy_pixel(int x, int y, const color_type& c)
208 		{
209 			translate_to_base_ren(x, y);
210 
211 			first_clip_box();
212 			do
213 			{
214 				if(m_ren.inbox(x, y))
215 				{
216 					m_ren.ren().copy_pixel(x, y, c);
217 					break;
218 				}
219 			}
220 			while(next_clip_box());
221 		}
222 
223 		//--------------------------------------------------------------------
224 		void blend_pixel(int x, int y, const color_type& c, cover_type cover)
225 		{
226 			translate_to_base_ren(x, y);
227 
228 			first_clip_box();
229 			do
230 			{
231 				if(m_ren.inbox(x, y))
232 				{
233 					m_ren.ren().blend_pixel(x, y, c, cover);
234 					break;
235 				}
236 			}
237 			while(next_clip_box());
238 		}
239 
240 		//--------------------------------------------------------------------
241 		color_type pixel(int x, int y) const
242 		{
243 			translate_to_base_ren(x, y);
244 
245 			first_clip_box();
246 			do
247 			{
248 				if(m_ren.inbox(x, y))
249 				{
250 					return m_ren.ren().pixel(x, y);
251 				}
252 			}
253 			while(next_clip_box());
254 			return color_type::no_color();
255 		}
256 
257 		//--------------------------------------------------------------------
258 		void copy_hline(int x1, int y, int x2, const color_type& c)
259 		{
260 			translate_to_base_ren(x1, y);
261 			translate_to_base_ren_x(x2);
262 
263 			first_clip_box();
264 			do
265 			{
266 				m_ren.copy_hline(x1, y, x2, c);
267 			}
268 			while(next_clip_box());
269 		}
270 
271 		//--------------------------------------------------------------------
272 		void copy_vline(int x, int y1, int y2, const color_type& c)
273 		{
274 			translate_to_base_ren(x, y1);
275 			translate_to_base_ren_y(y2);
276 
277 			first_clip_box();
278 			do
279 			{
280 				m_ren.copy_vline(x, y1, y2, c);
281 			}
282 			while(next_clip_box());
283 		}
284 
285 		//--------------------------------------------------------------------
286 		void blend_hline(int x1, int y, int x2,
287 						 const color_type& c, cover_type cover)
288 		{
289 			translate_to_base_ren(x1, y);
290 			translate_to_base_ren_x(x2);
291 
292 			first_clip_box();
293 			do
294 			{
295 				m_ren.blend_hline(x1, y, x2, c, cover);
296 			}
297 			while(next_clip_box());
298 		}
299 
300 		//--------------------------------------------------------------------
301 		void blend_vline(int x, int y1, int y2,
302 						 const color_type& c, cover_type cover)
303 		{
304 			translate_to_base_ren(x, y1);
305 			translate_to_base_ren_y(y2);
306 
307 			first_clip_box();
308 			do
309 			{
310 				m_ren.blend_vline(x, y1, y2, c, cover);
311 			}
312 			while(next_clip_box());
313 		}
314 
315 		//--------------------------------------------------------------------
316 		void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
317 		{
318 			translate_to_base_ren(x1, y1);
319 			translate_to_base_ren(x2, y2);
320 
321 			first_clip_box();
322 			do
323 			{
324 				m_ren.copy_bar(x1, y1, x2, y2, c);
325 			}
326 			while(next_clip_box());
327 		}
328 
329 		//--------------------------------------------------------------------
330 		void blend_bar(int x1, int y1, int x2, int y2,
331 					   const color_type& c, cover_type cover)
332 		{
333 			translate_to_base_ren(x1, y1);
334 			translate_to_base_ren(x2, y2);
335 
336 			first_clip_box();
337 			do
338 			{
339 				m_ren.blend_bar(x1, y1, x2, y2, c, cover);
340 			}
341 			while(next_clip_box());
342 		}
343 
344 
345 		//--------------------------------------------------------------------
346 		void blend_solid_hspan(int x, int y, int len,
347 							   const color_type& c, const cover_type* covers)
348 		{
349 			translate_to_base_ren(x, y);
350 
351 			first_clip_box();
352 			do
353 			{
354 				m_ren.blend_solid_hspan(x, y, len, c, covers);
355 			}
356 			while(next_clip_box());
357 		}
358 
359 		//--------------------------------------------------------------------
360 		void blend_solid_hspan_subpix(int x, int y, int len,
361 							   const color_type& c, const cover_type* covers)
362 		{
363 			translate_to_base_ren(x, y);
364 
365 			first_clip_box();
366 			do
367 			{
368 				m_ren.blend_solid_hspan_subpix(x, y, len, c, covers);
369 			}
370 			while(next_clip_box());
371 		}
372 
373 		//--------------------------------------------------------------------
374 		void blend_solid_vspan(int x, int y, int len,
375 							   const color_type& c, const cover_type* covers)
376 		{
377 			translate_to_base_ren(x, y);
378 
379 			first_clip_box();
380 			do
381 			{
382 				m_ren.blend_solid_vspan(x, y, len, c, covers);
383 			}
384 			while(next_clip_box());
385 		}
386 
387 		//--------------------------------------------------------------------
388 		void blend_color_hspan(int x, int y, int len,
389 							   const color_type* colors,
390 							   const cover_type* covers,
391 							   cover_type cover = cover_full)
392 		{
393 			translate_to_base_ren(x, y);
394 
395 			first_clip_box();
396 			do
397 			{
398 				m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
399 			}
400 			while(next_clip_box());
401 		}
402 
403 		//--------------------------------------------------------------------
404 		void blend_color_vspan(int x, int y, int len,
405 							   const color_type* colors,
406 							   const cover_type* covers,
407 							   cover_type cover = cover_full)
408 		{
409 			translate_to_base_ren(x, y);
410 
411 			first_clip_box();
412 			do
413 			{
414 				m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
415 			}
416 			while(next_clip_box());
417 		}
418 
419 		//--------------------------------------------------------------------
420 		void blend_color_hspan_no_clip(int x, int y, int len,
421 									   const color_type* colors,
422 									   const cover_type* covers,
423 									   cover_type cover = cover_full)
424 		{
425 			translate_to_base_ren(x, y);
426 			m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover);
427 		}
428 
429 		//--------------------------------------------------------------------
430 		void blend_color_vspan_no_clip(int x, int y, int len,
431 									   const color_type* colors,
432 									   const cover_type* covers,
433 									   cover_type cover = cover_full)
434 		{
435 			translate_to_base_ren(x, y);
436 			m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover);
437 		}
438 
439 		//--------------------------------------------------------------------
440 		void copy_from(const rendering_buffer& from,
441 					   const rect_i* rc=0,
442 					   int x_to=0,
443 					   int y_to=0)
444 		{
445 			translate_to_base_ren(x_to, y_to);
446 			first_clip_box();
447 			do
448 			{
449 				m_ren.copy_from(from, rc, x_to, y_to);
450 			}
451 			while(next_clip_box());
452 		}
453 
454 	private:
455 		renderer_region(const renderer_region<PixelFormat>&);
456 		const renderer_region<PixelFormat>&
457 			operator = (const renderer_region<PixelFormat>&);
458 
459 		base_ren_type	   m_ren;
460 		BRegion*		   m_region;
461 		unsigned		   m_curr_cb;
462 		rect_i			   m_bounds;
463 
464 		int				   m_offset_x;
465 		int				   m_offset_y;
466 	};
467 
468 
469 }
470 
471 #endif
472