1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.2 3 // Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 // 16 // class renderer_base 17 // 18 //---------------------------------------------------------------------------- 19 20 #ifndef AGG_RENDERER_BASE_INCLUDED 21 #define AGG_RENDERER_BASE_INCLUDED 22 23 #include "agg_basics.h" 24 #include "agg_rendering_buffer.h" 25 26 namespace agg 27 { 28 29 //-----------------------------------------------------------renderer_base 30 template<class PixelFormat> class renderer_base 31 { 32 public: 33 typedef PixelFormat pixfmt_type; 34 typedef typename pixfmt_type::color_type color_type; 35 36 //-------------------------------------------------------------------- 37 renderer_base(pixfmt_type& ren) : 38 m_ren(&ren), 39 m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) 40 { 41 } 42 43 //-------------------------------------------------------------------- 44 const pixfmt_type& ren() const { return *m_ren; } 45 pixfmt_type& ren() { return *m_ren; } 46 47 //-------------------------------------------------------------------- 48 unsigned width() const { return m_ren->width(); } 49 unsigned height() const { return m_ren->height(); } 50 51 //-------------------------------------------------------------------- 52 bool clip_box(int x1, int y1, int x2, int y2) 53 { 54 rect cb(x1, y1, x2, y2); 55 cb.normalize(); 56 if(cb.clip(rect(0, 0, width() - 1, height() - 1))) 57 { 58 m_clip_box = cb; 59 return true; 60 } 61 m_clip_box.x1 = 1; 62 m_clip_box.y1 = 1; 63 m_clip_box.x2 = 0; 64 m_clip_box.y2 = 0; 65 return false; 66 } 67 68 //-------------------------------------------------------------------- 69 void reset_clipping(bool visibility) 70 { 71 if(visibility) 72 { 73 m_clip_box.x1 = 0; 74 m_clip_box.y1 = 0; 75 m_clip_box.x2 = width() - 1; 76 m_clip_box.y2 = height() - 1; 77 } 78 else 79 { 80 m_clip_box.x1 = 1; 81 m_clip_box.y1 = 1; 82 m_clip_box.x2 = 0; 83 m_clip_box.y2 = 0; 84 } 85 } 86 87 //-------------------------------------------------------------------- 88 void clip_box_naked(int x1, int y1, int x2, int y2) 89 { 90 m_clip_box.x1 = x1; 91 m_clip_box.y1 = y1; 92 m_clip_box.x2 = x2; 93 m_clip_box.y2 = y2; 94 } 95 96 //-------------------------------------------------------------------- 97 bool inbox(int x, int y) const 98 { 99 return x >= m_clip_box.x1 && y >= m_clip_box.y1 && 100 x <= m_clip_box.x2 && y <= m_clip_box.y2; 101 } 102 103 //-------------------------------------------------------------------- 104 void first_clip_box() {} 105 bool next_clip_box() { return false; } 106 107 //-------------------------------------------------------------------- 108 const rect& clip_box() const { return m_clip_box; } 109 int xmin() const { return m_clip_box.x1; } 110 int ymin() const { return m_clip_box.y1; } 111 int xmax() const { return m_clip_box.x2; } 112 int ymax() const { return m_clip_box.y2; } 113 114 //-------------------------------------------------------------------- 115 const rect& bounding_clip_box() const { return m_clip_box; } 116 int bounding_xmin() const { return m_clip_box.x1; } 117 int bounding_ymin() const { return m_clip_box.y1; } 118 int bounding_xmax() const { return m_clip_box.x2; } 119 int bounding_ymax() const { return m_clip_box.y2; } 120 121 //-------------------------------------------------------------------- 122 void clear(const color_type& c) 123 { 124 unsigned y; 125 if(width()) 126 { 127 for(y = 0; y < height(); y++) 128 { 129 m_ren->copy_hline(0, y, width(), c); 130 } 131 } 132 } 133 134 //-------------------------------------------------------------------- 135 void copy_pixel(int x, int y, const color_type& c) 136 { 137 if(inbox(x, y)) 138 { 139 m_ren->copy_pixel(x, y, c); 140 } 141 } 142 143 //-------------------------------------------------------------------- 144 void blend_pixel(int x, int y, const color_type& c, cover_type cover) 145 { 146 if(inbox(x, y)) 147 { 148 m_ren->blend_pixel(x, y, c, cover); 149 } 150 } 151 152 //-------------------------------------------------------------------- 153 color_type pixel(int x, int y) const 154 { 155 return inbox(x, y) ? 156 m_ren->pixel(x, y) : 157 color_type::no_color(); 158 } 159 160 //-------------------------------------------------------------------- 161 void copy_hline(int x1, int y, int x2, const color_type& c) 162 { 163 if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } 164 if(y > ymax()) return; 165 if(y < ymin()) return; 166 if(x1 > xmax()) return; 167 if(x2 < xmin()) return; 168 169 if(x1 < xmin()) x1 = xmin(); 170 if(x2 > xmax()) x2 = xmax(); 171 172 m_ren->copy_hline(x1, y, x2 - x1 + 1, c); 173 } 174 175 //-------------------------------------------------------------------- 176 void copy_vline(int x, int y1, int y2, const color_type& c) 177 { 178 if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } 179 if(x > xmax()) return; 180 if(x < xmin()) return; 181 if(y1 > ymax()) return; 182 if(y2 < ymin()) return; 183 184 if(y1 < ymin()) y1 = ymin(); 185 if(y2 > ymax()) y2 = ymax(); 186 187 m_ren->copy_vline(x, y1, y2 - y1 + 1, c); 188 } 189 190 //-------------------------------------------------------------------- 191 void blend_hline(int x1, int y, int x2, 192 const color_type& c, cover_type cover) 193 { 194 if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } 195 if(y > ymax()) return; 196 if(y < ymin()) return; 197 if(x1 > xmax()) return; 198 if(x2 < xmin()) return; 199 200 if(x1 < xmin()) x1 = xmin(); 201 if(x2 > xmax()) x2 = xmax(); 202 203 m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); 204 } 205 206 //-------------------------------------------------------------------- 207 void blend_vline(int x, int y1, int y2, 208 const color_type& c, cover_type cover) 209 { 210 if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } 211 if(x > xmax()) return; 212 if(x < xmin()) return; 213 if(y1 > ymax()) return; 214 if(y2 < ymin()) return; 215 216 if(y1 < ymin()) y1 = ymin(); 217 if(y2 > ymax()) y2 = ymax(); 218 219 m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover); 220 } 221 222 223 //-------------------------------------------------------------------- 224 void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) 225 { 226 rect rc(x1, y1, x2, y2); 227 rc.normalize(); 228 if(rc.clip(clip_box())) 229 { 230 int y; 231 for(y = rc.y1; y <= rc.y2; y++) 232 { 233 m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c); 234 } 235 } 236 } 237 238 //-------------------------------------------------------------------- 239 void blend_bar(int x1, int y1, int x2, int y2, 240 const color_type& c, cover_type cover) 241 { 242 rect rc(x1, y1, x2, y2); 243 rc.normalize(); 244 if(rc.clip(clip_box())) 245 { 246 int y; 247 for(y = rc.y1; y <= rc.y2; y++) 248 { 249 m_ren->blend_hline(rc.x1, 250 y, 251 unsigned(rc.x2 - rc.x1 + 1), 252 c, 253 cover); 254 } 255 } 256 } 257 258 259 //-------------------------------------------------------------------- 260 void blend_solid_hspan(int x, int y, int len, 261 const color_type& c, 262 const cover_type* covers) 263 { 264 if(y > ymax()) return; 265 if(y < ymin()) return; 266 267 if(x < xmin()) 268 { 269 len -= xmin() - x; 270 if(len <= 0) return; 271 covers += xmin() - x; 272 x = xmin(); 273 } 274 if(x + len > xmax()) 275 { 276 len = xmax() - x + 1; 277 if(len <= 0) return; 278 } 279 m_ren->blend_solid_hspan(x, y, len, c, covers); 280 } 281 282 //-------------------------------------------------------------------- 283 void blend_solid_vspan(int x, int y, int len, 284 const color_type& c, 285 const cover_type* covers) 286 { 287 if(x > xmax()) return; 288 if(x < xmin()) return; 289 290 if(y < ymin()) 291 { 292 len -= ymin() - y; 293 if(len <= 0) return; 294 covers += ymin() - y; 295 y = ymin(); 296 } 297 if(y + len > ymax()) 298 { 299 len = ymax() - y + 1; 300 if(len <= 0) return; 301 } 302 m_ren->blend_solid_vspan(x, y, len, c, covers); 303 } 304 305 //-------------------------------------------------------------------- 306 void blend_color_hspan(int x, int y, int len, 307 const color_type* colors, 308 const cover_type* covers, 309 cover_type cover = cover_full) 310 { 311 if(y > ymax()) return; 312 if(y < ymin()) return; 313 314 if(x < xmin()) 315 { 316 int d = xmin() - x; 317 len -= d; 318 if(len <= 0) return; 319 if(covers) covers += d; 320 colors += d; 321 x = xmin(); 322 } 323 if(x + len > xmax()) 324 { 325 len = xmax() - x + 1; 326 if(len <= 0) return; 327 } 328 m_ren->blend_color_hspan(x, y, len, colors, covers, cover); 329 } 330 331 //-------------------------------------------------------------------- 332 void blend_color_vspan(int x, int y, int len, 333 const color_type* colors, 334 const cover_type* covers, 335 cover_type cover = cover_full) 336 { 337 if(x > xmax()) return; 338 if(x < xmin()) return; 339 340 if(y < ymin()) 341 { 342 int d = ymin() - y; 343 len -= d; 344 if(len <= 0) return; 345 if(covers) covers += d; 346 colors += d; 347 y = ymin(); 348 } 349 if(y + len > ymax()) 350 { 351 len = ymax() - y + 1; 352 if(len <= 0) return; 353 } 354 m_ren->blend_color_vspan(x, y, len, colors, covers, cover); 355 } 356 357 //-------------------------------------------------------------------- 358 void blend_color_hspan_no_clip(int x, int y, int len, 359 const color_type* colors, 360 const cover_type* covers, 361 cover_type cover = cover_full) 362 { 363 m_ren->blend_color_hspan(x, y, len, colors, covers, cover); 364 } 365 366 //-------------------------------------------------------------------- 367 void blend_color_vspan_no_clip(int x, int y, int len, 368 const color_type* colors, 369 const cover_type* covers, 370 cover_type cover = cover_full) 371 { 372 m_ren->blend_color_vspan(x, y, len, colors, covers, cover); 373 } 374 375 376 //-------------------------------------------------------------------- 377 rect clip_rect_area(rect& dst, rect& src, int wsrc, int hsrc) const 378 { 379 rect rc(0,0,0,0); 380 rect cb = clip_box(); 381 ++cb.x2; 382 ++cb.y2; 383 384 if(src.x1 < 0) 385 { 386 dst.x1 -= src.x1; 387 src.x1 = 0; 388 } 389 if(src.y1 < 0) 390 { 391 dst.y1 -= src.y1; 392 src.y1 = 0; 393 } 394 395 if(src.x2 > wsrc) src.x2 = wsrc; 396 if(src.y2 > hsrc) src.y2 = hsrc; 397 398 if(dst.x1 < cb.x1) 399 { 400 src.x1 += cb.x1 - dst.x1; 401 dst.x1 = cb.x1; 402 } 403 if(dst.y1 < cb.y1) 404 { 405 src.y1 += cb.y1 - dst.y1; 406 dst.y1 = cb.y1; 407 } 408 409 if(dst.x2 > cb.x2) dst.x2 = cb.x2; 410 if(dst.y2 > cb.y2) dst.y2 = cb.y2; 411 412 rc.x2 = dst.x2 - dst.x1; 413 rc.y2 = dst.y2 - dst.y1; 414 415 if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1; 416 if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1; 417 return rc; 418 } 419 420 421 //-------------------------------------------------------------------- 422 void copy_from(const rendering_buffer& src, 423 const rect* rect_src_ptr = 0, 424 int dx = 0, 425 int dy = 0) 426 { 427 rect rsrc(0, 0, src.width(), src.height()); 428 if(rect_src_ptr) 429 { 430 rsrc.x1 = rect_src_ptr->x1; 431 rsrc.y1 = rect_src_ptr->y1; 432 rsrc.x2 = rect_src_ptr->x2 + 1; 433 rsrc.y2 = rect_src_ptr->y2 + 1; 434 } 435 436 // Version with xdst, ydst (absolute positioning) 437 //rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); 438 439 // Version with dx, dy (relative positioning) 440 rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); 441 442 rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); 443 444 if(rc.x2 > 0) 445 { 446 int incy = 1; 447 if(rdst.y1 > rsrc.y1) 448 { 449 rsrc.y1 += rc.y2 - 1; 450 rdst.y1 += rc.y2 - 1; 451 incy = -1; 452 } 453 while(rc.y2 > 0) 454 { 455 m_ren->copy_from(src, 456 rdst.x1, rdst.y1, 457 rsrc.x1, rsrc.y1, 458 rc.x2); 459 rdst.y1 += incy; 460 rsrc.y1 += incy; 461 --rc.y2; 462 } 463 } 464 } 465 466 467 468 //-------------------------------------------------------------------- 469 template<class SrcPixelFormatRenderer> 470 void blend_from(const SrcPixelFormatRenderer& src, 471 const rect* rect_src_ptr = 0, 472 int dx = 0, 473 int dy = 0) 474 { 475 rect rsrc(0, 0, src.width(), src.height()); 476 if(rect_src_ptr) 477 { 478 rsrc.x1 = rect_src_ptr->x1; 479 rsrc.y1 = rect_src_ptr->y1; 480 rsrc.x2 = rect_src_ptr->x2 + 1; 481 rsrc.y2 = rect_src_ptr->y2 + 1; 482 } 483 484 // Version with xdst, ydst (absolute positioning) 485 //rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); 486 487 // Version with dx, dy (relative positioning) 488 rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); 489 490 rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); 491 492 if(rc.x2 > 0) 493 { 494 int incy = 1; 495 if(rdst.y1 > rsrc.y1) 496 { 497 rsrc.y1 += rc.y2 - 1; 498 rdst.y1 += rc.y2 - 1; 499 incy = -1; 500 } 501 while(rc.y2 > 0) 502 { 503 typename SrcPixelFormatRenderer::row_data span = src.span(rsrc.x1, rsrc.y1); 504 if(span.ptr) 505 { 506 int x1src = rsrc.x1; 507 int x1dst = rdst.x1; 508 int len = rc.x2; 509 if(span.x1 > x1src) 510 { 511 x1dst += span.x1 - x1src; 512 len -= span.x1 - x1src; 513 x1src = span.x1; 514 } 515 if(len > 0) 516 { 517 if(x1src + len-1 > span.x2) 518 { 519 len -= x1src + len - span.x2 - 1; 520 } 521 if(len > 0) 522 { 523 m_ren->blend_from(src, span.ptr, 524 x1dst, rdst.y1, 525 x1src, rsrc.y1, 526 len); 527 } 528 } 529 } 530 rdst.y1 += incy; 531 rsrc.y1 += incy; 532 --rc.y2; 533 } 534 } 535 } 536 537 538 539 private: 540 pixfmt_type* m_ren; 541 rect m_clip_box; 542 }; 543 544 545 } 546 547 #endif 548