1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.4 3 // Copyright (C) 2002-2005 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 typedef typename pixfmt_type::row_data row_data; 36 37 //-------------------------------------------------------------------- renderer_base()38 renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {} renderer_base(pixfmt_type & ren)39 renderer_base(pixfmt_type& ren) : 40 m_ren(&ren), 41 m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) 42 {} attach(pixfmt_type & ren)43 void attach(pixfmt_type& ren) 44 { 45 m_ren = &ren; 46 m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1); 47 } 48 49 //-------------------------------------------------------------------- ren()50 const pixfmt_type& ren() const { return *m_ren; } ren()51 pixfmt_type& ren() { return *m_ren; } 52 53 //-------------------------------------------------------------------- width()54 unsigned width() const { return m_ren->width(); } height()55 unsigned height() const { return m_ren->height(); } 56 57 //-------------------------------------------------------------------- clip_box(int x1,int y1,int x2,int y2)58 bool clip_box(int x1, int y1, int x2, int y2) 59 { 60 rect_i cb(x1, y1, x2, y2); 61 cb.normalize(); 62 if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) 63 { 64 m_clip_box = cb; 65 return true; 66 } 67 m_clip_box.x1 = 1; 68 m_clip_box.y1 = 1; 69 m_clip_box.x2 = 0; 70 m_clip_box.y2 = 0; 71 return false; 72 } 73 74 //-------------------------------------------------------------------- reset_clipping(bool visibility)75 void reset_clipping(bool visibility) 76 { 77 if(visibility) 78 { 79 m_clip_box.x1 = 0; 80 m_clip_box.y1 = 0; 81 m_clip_box.x2 = width() - 1; 82 m_clip_box.y2 = height() - 1; 83 } 84 else 85 { 86 m_clip_box.x1 = 1; 87 m_clip_box.y1 = 1; 88 m_clip_box.x2 = 0; 89 m_clip_box.y2 = 0; 90 } 91 } 92 93 //-------------------------------------------------------------------- clip_box_naked(int x1,int y1,int x2,int y2)94 void clip_box_naked(int x1, int y1, int x2, int y2) 95 { 96 m_clip_box.x1 = x1; 97 m_clip_box.y1 = y1; 98 m_clip_box.x2 = x2; 99 m_clip_box.y2 = y2; 100 } 101 102 //-------------------------------------------------------------------- inbox(int x,int y)103 bool inbox(int x, int y) const 104 { 105 return x >= m_clip_box.x1 && y >= m_clip_box.y1 && 106 x <= m_clip_box.x2 && y <= m_clip_box.y2; 107 } 108 109 //-------------------------------------------------------------------- clip_box()110 const rect_i& clip_box() const { return m_clip_box; } xmin()111 int xmin() const { return m_clip_box.x1; } ymin()112 int ymin() const { return m_clip_box.y1; } xmax()113 int xmax() const { return m_clip_box.x2; } ymax()114 int ymax() const { return m_clip_box.y2; } 115 116 //-------------------------------------------------------------------- bounding_clip_box()117 const rect_i& bounding_clip_box() const { return m_clip_box; } bounding_xmin()118 int bounding_xmin() const { return m_clip_box.x1; } bounding_ymin()119 int bounding_ymin() const { return m_clip_box.y1; } bounding_xmax()120 int bounding_xmax() const { return m_clip_box.x2; } bounding_ymax()121 int bounding_ymax() const { return m_clip_box.y2; } 122 123 //-------------------------------------------------------------------- clear(const color_type & c)124 void clear(const color_type& c) 125 { 126 unsigned y; 127 if(width()) 128 { 129 for(y = 0; y < height(); y++) 130 { 131 m_ren->copy_hline(0, y, width(), c); 132 } 133 } 134 } 135 136 //-------------------------------------------------------------------- fill(const color_type & c)137 void fill(const color_type& c) 138 { 139 unsigned y; 140 if(width()) 141 { 142 for(y = 0; y < height(); y++) 143 { 144 m_ren->blend_hline(0, y, width(), c, cover_mask); 145 } 146 } 147 } 148 149 //-------------------------------------------------------------------- copy_pixel(int x,int y,const color_type & c)150 void copy_pixel(int x, int y, const color_type& c) 151 { 152 if(inbox(x, y)) 153 { 154 m_ren->copy_pixel(x, y, c); 155 } 156 } 157 158 //-------------------------------------------------------------------- blend_pixel(int x,int y,const color_type & c,cover_type cover)159 void blend_pixel(int x, int y, const color_type& c, cover_type cover) 160 { 161 if(inbox(x, y)) 162 { 163 m_ren->blend_pixel(x, y, c, cover); 164 } 165 } 166 167 //-------------------------------------------------------------------- pixel(int x,int y)168 color_type pixel(int x, int y) const 169 { 170 return inbox(x, y) ? 171 m_ren->pixel(x, y) : 172 color_type::no_color(); 173 } 174 175 //-------------------------------------------------------------------- copy_hline(int x1,int y,int x2,const color_type & c)176 void copy_hline(int x1, int y, int x2, const color_type& c) 177 { 178 if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } 179 if(y > ymax()) return; 180 if(y < ymin()) return; 181 if(x1 > xmax()) return; 182 if(x2 < xmin()) return; 183 184 if(x1 < xmin()) x1 = xmin(); 185 if(x2 > xmax()) x2 = xmax(); 186 187 m_ren->copy_hline(x1, y, x2 - x1 + 1, c); 188 } 189 190 //-------------------------------------------------------------------- copy_vline(int x,int y1,int y2,const color_type & c)191 void copy_vline(int x, int y1, int y2, const color_type& c) 192 { 193 if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } 194 if(x > xmax()) return; 195 if(x < xmin()) return; 196 if(y1 > ymax()) return; 197 if(y2 < ymin()) return; 198 199 if(y1 < ymin()) y1 = ymin(); 200 if(y2 > ymax()) y2 = ymax(); 201 202 m_ren->copy_vline(x, y1, y2 - y1 + 1, c); 203 } 204 205 //-------------------------------------------------------------------- blend_hline(int x1,int y,int x2,const color_type & c,cover_type cover)206 void blend_hline(int x1, int y, int x2, 207 const color_type& c, cover_type cover) 208 { 209 if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } 210 if(y > ymax()) return; 211 if(y < ymin()) return; 212 if(x1 > xmax()) return; 213 if(x2 < xmin()) return; 214 215 if(x1 < xmin()) x1 = xmin(); 216 if(x2 > xmax()) x2 = xmax(); 217 218 m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); 219 } 220 221 222 //-------------------------------------------------------------------- blend_vline(int x,int y1,int y2,const color_type & c,cover_type cover)223 void blend_vline(int x, int y1, int y2, 224 const color_type& c, cover_type cover) 225 { 226 if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } 227 if(x > xmax()) return; 228 if(x < xmin()) return; 229 if(y1 > ymax()) return; 230 if(y2 < ymin()) return; 231 232 if(y1 < ymin()) y1 = ymin(); 233 if(y2 > ymax()) y2 = ymax(); 234 235 m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover); 236 } 237 238 239 //-------------------------------------------------------------------- copy_bar(int x1,int y1,int x2,int y2,const color_type & c)240 void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) 241 { 242 rect_i 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->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c); 250 } 251 } 252 } 253 254 //-------------------------------------------------------------------- blend_bar(int x1,int y1,int x2,int y2,const color_type & c,cover_type cover)255 void blend_bar(int x1, int y1, int x2, int y2, 256 const color_type& c, cover_type cover) 257 { 258 rect_i rc(x1, y1, x2, y2); 259 rc.normalize(); 260 if(rc.clip(clip_box())) 261 { 262 int y; 263 for(y = rc.y1; y <= rc.y2; y++) 264 { 265 m_ren->blend_hline(rc.x1, 266 y, 267 unsigned(rc.x2 - rc.x1 + 1), 268 c, 269 cover); 270 } 271 } 272 } 273 274 //-------------------------------------------------------------------- blend_solid_hspan(int x,int y,int len,const color_type & c,const cover_type * covers)275 void blend_solid_hspan(int x, int y, int len, 276 const color_type& c, 277 const cover_type* covers) 278 { 279 if(y > ymax()) return; 280 if(y < ymin()) return; 281 282 if(x < xmin()) 283 { 284 len -= xmin() - x; 285 if(len <= 0) return; 286 covers += xmin() - x; 287 x = xmin(); 288 } 289 if(x + len > xmax()) 290 { 291 len = xmax() - x + 1; 292 if(len <= 0) return; 293 } 294 m_ren->blend_solid_hspan(x, y, len, c, covers); 295 } 296 297 //-------------------------------------------------------------------- blend_solid_hspan_subpix(int x,int y,int len,const color_type & c,const cover_type * covers)298 void blend_solid_hspan_subpix(int x, int y, int len, 299 const color_type& c, 300 const cover_type* covers) 301 { 302 if(y > ymax()) return; 303 if(y < ymin()) return; 304 305 if(x < xmin()) 306 { 307 len -= 3 * (xmin() - x); 308 if(len <= 0) return; 309 covers += 3 * (xmin() - x); 310 x = xmin(); 311 } 312 if(x + len / 3 > xmax()) 313 { 314 len = 3 * (xmax() - x + 1); 315 if(len <= 0) return; 316 } 317 m_ren->blend_solid_hspan_subpix(x, y, len, c, covers); 318 } 319 320 //-------------------------------------------------------------------- blend_solid_vspan(int x,int y,int len,const color_type & c,const cover_type * covers)321 void blend_solid_vspan(int x, int y, int len, 322 const color_type& c, 323 const cover_type* covers) 324 { 325 if(x > xmax()) return; 326 if(x < xmin()) return; 327 328 if(y < ymin()) 329 { 330 len -= ymin() - y; 331 if(len <= 0) return; 332 covers += ymin() - y; 333 y = ymin(); 334 } 335 if(y + len > ymax()) 336 { 337 len = ymax() - y + 1; 338 if(len <= 0) return; 339 } 340 m_ren->blend_solid_vspan(x, y, len, c, covers); 341 } 342 343 344 //-------------------------------------------------------------------- copy_color_hspan(int x,int y,int len,const color_type * colors)345 void copy_color_hspan(int x, int y, int len, const color_type* colors) 346 { 347 if(y > ymax()) return; 348 if(y < ymin()) return; 349 350 if(x < xmin()) 351 { 352 int d = xmin() - x; 353 len -= d; 354 if(len <= 0) return; 355 colors += d; 356 x = xmin(); 357 } 358 if(x + len > xmax()) 359 { 360 len = xmax() - x + 1; 361 if(len <= 0) return; 362 } 363 m_ren->copy_color_hspan(x, y, len, colors); 364 } 365 366 367 //-------------------------------------------------------------------- copy_color_vspan(int x,int y,int len,const color_type * colors)368 void copy_color_vspan(int x, int y, int len, const color_type* colors) 369 { 370 if(x > xmax()) return; 371 if(x < xmin()) return; 372 373 if(y < ymin()) 374 { 375 int d = ymin() - y; 376 len -= d; 377 if(len <= 0) return; 378 colors += d; 379 y = ymin(); 380 } 381 if(y + len > ymax()) 382 { 383 len = ymax() - y + 1; 384 if(len <= 0) return; 385 } 386 m_ren->copy_color_vspan(x, y, len, colors); 387 } 388 389 390 //-------------------------------------------------------------------- 391 void blend_color_hspan(int x, int y, int len, 392 const color_type* colors, 393 const cover_type* covers, 394 cover_type cover = agg::cover_full) 395 { 396 if(y > ymax()) return; 397 if(y < ymin()) return; 398 399 if(x < xmin()) 400 { 401 int d = xmin() - x; 402 len -= d; 403 if(len <= 0) return; 404 if(covers) covers += d; 405 colors += d; 406 x = xmin(); 407 } 408 if(x + len > xmax()) 409 { 410 len = xmax() - x + 1; 411 if(len <= 0) return; 412 } 413 m_ren->blend_color_hspan(x, y, len, colors, covers, cover); 414 } 415 416 //-------------------------------------------------------------------- 417 void blend_color_vspan(int x, int y, int len, 418 const color_type* colors, 419 const cover_type* covers, 420 cover_type cover = agg::cover_full) 421 { 422 if(x > xmax()) return; 423 if(x < xmin()) return; 424 425 if(y < ymin()) 426 { 427 int d = ymin() - y; 428 len -= d; 429 if(len <= 0) return; 430 if(covers) covers += d; 431 colors += d; 432 y = ymin(); 433 } 434 if(y + len > ymax()) 435 { 436 len = ymax() - y + 1; 437 if(len <= 0) return; 438 } 439 m_ren->blend_color_vspan(x, y, len, colors, covers, cover); 440 } 441 442 //-------------------------------------------------------------------- clip_rect_area(rect_i & dst,rect_i & src,int wsrc,int hsrc)443 rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const 444 { 445 rect_i rc(0,0,0,0); 446 rect_i cb = clip_box(); 447 ++cb.x2; 448 ++cb.y2; 449 450 if(src.x1 < 0) 451 { 452 dst.x1 -= src.x1; 453 src.x1 = 0; 454 } 455 if(src.y1 < 0) 456 { 457 dst.y1 -= src.y1; 458 src.y1 = 0; 459 } 460 461 if(src.x2 > wsrc) src.x2 = wsrc; 462 if(src.y2 > hsrc) src.y2 = hsrc; 463 464 if(dst.x1 < cb.x1) 465 { 466 src.x1 += cb.x1 - dst.x1; 467 dst.x1 = cb.x1; 468 } 469 if(dst.y1 < cb.y1) 470 { 471 src.y1 += cb.y1 - dst.y1; 472 dst.y1 = cb.y1; 473 } 474 475 if(dst.x2 > cb.x2) dst.x2 = cb.x2; 476 if(dst.y2 > cb.y2) dst.y2 = cb.y2; 477 478 rc.x2 = dst.x2 - dst.x1; 479 rc.y2 = dst.y2 - dst.y1; 480 481 if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1; 482 if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1; 483 return rc; 484 } 485 486 //-------------------------------------------------------------------- 487 template<class RenBuf> 488 void copy_from(const RenBuf& src, 489 const rect_i* rect_src_ptr = 0, 490 int dx = 0, 491 int dy = 0) 492 { 493 rect_i rsrc(0, 0, src.width(), src.height()); 494 if(rect_src_ptr) 495 { 496 rsrc.x1 = rect_src_ptr->x1; 497 rsrc.y1 = rect_src_ptr->y1; 498 rsrc.x2 = rect_src_ptr->x2 + 1; 499 rsrc.y2 = rect_src_ptr->y2 + 1; 500 } 501 502 // Version with xdst, ydst (absolute positioning) 503 //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); 504 505 // Version with dx, dy (relative positioning) 506 rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); 507 508 rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); 509 510 if(rc.x2 > 0) 511 { 512 int incy = 1; 513 if(rdst.y1 > rsrc.y1) 514 { 515 rsrc.y1 += rc.y2 - 1; 516 rdst.y1 += rc.y2 - 1; 517 incy = -1; 518 } 519 while(rc.y2 > 0) 520 { 521 m_ren->copy_from(src, 522 rdst.x1, rdst.y1, 523 rsrc.x1, rsrc.y1, 524 rc.x2); 525 rdst.y1 += incy; 526 rsrc.y1 += incy; 527 --rc.y2; 528 } 529 } 530 } 531 532 //-------------------------------------------------------------------- 533 template<class SrcPixelFormatRenderer> 534 void blend_from(const SrcPixelFormatRenderer& src, 535 const rect_i* rect_src_ptr = 0, 536 int dx = 0, 537 int dy = 0, 538 cover_type cover = agg::cover_full) 539 { 540 rect_i rsrc(0, 0, src.width(), src.height()); 541 if(rect_src_ptr) 542 { 543 rsrc.x1 = rect_src_ptr->x1; 544 rsrc.y1 = rect_src_ptr->y1; 545 rsrc.x2 = rect_src_ptr->x2 + 1; 546 rsrc.y2 = rect_src_ptr->y2 + 1; 547 } 548 549 // Version with xdst, ydst (absolute positioning) 550 //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); 551 552 // Version with dx, dy (relative positioning) 553 rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); 554 rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); 555 556 if(rc.x2 > 0) 557 { 558 int incy = 1; 559 if(rdst.y1 > rsrc.y1) 560 { 561 rsrc.y1 += rc.y2 - 1; 562 rdst.y1 += rc.y2 - 1; 563 incy = -1; 564 } 565 while(rc.y2 > 0) 566 { 567 typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); 568 if(rw.ptr) 569 { 570 int x1src = rsrc.x1; 571 int x1dst = rdst.x1; 572 int len = rc.x2; 573 if(rw.x1 > x1src) 574 { 575 x1dst += rw.x1 - x1src; 576 len -= rw.x1 - x1src; 577 x1src = rw.x1; 578 } 579 if(len > 0) 580 { 581 if(x1src + len-1 > rw.x2) 582 { 583 len -= x1src + len - rw.x2 - 1; 584 } 585 if(len > 0) 586 { 587 m_ren->blend_from(src, 588 x1dst, rdst.y1, 589 x1src, rsrc.y1, 590 len, 591 cover); 592 } 593 } 594 } 595 rdst.y1 += incy; 596 rsrc.y1 += incy; 597 --rc.y2; 598 } 599 } 600 } 601 602 private: 603 pixfmt_type* m_ren; 604 rect_i m_clip_box; 605 }; 606 607 608 } 609 610 #endif 611