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