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 #ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED 16 #define AGG_RENDERER_OUTLINE_AA_INCLUDED 17 18 #include "agg_array.h" 19 #include "agg_math.h" 20 #include "agg_line_aa_basics.h" 21 #include "agg_dda_line.h" 22 #include "agg_ellipse_bresenham.h" 23 #include "agg_renderer_base.h" 24 #include "agg_gamma_functions.h" 25 #include "agg_clip_liang_barsky.h" 26 27 namespace agg 28 { 29 30 //===================================================distance_interpolator0 31 class distance_interpolator0 32 { 33 public: 34 //--------------------------------------------------------------------- 35 distance_interpolator0() {} 36 distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) : 37 m_dx(line_mr(x2) - line_mr(x1)), 38 m_dy(line_mr(y2) - line_mr(y1)), 39 m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy - 40 (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx) 41 { 42 m_dx <<= line_mr_subpixel_shift; 43 m_dy <<= line_mr_subpixel_shift; 44 } 45 46 //--------------------------------------------------------------------- 47 void inc_x() { m_dist += m_dy; } 48 int dist() const { return m_dist; } 49 50 private: 51 //--------------------------------------------------------------------- 52 int m_dx; 53 int m_dy; 54 int m_dist; 55 }; 56 57 //==================================================distance_interpolator00 58 class distance_interpolator00 59 { 60 public: 61 //--------------------------------------------------------------------- 62 distance_interpolator00() {} 63 distance_interpolator00(int xc, int yc, 64 int x1, int y1, int x2, int y2, 65 int x, int y) : 66 m_dx1(line_mr(x1) - line_mr(xc)), 67 m_dy1(line_mr(y1) - line_mr(yc)), 68 m_dx2(line_mr(x2) - line_mr(xc)), 69 m_dy2(line_mr(y2) - line_mr(yc)), 70 m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 - 71 (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1), 72 m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 - 73 (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2) 74 { 75 m_dx1 <<= line_mr_subpixel_shift; 76 m_dy1 <<= line_mr_subpixel_shift; 77 m_dx2 <<= line_mr_subpixel_shift; 78 m_dy2 <<= line_mr_subpixel_shift; 79 } 80 81 //--------------------------------------------------------------------- 82 void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; } 83 int dist1() const { return m_dist1; } 84 int dist2() const { return m_dist2; } 85 86 private: 87 //--------------------------------------------------------------------- 88 int m_dx1; 89 int m_dy1; 90 int m_dx2; 91 int m_dy2; 92 int m_dist1; 93 int m_dist2; 94 }; 95 96 //===================================================distance_interpolator1 97 class distance_interpolator1 98 { 99 public: 100 //--------------------------------------------------------------------- 101 distance_interpolator1() {} 102 distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) : 103 m_dx(x2 - x1), 104 m_dy(y2 - y1), 105 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 106 double(y + line_subpixel_scale/2 - y2) * double(m_dx))) 107 { 108 m_dx <<= line_subpixel_shift; 109 m_dy <<= line_subpixel_shift; 110 } 111 112 //--------------------------------------------------------------------- 113 void inc_x() { m_dist += m_dy; } 114 void dec_x() { m_dist -= m_dy; } 115 void inc_y() { m_dist -= m_dx; } 116 void dec_y() { m_dist += m_dx; } 117 118 //--------------------------------------------------------------------- 119 void inc_x(int dy) 120 { 121 m_dist += m_dy; 122 if(dy > 0) m_dist -= m_dx; 123 if(dy < 0) m_dist += m_dx; 124 } 125 126 //--------------------------------------------------------------------- 127 void dec_x(int dy) 128 { 129 m_dist -= m_dy; 130 if(dy > 0) m_dist -= m_dx; 131 if(dy < 0) m_dist += m_dx; 132 } 133 134 //--------------------------------------------------------------------- 135 void inc_y(int dx) 136 { 137 m_dist -= m_dx; 138 if(dx > 0) m_dist += m_dy; 139 if(dx < 0) m_dist -= m_dy; 140 } 141 142 void dec_y(int dx) 143 //--------------------------------------------------------------------- 144 { 145 m_dist += m_dx; 146 if(dx > 0) m_dist += m_dy; 147 if(dx < 0) m_dist -= m_dy; 148 } 149 150 //--------------------------------------------------------------------- 151 int dist() const { return m_dist; } 152 int dx() const { return m_dx; } 153 int dy() const { return m_dy; } 154 155 private: 156 //--------------------------------------------------------------------- 157 int m_dx; 158 int m_dy; 159 int m_dist; 160 }; 161 162 163 164 165 166 //===================================================distance_interpolator2 167 class distance_interpolator2 168 { 169 public: 170 //--------------------------------------------------------------------- 171 distance_interpolator2() {} 172 distance_interpolator2(int x1, int y1, int x2, int y2, 173 int sx, int sy, int x, int y) : 174 m_dx(x2 - x1), 175 m_dy(y2 - y1), 176 m_dx_start(line_mr(sx) - line_mr(x1)), 177 m_dy_start(line_mr(sy) - line_mr(y1)), 178 179 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 180 double(y + line_subpixel_scale/2 - y2) * double(m_dx))), 181 182 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - 183 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start) 184 { 185 m_dx <<= line_subpixel_shift; 186 m_dy <<= line_subpixel_shift; 187 m_dx_start <<= line_mr_subpixel_shift; 188 m_dy_start <<= line_mr_subpixel_shift; 189 } 190 191 distance_interpolator2(int x1, int y1, int x2, int y2, 192 int ex, int ey, int x, int y, int) : 193 m_dx(x2 - x1), 194 m_dy(y2 - y1), 195 m_dx_start(line_mr(ex) - line_mr(x2)), 196 m_dy_start(line_mr(ey) - line_mr(y2)), 197 198 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 199 double(y + line_subpixel_scale/2 - y2) * double(m_dx))), 200 201 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start - 202 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start) 203 { 204 m_dx <<= line_subpixel_shift; 205 m_dy <<= line_subpixel_shift; 206 m_dx_start <<= line_mr_subpixel_shift; 207 m_dy_start <<= line_mr_subpixel_shift; 208 } 209 210 211 //--------------------------------------------------------------------- 212 void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; } 213 void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; } 214 void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; } 215 void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; } 216 217 //--------------------------------------------------------------------- 218 void inc_x(int dy) 219 { 220 m_dist += m_dy; 221 m_dist_start += m_dy_start; 222 if(dy > 0) 223 { 224 m_dist -= m_dx; 225 m_dist_start -= m_dx_start; 226 } 227 if(dy < 0) 228 { 229 m_dist += m_dx; 230 m_dist_start += m_dx_start; 231 } 232 } 233 234 //--------------------------------------------------------------------- 235 void dec_x(int dy) 236 { 237 m_dist -= m_dy; 238 m_dist_start -= m_dy_start; 239 if(dy > 0) 240 { 241 m_dist -= m_dx; 242 m_dist_start -= m_dx_start; 243 } 244 if(dy < 0) 245 { 246 m_dist += m_dx; 247 m_dist_start += m_dx_start; 248 } 249 } 250 251 //--------------------------------------------------------------------- 252 void inc_y(int dx) 253 { 254 m_dist -= m_dx; 255 m_dist_start -= m_dx_start; 256 if(dx > 0) 257 { 258 m_dist += m_dy; 259 m_dist_start += m_dy_start; 260 } 261 if(dx < 0) 262 { 263 m_dist -= m_dy; 264 m_dist_start -= m_dy_start; 265 } 266 } 267 268 //--------------------------------------------------------------------- 269 void dec_y(int dx) 270 { 271 m_dist += m_dx; 272 m_dist_start += m_dx_start; 273 if(dx > 0) 274 { 275 m_dist += m_dy; 276 m_dist_start += m_dy_start; 277 } 278 if(dx < 0) 279 { 280 m_dist -= m_dy; 281 m_dist_start -= m_dy_start; 282 } 283 } 284 285 //--------------------------------------------------------------------- 286 int dist() const { return m_dist; } 287 int dist_start() const { return m_dist_start; } 288 int dist_end() const { return m_dist_start; } 289 290 //--------------------------------------------------------------------- 291 int dx() const { return m_dx; } 292 int dy() const { return m_dy; } 293 int dx_start() const { return m_dx_start; } 294 int dy_start() const { return m_dy_start; } 295 int dx_end() const { return m_dx_start; } 296 int dy_end() const { return m_dy_start; } 297 298 private: 299 //--------------------------------------------------------------------- 300 int m_dx; 301 int m_dy; 302 int m_dx_start; 303 int m_dy_start; 304 305 int m_dist; 306 int m_dist_start; 307 }; 308 309 310 311 312 313 //===================================================distance_interpolator3 314 class distance_interpolator3 315 { 316 public: 317 //--------------------------------------------------------------------- 318 distance_interpolator3() {} 319 distance_interpolator3(int x1, int y1, int x2, int y2, 320 int sx, int sy, int ex, int ey, 321 int x, int y) : 322 m_dx(x2 - x1), 323 m_dy(y2 - y1), 324 m_dx_start(line_mr(sx) - line_mr(x1)), 325 m_dy_start(line_mr(sy) - line_mr(y1)), 326 m_dx_end(line_mr(ex) - line_mr(x2)), 327 m_dy_end(line_mr(ey) - line_mr(y2)), 328 329 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 330 double(y + line_subpixel_scale/2 - y2) * double(m_dx))), 331 332 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - 333 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), 334 335 m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - 336 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end) 337 { 338 m_dx <<= line_subpixel_shift; 339 m_dy <<= line_subpixel_shift; 340 m_dx_start <<= line_mr_subpixel_shift; 341 m_dy_start <<= line_mr_subpixel_shift; 342 m_dx_end <<= line_mr_subpixel_shift; 343 m_dy_end <<= line_mr_subpixel_shift; 344 } 345 346 //--------------------------------------------------------------------- 347 void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } 348 void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; } 349 void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } 350 void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } 351 352 //--------------------------------------------------------------------- 353 void inc_x(int dy) 354 { 355 m_dist += m_dy; 356 m_dist_start += m_dy_start; 357 m_dist_end += m_dy_end; 358 if(dy > 0) 359 { 360 m_dist -= m_dx; 361 m_dist_start -= m_dx_start; 362 m_dist_end -= m_dx_end; 363 } 364 if(dy < 0) 365 { 366 m_dist += m_dx; 367 m_dist_start += m_dx_start; 368 m_dist_end += m_dx_end; 369 } 370 } 371 372 //--------------------------------------------------------------------- 373 void dec_x(int dy) 374 { 375 m_dist -= m_dy; 376 m_dist_start -= m_dy_start; 377 m_dist_end -= m_dy_end; 378 if(dy > 0) 379 { 380 m_dist -= m_dx; 381 m_dist_start -= m_dx_start; 382 m_dist_end -= m_dx_end; 383 } 384 if(dy < 0) 385 { 386 m_dist += m_dx; 387 m_dist_start += m_dx_start; 388 m_dist_end += m_dx_end; 389 } 390 } 391 392 //--------------------------------------------------------------------- 393 void inc_y(int dx) 394 { 395 m_dist -= m_dx; 396 m_dist_start -= m_dx_start; 397 m_dist_end -= m_dx_end; 398 if(dx > 0) 399 { 400 m_dist += m_dy; 401 m_dist_start += m_dy_start; 402 m_dist_end += m_dy_end; 403 } 404 if(dx < 0) 405 { 406 m_dist -= m_dy; 407 m_dist_start -= m_dy_start; 408 m_dist_end -= m_dy_end; 409 } 410 } 411 412 //--------------------------------------------------------------------- 413 void dec_y(int dx) 414 { 415 m_dist += m_dx; 416 m_dist_start += m_dx_start; 417 m_dist_end += m_dx_end; 418 if(dx > 0) 419 { 420 m_dist += m_dy; 421 m_dist_start += m_dy_start; 422 m_dist_end += m_dy_end; 423 } 424 if(dx < 0) 425 { 426 m_dist -= m_dy; 427 m_dist_start -= m_dy_start; 428 m_dist_end -= m_dy_end; 429 } 430 } 431 432 //--------------------------------------------------------------------- 433 int dist() const { return m_dist; } 434 int dist_start() const { return m_dist_start; } 435 int dist_end() const { return m_dist_end; } 436 437 //--------------------------------------------------------------------- 438 int dx() const { return m_dx; } 439 int dy() const { return m_dy; } 440 int dx_start() const { return m_dx_start; } 441 int dy_start() const { return m_dy_start; } 442 int dx_end() const { return m_dx_end; } 443 int dy_end() const { return m_dy_end; } 444 445 private: 446 //--------------------------------------------------------------------- 447 int m_dx; 448 int m_dy; 449 int m_dx_start; 450 int m_dy_start; 451 int m_dx_end; 452 int m_dy_end; 453 454 int m_dist; 455 int m_dist_start; 456 int m_dist_end; 457 }; 458 459 460 461 462 463 //================================================line_interpolator_aa_base 464 template<class Renderer> class line_interpolator_aa_base 465 { 466 public: 467 typedef Renderer renderer_type; 468 typedef typename Renderer::color_type color_type; 469 470 //--------------------------------------------------------------------- 471 enum max_half_width_e 472 { 473 max_half_width = 64 474 }; 475 476 //--------------------------------------------------------------------- 477 line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) : 478 m_lp(&lp), 479 m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : 480 line_dbl_hr(lp.y2 - lp.y1), 481 lp.vertical ? abs(lp.y2 - lp.y1) : 482 abs(lp.x2 - lp.x1) + 1), 483 m_ren(ren), 484 m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len), 485 m_x(lp.x1 >> line_subpixel_shift), 486 m_y(lp.y1 >> line_subpixel_shift), 487 m_old_x(m_x), 488 m_old_y(m_y), 489 m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : 490 abs((lp.x2 >> line_subpixel_shift) - m_x))), 491 m_width(ren.subpixel_width()), 492 //m_max_extent(m_width >> (line_subpixel_shift - 2)), 493 m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift), 494 m_step(0) 495 { 496 agg::dda2_line_interpolator li(0, lp.vertical ? 497 (lp.dy << agg::line_subpixel_shift) : 498 (lp.dx << agg::line_subpixel_shift), 499 lp.len); 500 501 unsigned i; 502 int stop = m_width + line_subpixel_scale * 2; 503 for(i = 0; i < max_half_width; ++i) 504 { 505 m_dist[i] = li.y(); 506 if(m_dist[i] >= stop) break; 507 ++li; 508 } 509 m_dist[i++] = 0x7FFF0000; 510 } 511 512 //--------------------------------------------------------------------- 513 template<class DI> int step_hor_base(DI& di) 514 { 515 ++m_li; 516 m_x += m_lp->inc; 517 m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift; 518 519 if(m_lp->inc > 0) di.inc_x(m_y - m_old_y); 520 else di.dec_x(m_y - m_old_y); 521 522 m_old_y = m_y; 523 524 return di.dist() / m_len; 525 } 526 527 //--------------------------------------------------------------------- 528 template<class DI> int step_ver_base(DI& di) 529 { 530 ++m_li; 531 m_y += m_lp->inc; 532 m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift; 533 534 if(m_lp->inc > 0) di.inc_y(m_x - m_old_x); 535 else di.dec_y(m_x - m_old_x); 536 537 m_old_x = m_x; 538 539 return di.dist() / m_len; 540 } 541 542 //--------------------------------------------------------------------- 543 bool vertical() const { return m_lp->vertical; } 544 int width() const { return m_width; } 545 int count() const { return m_count; } 546 547 private: 548 line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&); 549 const line_interpolator_aa_base<Renderer>& 550 operator = (const line_interpolator_aa_base<Renderer>&); 551 552 protected: 553 const line_parameters* m_lp; 554 dda2_line_interpolator m_li; 555 renderer_type& m_ren; 556 int m_len; 557 int m_x; 558 int m_y; 559 int m_old_x; 560 int m_old_y; 561 int m_count; 562 int m_width; 563 int m_max_extent; 564 int m_step; 565 int m_dist[max_half_width + 1]; 566 cover_type m_covers[max_half_width * 2 + 4]; 567 }; 568 569 570 571 572 573 574 575 //====================================================line_interpolator_aa0 576 template<class Renderer> class line_interpolator_aa0 : 577 public line_interpolator_aa_base<Renderer> 578 { 579 public: 580 typedef Renderer renderer_type; 581 typedef typename Renderer::color_type color_type; 582 typedef line_interpolator_aa_base<Renderer> base_type; 583 584 //--------------------------------------------------------------------- 585 line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) : 586 line_interpolator_aa_base<Renderer>(ren, lp), 587 m_di(lp.x1, lp.y1, lp.x2, lp.y2, 588 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) 589 { 590 base_type::m_li.adjust_forward(); 591 } 592 593 //--------------------------------------------------------------------- 594 bool step_hor() 595 { 596 int dist; 597 int dy; 598 int s1 = base_type::step_hor_base(m_di); 599 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 600 cover_type* p1 = p0; 601 602 *p1++ = (cover_type)base_type::m_ren.cover(s1); 603 604 dy = 1; 605 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) 606 { 607 *p1++ = (cover_type)base_type::m_ren.cover(dist); 608 ++dy; 609 } 610 611 dy = 1; 612 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) 613 { 614 *--p0 = (cover_type)base_type::m_ren.cover(dist); 615 ++dy; 616 } 617 base_type::m_ren.blend_solid_vspan(base_type::m_x, 618 base_type::m_y - dy + 1, 619 unsigned(p1 - p0), 620 p0); 621 return ++base_type::m_step < base_type::m_count; 622 } 623 624 //--------------------------------------------------------------------- 625 bool step_ver() 626 { 627 int dist; 628 int dx; 629 int s1 = base_type::step_ver_base(m_di); 630 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 631 cover_type* p1 = p0; 632 633 *p1++ = (cover_type)base_type::m_ren.cover(s1); 634 635 dx = 1; 636 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) 637 { 638 *p1++ = (cover_type)base_type::m_ren.cover(dist); 639 ++dx; 640 } 641 642 dx = 1; 643 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) 644 { 645 *--p0 = (cover_type)base_type::m_ren.cover(dist); 646 ++dx; 647 } 648 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 649 base_type::m_y, 650 unsigned(p1 - p0), 651 p0); 652 return ++base_type::m_step < base_type::m_count; 653 } 654 655 private: 656 line_interpolator_aa0(const line_interpolator_aa0<Renderer>&); 657 const line_interpolator_aa0<Renderer>& 658 operator = (const line_interpolator_aa0<Renderer>&); 659 660 //--------------------------------------------------------------------- 661 distance_interpolator1 m_di; 662 }; 663 664 665 666 667 668 669 //====================================================line_interpolator_aa1 670 template<class Renderer> class line_interpolator_aa1 : 671 public line_interpolator_aa_base<Renderer> 672 { 673 public: 674 typedef Renderer renderer_type; 675 typedef typename Renderer::color_type color_type; 676 typedef line_interpolator_aa_base<Renderer> base_type; 677 678 //--------------------------------------------------------------------- 679 line_interpolator_aa1(renderer_type& ren, const line_parameters& lp, 680 int sx, int sy) : 681 line_interpolator_aa_base<Renderer>(ren, lp), 682 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, 683 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) 684 { 685 int dist1_start; 686 int dist2_start; 687 688 int npix = 1; 689 690 if(lp.vertical) 691 { 692 do 693 { 694 --base_type::m_li; 695 base_type::m_y -= lp.inc; 696 base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; 697 698 if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); 699 else m_di.inc_y(base_type::m_x - base_type::m_old_x); 700 701 base_type::m_old_x = base_type::m_x; 702 703 dist1_start = dist2_start = m_di.dist_start(); 704 705 int dx = 0; 706 if(dist1_start < 0) ++npix; 707 do 708 { 709 dist1_start += m_di.dy_start(); 710 dist2_start -= m_di.dy_start(); 711 if(dist1_start < 0) ++npix; 712 if(dist2_start < 0) ++npix; 713 ++dx; 714 } 715 while(base_type::m_dist[dx] <= base_type::m_width); 716 --base_type::m_step; 717 if(npix == 0) break; 718 npix = 0; 719 } 720 while(base_type::m_step >= -base_type::m_max_extent); 721 } 722 else 723 { 724 do 725 { 726 --base_type::m_li; 727 base_type::m_x -= lp.inc; 728 base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; 729 730 if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); 731 else m_di.inc_x(base_type::m_y - base_type::m_old_y); 732 733 base_type::m_old_y = base_type::m_y; 734 735 dist1_start = dist2_start = m_di.dist_start(); 736 737 int dy = 0; 738 if(dist1_start < 0) ++npix; 739 do 740 { 741 dist1_start -= m_di.dx_start(); 742 dist2_start += m_di.dx_start(); 743 if(dist1_start < 0) ++npix; 744 if(dist2_start < 0) ++npix; 745 ++dy; 746 } 747 while(base_type::m_dist[dy] <= base_type::m_width); 748 --base_type::m_step; 749 if(npix == 0) break; 750 npix = 0; 751 } 752 while(base_type::m_step >= -base_type::m_max_extent); 753 } 754 base_type::m_li.adjust_forward(); 755 } 756 757 //--------------------------------------------------------------------- 758 bool step_hor() 759 { 760 int dist_start; 761 int dist; 762 int dy; 763 int s1 = base_type::step_hor_base(m_di); 764 765 dist_start = m_di.dist_start(); 766 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 767 cover_type* p1 = p0; 768 769 *p1 = 0; 770 if(dist_start <= 0) 771 { 772 *p1 = (cover_type)base_type::m_ren.cover(s1); 773 } 774 ++p1; 775 776 dy = 1; 777 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) 778 { 779 dist_start -= m_di.dx_start(); 780 *p1 = 0; 781 if(dist_start <= 0) 782 { 783 *p1 = (cover_type)base_type::m_ren.cover(dist); 784 } 785 ++p1; 786 ++dy; 787 } 788 789 dy = 1; 790 dist_start = m_di.dist_start(); 791 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) 792 { 793 dist_start += m_di.dx_start(); 794 *--p0 = 0; 795 if(dist_start <= 0) 796 { 797 *p0 = (cover_type)base_type::m_ren.cover(dist); 798 } 799 ++dy; 800 } 801 802 base_type::m_ren.blend_solid_vspan(base_type::m_x, 803 base_type::m_y - dy + 1, 804 unsigned(p1 - p0), 805 p0); 806 return ++base_type::m_step < base_type::m_count; 807 } 808 809 //--------------------------------------------------------------------- 810 bool step_ver() 811 { 812 int dist_start; 813 int dist; 814 int dx; 815 int s1 = base_type::step_ver_base(m_di); 816 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 817 cover_type* p1 = p0; 818 819 dist_start = m_di.dist_start(); 820 821 *p1 = 0; 822 if(dist_start <= 0) 823 { 824 *p1 = (cover_type)base_type::m_ren.cover(s1); 825 } 826 ++p1; 827 828 dx = 1; 829 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) 830 { 831 dist_start += m_di.dy_start(); 832 *p1 = 0; 833 if(dist_start <= 0) 834 { 835 *p1 = (cover_type)base_type::m_ren.cover(dist); 836 } 837 ++p1; 838 ++dx; 839 } 840 841 dx = 1; 842 dist_start = m_di.dist_start(); 843 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) 844 { 845 dist_start -= m_di.dy_start(); 846 *--p0 = 0; 847 if(dist_start <= 0) 848 { 849 *p0 = (cover_type)base_type::m_ren.cover(dist); 850 } 851 ++dx; 852 } 853 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 854 base_type::m_y, 855 unsigned(p1 - p0), 856 p0); 857 return ++base_type::m_step < base_type::m_count; 858 } 859 860 private: 861 line_interpolator_aa1(const line_interpolator_aa1<Renderer>&); 862 const line_interpolator_aa1<Renderer>& 863 operator = (const line_interpolator_aa1<Renderer>&); 864 865 //--------------------------------------------------------------------- 866 distance_interpolator2 m_di; 867 }; 868 869 870 871 872 873 874 875 876 877 878 879 880 //====================================================line_interpolator_aa2 881 template<class Renderer> class line_interpolator_aa2 : 882 public line_interpolator_aa_base<Renderer> 883 { 884 public: 885 typedef Renderer renderer_type; 886 typedef typename Renderer::color_type color_type; 887 typedef line_interpolator_aa_base<Renderer> base_type; 888 889 //--------------------------------------------------------------------- 890 line_interpolator_aa2(renderer_type& ren, const line_parameters& lp, 891 int ex, int ey) : 892 line_interpolator_aa_base<Renderer>(ren, lp), 893 m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey, 894 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask, 895 0) 896 { 897 base_type::m_li.adjust_forward(); 898 base_type::m_step -= base_type::m_max_extent; 899 } 900 901 //--------------------------------------------------------------------- 902 bool step_hor() 903 { 904 int dist_end; 905 int dist; 906 int dy; 907 int s1 = base_type::step_hor_base(m_di); 908 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 909 cover_type* p1 = p0; 910 911 dist_end = m_di.dist_end(); 912 913 int npix = 0; 914 *p1 = 0; 915 if(dist_end > 0) 916 { 917 *p1 = (cover_type)base_type::m_ren.cover(s1); 918 ++npix; 919 } 920 ++p1; 921 922 dy = 1; 923 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) 924 { 925 dist_end -= m_di.dx_end(); 926 *p1 = 0; 927 if(dist_end > 0) 928 { 929 *p1 = (cover_type)base_type::m_ren.cover(dist); 930 ++npix; 931 } 932 ++p1; 933 ++dy; 934 } 935 936 dy = 1; 937 dist_end = m_di.dist_end(); 938 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) 939 { 940 dist_end += m_di.dx_end(); 941 *--p0 = 0; 942 if(dist_end > 0) 943 { 944 *p0 = (cover_type)base_type::m_ren.cover(dist); 945 ++npix; 946 } 947 ++dy; 948 } 949 base_type::m_ren.blend_solid_vspan(base_type::m_x, 950 base_type::m_y - dy + 1, 951 unsigned(p1 - p0), 952 p0); 953 return npix && ++base_type::m_step < base_type::m_count; 954 } 955 956 //--------------------------------------------------------------------- 957 bool step_ver() 958 { 959 int dist_end; 960 int dist; 961 int dx; 962 int s1 = base_type::step_ver_base(m_di); 963 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 964 cover_type* p1 = p0; 965 966 dist_end = m_di.dist_end(); 967 968 int npix = 0; 969 *p1 = 0; 970 if(dist_end > 0) 971 { 972 *p1 = (cover_type)base_type::m_ren.cover(s1); 973 ++npix; 974 } 975 ++p1; 976 977 dx = 1; 978 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) 979 { 980 dist_end += m_di.dy_end(); 981 *p1 = 0; 982 if(dist_end > 0) 983 { 984 *p1 = (cover_type)base_type::m_ren.cover(dist); 985 ++npix; 986 } 987 ++p1; 988 ++dx; 989 } 990 991 dx = 1; 992 dist_end = m_di.dist_end(); 993 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) 994 { 995 dist_end -= m_di.dy_end(); 996 *--p0 = 0; 997 if(dist_end > 0) 998 { 999 *p0 = (cover_type)base_type::m_ren.cover(dist); 1000 ++npix; 1001 } 1002 ++dx; 1003 } 1004 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 1005 base_type::m_y, 1006 unsigned(p1 - p0), 1007 p0); 1008 return npix && ++base_type::m_step < base_type::m_count; 1009 } 1010 1011 private: 1012 line_interpolator_aa2(const line_interpolator_aa2<Renderer>&); 1013 const line_interpolator_aa2<Renderer>& 1014 operator = (const line_interpolator_aa2<Renderer>&); 1015 1016 //--------------------------------------------------------------------- 1017 distance_interpolator2 m_di; 1018 }; 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 //====================================================line_interpolator_aa3 1030 template<class Renderer> class line_interpolator_aa3 : 1031 public line_interpolator_aa_base<Renderer> 1032 { 1033 public: 1034 typedef Renderer renderer_type; 1035 typedef typename Renderer::color_type color_type; 1036 typedef line_interpolator_aa_base<Renderer> base_type; 1037 1038 //--------------------------------------------------------------------- 1039 line_interpolator_aa3(renderer_type& ren, const line_parameters& lp, 1040 int sx, int sy, int ex, int ey) : 1041 line_interpolator_aa_base<Renderer>(ren, lp), 1042 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, 1043 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) 1044 { 1045 int dist1_start; 1046 int dist2_start; 1047 int npix = 1; 1048 if(lp.vertical) 1049 { 1050 do 1051 { 1052 --base_type::m_li; 1053 base_type::m_y -= lp.inc; 1054 base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; 1055 1056 if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); 1057 else m_di.inc_y(base_type::m_x - base_type::m_old_x); 1058 1059 base_type::m_old_x = base_type::m_x; 1060 1061 dist1_start = dist2_start = m_di.dist_start(); 1062 1063 int dx = 0; 1064 if(dist1_start < 0) ++npix; 1065 do 1066 { 1067 dist1_start += m_di.dy_start(); 1068 dist2_start -= m_di.dy_start(); 1069 if(dist1_start < 0) ++npix; 1070 if(dist2_start < 0) ++npix; 1071 ++dx; 1072 } 1073 while(base_type::m_dist[dx] <= base_type::m_width); 1074 if(npix == 0) break; 1075 npix = 0; 1076 } 1077 while(--base_type::m_step >= -base_type::m_max_extent); 1078 } 1079 else 1080 { 1081 do 1082 { 1083 --base_type::m_li; 1084 base_type::m_x -= lp.inc; 1085 base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; 1086 1087 if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); 1088 else m_di.inc_x(base_type::m_y - base_type::m_old_y); 1089 1090 base_type::m_old_y = base_type::m_y; 1091 1092 dist1_start = dist2_start = m_di.dist_start(); 1093 1094 int dy = 0; 1095 if(dist1_start < 0) ++npix; 1096 do 1097 { 1098 dist1_start -= m_di.dx_start(); 1099 dist2_start += m_di.dx_start(); 1100 if(dist1_start < 0) ++npix; 1101 if(dist2_start < 0) ++npix; 1102 ++dy; 1103 } 1104 while(base_type::m_dist[dy] <= base_type::m_width); 1105 if(npix == 0) break; 1106 npix = 0; 1107 } 1108 while(--base_type::m_step >= -base_type::m_max_extent); 1109 } 1110 base_type::m_li.adjust_forward(); 1111 base_type::m_step -= base_type::m_max_extent; 1112 } 1113 1114 1115 //--------------------------------------------------------------------- 1116 bool step_hor() 1117 { 1118 int dist_start; 1119 int dist_end; 1120 int dist; 1121 int dy; 1122 int s1 = base_type::step_hor_base(m_di); 1123 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 1124 cover_type* p1 = p0; 1125 1126 dist_start = m_di.dist_start(); 1127 dist_end = m_di.dist_end(); 1128 1129 int npix = 0; 1130 *p1 = 0; 1131 if(dist_end > 0) 1132 { 1133 if(dist_start <= 0) 1134 { 1135 *p1 = (cover_type)base_type::m_ren.cover(s1); 1136 } 1137 ++npix; 1138 } 1139 ++p1; 1140 1141 dy = 1; 1142 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) 1143 { 1144 dist_start -= m_di.dx_start(); 1145 dist_end -= m_di.dx_end(); 1146 *p1 = 0; 1147 if(dist_end > 0 && dist_start <= 0) 1148 { 1149 *p1 = (cover_type)base_type::m_ren.cover(dist); 1150 ++npix; 1151 } 1152 ++p1; 1153 ++dy; 1154 } 1155 1156 dy = 1; 1157 dist_start = m_di.dist_start(); 1158 dist_end = m_di.dist_end(); 1159 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) 1160 { 1161 dist_start += m_di.dx_start(); 1162 dist_end += m_di.dx_end(); 1163 *--p0 = 0; 1164 if(dist_end > 0 && dist_start <= 0) 1165 { 1166 *p0 = (cover_type)base_type::m_ren.cover(dist); 1167 ++npix; 1168 } 1169 ++dy; 1170 } 1171 base_type::m_ren.blend_solid_vspan(base_type::m_x, 1172 base_type::m_y - dy + 1, 1173 unsigned(p1 - p0), 1174 p0); 1175 return npix && ++base_type::m_step < base_type::m_count; 1176 } 1177 1178 //--------------------------------------------------------------------- 1179 bool step_ver() 1180 { 1181 int dist_start; 1182 int dist_end; 1183 int dist; 1184 int dx; 1185 int s1 = base_type::step_ver_base(m_di); 1186 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 1187 cover_type* p1 = p0; 1188 1189 dist_start = m_di.dist_start(); 1190 dist_end = m_di.dist_end(); 1191 1192 int npix = 0; 1193 *p1 = 0; 1194 if(dist_end > 0) 1195 { 1196 if(dist_start <= 0) 1197 { 1198 *p1 = (cover_type)base_type::m_ren.cover(s1); 1199 } 1200 ++npix; 1201 } 1202 ++p1; 1203 1204 dx = 1; 1205 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) 1206 { 1207 dist_start += m_di.dy_start(); 1208 dist_end += m_di.dy_end(); 1209 *p1 = 0; 1210 if(dist_end > 0 && dist_start <= 0) 1211 { 1212 *p1 = (cover_type)base_type::m_ren.cover(dist); 1213 ++npix; 1214 } 1215 ++p1; 1216 ++dx; 1217 } 1218 1219 dx = 1; 1220 dist_start = m_di.dist_start(); 1221 dist_end = m_di.dist_end(); 1222 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) 1223 { 1224 dist_start -= m_di.dy_start(); 1225 dist_end -= m_di.dy_end(); 1226 *--p0 = 0; 1227 if(dist_end > 0 && dist_start <= 0) 1228 { 1229 *p0 = (cover_type)base_type::m_ren.cover(dist); 1230 ++npix; 1231 } 1232 ++dx; 1233 } 1234 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 1235 base_type::m_y, 1236 unsigned(p1 - p0), 1237 p0); 1238 return npix && ++base_type::m_step < base_type::m_count; 1239 } 1240 1241 private: 1242 line_interpolator_aa3(const line_interpolator_aa3<Renderer>&); 1243 const line_interpolator_aa3<Renderer>& 1244 operator = (const line_interpolator_aa3<Renderer>&); 1245 1246 //--------------------------------------------------------------------- 1247 distance_interpolator3 m_di; 1248 }; 1249 1250 1251 1252 1253 //==========================================================line_profile_aa 1254 // 1255 // See Implementation agg_line_profile_aa.cpp 1256 // 1257 class line_profile_aa 1258 { 1259 public: 1260 //--------------------------------------------------------------------- 1261 typedef int8u value_type; 1262 enum subpixel_scale_e 1263 { 1264 subpixel_shift = line_subpixel_shift, 1265 subpixel_scale = 1 << subpixel_shift, 1266 subpixel_mask = subpixel_scale - 1 1267 }; 1268 1269 enum aa_scale_e 1270 { 1271 aa_shift = 8, 1272 aa_scale = 1 << aa_shift, 1273 aa_mask = aa_scale - 1 1274 }; 1275 1276 //--------------------------------------------------------------------- 1277 line_profile_aa() : 1278 m_subpixel_width(0), 1279 m_min_width(1.0), 1280 m_smoother_width(1.0) 1281 { 1282 int i; 1283 for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i; 1284 } 1285 1286 //--------------------------------------------------------------------- 1287 template<class GammaF> 1288 line_profile_aa(double w, const GammaF& gamma_function) : 1289 m_subpixel_width(0), 1290 m_min_width(1.0), 1291 m_smoother_width(1.0) 1292 { 1293 gamma(gamma_function); 1294 width(w); 1295 } 1296 1297 //--------------------------------------------------------------------- 1298 void min_width(double w) { m_min_width = w; } 1299 void smoother_width(double w) { m_smoother_width = w; } 1300 1301 //--------------------------------------------------------------------- 1302 template<class GammaF> void gamma(const GammaF& gamma_function) 1303 { 1304 int i; 1305 for(i = 0; i < aa_scale; i++) 1306 { 1307 m_gamma[i] = value_type( 1308 uround(gamma_function(double(i) / aa_mask) * aa_mask)); 1309 } 1310 } 1311 1312 void width(double w); 1313 1314 unsigned profile_size() const { return m_profile.size(); } 1315 int subpixel_width() const { return m_subpixel_width; } 1316 1317 //--------------------------------------------------------------------- 1318 double min_width() const { return m_min_width; } 1319 double smoother_width() const { return m_smoother_width; } 1320 1321 //--------------------------------------------------------------------- 1322 value_type value(int dist) const 1323 { 1324 return m_profile[dist + subpixel_scale*2]; 1325 } 1326 1327 private: 1328 line_profile_aa(const line_profile_aa&); 1329 const line_profile_aa& operator = (const line_profile_aa&); 1330 1331 value_type* profile(double w); 1332 void set(double center_width, double smoother_width); 1333 1334 //--------------------------------------------------------------------- 1335 pod_array<value_type> m_profile; 1336 value_type m_gamma[aa_scale]; 1337 int m_subpixel_width; 1338 double m_min_width; 1339 double m_smoother_width; 1340 }; 1341 1342 1343 //======================================================renderer_outline_aa 1344 template<class BaseRenderer> class renderer_outline_aa 1345 { 1346 public: 1347 //--------------------------------------------------------------------- 1348 typedef BaseRenderer base_ren_type; 1349 typedef renderer_outline_aa<base_ren_type> self_type; 1350 typedef typename base_ren_type::color_type color_type; 1351 1352 //--------------------------------------------------------------------- 1353 renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) : 1354 m_ren(&ren), 1355 m_profile(&prof), 1356 m_clip_box(0,0,0,0), 1357 m_clipping(false) 1358 {} 1359 void attach(base_ren_type& ren) { m_ren = &ren; } 1360 1361 //--------------------------------------------------------------------- 1362 void color(const color_type& c) { m_color = c; } 1363 const color_type& color() const { return m_color; } 1364 1365 //--------------------------------------------------------------------- 1366 void profile(const line_profile_aa& prof) { m_profile = &prof; } 1367 const line_profile_aa& profile() const { return *m_profile; } 1368 line_profile_aa& profile() { return *(line_profile_aa*)m_profile; } 1369 1370 //--------------------------------------------------------------------- 1371 int subpixel_width() const { return m_profile->subpixel_width(); } 1372 1373 //--------------------------------------------------------------------- 1374 void reset_clipping() { m_clipping = false; } 1375 void clip_box(double x1, double y1, double x2, double y2) 1376 { 1377 m_clip_box.x1 = line_coord_sat::conv(x1); 1378 m_clip_box.y1 = line_coord_sat::conv(y1); 1379 m_clip_box.x2 = line_coord_sat::conv(x2); 1380 m_clip_box.y2 = line_coord_sat::conv(y2); 1381 m_clipping = true; 1382 } 1383 1384 //--------------------------------------------------------------------- 1385 int cover(int d) const 1386 { 1387 return m_profile->value(d); 1388 } 1389 1390 //------------------------------------------------------------------------- 1391 void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers) 1392 { 1393 m_ren->blend_solid_hspan(x, y, len, m_color, covers); 1394 } 1395 1396 //------------------------------------------------------------------------- 1397 void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers) 1398 { 1399 m_ren->blend_solid_vspan(x, y, len, m_color, covers); 1400 } 1401 1402 //------------------------------------------------------------------------- 1403 static bool accurate_join_only() { return false; } 1404 1405 //------------------------------------------------------------------------- 1406 template<class Cmp> 1407 void semidot_hline(Cmp cmp, 1408 int xc1, int yc1, int xc2, int yc2, 1409 int x1, int y1, int x2) 1410 { 1411 cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; 1412 cover_type* p0 = covers; 1413 cover_type* p1 = covers; 1414 int x = x1 << line_subpixel_shift; 1415 int y = y1 << line_subpixel_shift; 1416 int w = subpixel_width(); 1417 distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y); 1418 x += line_subpixel_scale/2; 1419 y += line_subpixel_scale/2; 1420 1421 int x0 = x1; 1422 int dx = x - xc1; 1423 int dy = y - yc1; 1424 do 1425 { 1426 int d = int(fast_sqrt(dx*dx + dy*dy)); 1427 *p1 = 0; 1428 if(cmp(di.dist()) && d <= w) 1429 { 1430 *p1 = (cover_type)cover(d); 1431 } 1432 ++p1; 1433 dx += line_subpixel_scale; 1434 di.inc_x(); 1435 } 1436 while(++x1 <= x2); 1437 m_ren->blend_solid_hspan(x0, y1, 1438 unsigned(p1 - p0), 1439 color(), 1440 p0); 1441 } 1442 1443 //------------------------------------------------------------------------- 1444 template<class Cmp> 1445 void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2) 1446 { 1447 if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return; 1448 1449 int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); 1450 if(r < 1) r = 1; 1451 ellipse_bresenham_interpolator ei(r, r); 1452 int dx = 0; 1453 int dy = -r; 1454 int dy0 = dy; 1455 int dx0 = dx; 1456 int x = xc1 >> line_subpixel_shift; 1457 int y = yc1 >> line_subpixel_shift; 1458 1459 do 1460 { 1461 dx += ei.dx(); 1462 dy += ei.dy(); 1463 1464 if(dy != dy0) 1465 { 1466 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); 1467 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0); 1468 } 1469 dx0 = dx; 1470 dy0 = dy; 1471 ++ei; 1472 } 1473 while(dy < 0); 1474 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); 1475 } 1476 1477 //------------------------------------------------------------------------- 1478 void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2, 1479 int xh1, int yh1, int xh2) 1480 { 1481 if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return; 1482 1483 cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; 1484 cover_type* p0 = covers; 1485 cover_type* p1 = covers; 1486 int x = xh1 << line_subpixel_shift; 1487 int y = yh1 << line_subpixel_shift; 1488 int w = subpixel_width(); 1489 1490 distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y); 1491 x += line_subpixel_scale/2; 1492 y += line_subpixel_scale/2; 1493 1494 int xh0 = xh1; 1495 int dx = x - xc; 1496 int dy = y - yc; 1497 do 1498 { 1499 int d = int(fast_sqrt(dx*dx + dy*dy)); 1500 *p1 = 0; 1501 if(di.dist1() <= 0 && di.dist2() > 0 && d <= w) 1502 { 1503 *p1 = (cover_type)cover(d); 1504 } 1505 ++p1; 1506 dx += line_subpixel_scale; 1507 di.inc_x(); 1508 } 1509 while(++xh1 <= xh2); 1510 m_ren->blend_solid_hspan(xh0, yh1, 1511 unsigned(p1 - p0), 1512 color(), 1513 p0); 1514 } 1515 1516 1517 //------------------------------------------------------------------------- 1518 void pie(int xc, int yc, int x1, int y1, int x2, int y2) 1519 { 1520 int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); 1521 if(r < 1) r = 1; 1522 ellipse_bresenham_interpolator ei(r, r); 1523 int dx = 0; 1524 int dy = -r; 1525 int dy0 = dy; 1526 int dx0 = dx; 1527 int x = xc >> line_subpixel_shift; 1528 int y = yc >> line_subpixel_shift; 1529 1530 do 1531 { 1532 dx += ei.dx(); 1533 dy += ei.dy(); 1534 1535 if(dy != dy0) 1536 { 1537 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); 1538 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0); 1539 } 1540 dx0 = dx; 1541 dy0 = dy; 1542 ++ei; 1543 } 1544 while(dy < 0); 1545 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); 1546 } 1547 1548 //------------------------------------------------------------------------- 1549 void line0_no_clip(const line_parameters& lp) 1550 { 1551 if(lp.len > line_max_length) 1552 { 1553 line_parameters lp1, lp2; 1554 lp.divide(lp1, lp2); 1555 line0_no_clip(lp1); 1556 line0_no_clip(lp2); 1557 return; 1558 } 1559 1560 line_interpolator_aa0<self_type> li(*this, lp); 1561 if(li.count()) 1562 { 1563 if(li.vertical()) 1564 { 1565 while(li.step_ver()); 1566 } 1567 else 1568 { 1569 while(li.step_hor()); 1570 } 1571 } 1572 } 1573 1574 //------------------------------------------------------------------------- 1575 void line0(const line_parameters& lp) 1576 { 1577 if(m_clipping) 1578 { 1579 int x1 = lp.x1; 1580 int y1 = lp.y1; 1581 int x2 = lp.x2; 1582 int y2 = lp.y2; 1583 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 1584 if((flags & 4) == 0) 1585 { 1586 if(flags) 1587 { 1588 line_parameters lp2(x1, y1, x2, y2, 1589 uround(calc_distance(x1, y1, x2, y2))); 1590 line0_no_clip(lp2); 1591 } 1592 else 1593 { 1594 line0_no_clip(lp); 1595 } 1596 } 1597 } 1598 else 1599 { 1600 line0_no_clip(lp); 1601 } 1602 } 1603 1604 //------------------------------------------------------------------------- 1605 void line1_no_clip(const line_parameters& lp, int sx, int sy) 1606 { 1607 if(lp.len > line_max_length) 1608 { 1609 line_parameters lp1, lp2; 1610 lp.divide(lp1, lp2); 1611 line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1); 1612 line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); 1613 return; 1614 } 1615 1616 fix_degenerate_bisectrix_start(lp, &sx, &sy); 1617 line_interpolator_aa1<self_type> li(*this, lp, sx, sy); 1618 if(li.vertical()) 1619 { 1620 while(li.step_ver()); 1621 } 1622 else 1623 { 1624 while(li.step_hor()); 1625 } 1626 } 1627 1628 1629 //------------------------------------------------------------------------- 1630 void line1(const line_parameters& lp, int sx, int sy) 1631 { 1632 if(m_clipping) 1633 { 1634 int x1 = lp.x1; 1635 int y1 = lp.y1; 1636 int x2 = lp.x2; 1637 int y2 = lp.y2; 1638 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 1639 if((flags & 4) == 0) 1640 { 1641 if(flags) 1642 { 1643 line_parameters lp2(x1, y1, x2, y2, 1644 uround(calc_distance(x1, y1, x2, y2))); 1645 if(flags & 1) 1646 { 1647 sx = x1 + (y2 - y1); 1648 sy = y1 - (x2 - x1); 1649 } 1650 else 1651 { 1652 while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) 1653 { 1654 sx = (lp.x1 + sx) >> 1; 1655 sy = (lp.y1 + sy) >> 1; 1656 } 1657 } 1658 line1_no_clip(lp2, sx, sy); 1659 } 1660 else 1661 { 1662 line1_no_clip(lp, sx, sy); 1663 } 1664 } 1665 } 1666 else 1667 { 1668 line1_no_clip(lp, sx, sy); 1669 } 1670 } 1671 1672 //------------------------------------------------------------------------- 1673 void line2_no_clip(const line_parameters& lp, int ex, int ey) 1674 { 1675 if(lp.len > line_max_length) 1676 { 1677 line_parameters lp1, lp2; 1678 lp.divide(lp1, lp2); 1679 line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); 1680 line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); 1681 return; 1682 } 1683 1684 fix_degenerate_bisectrix_end(lp, &ex, &ey); 1685 line_interpolator_aa2<self_type> li(*this, lp, ex, ey); 1686 if(li.vertical()) 1687 { 1688 while(li.step_ver()); 1689 } 1690 else 1691 { 1692 while(li.step_hor()); 1693 } 1694 } 1695 1696 //------------------------------------------------------------------------- 1697 void line2(const line_parameters& lp, int ex, int ey) 1698 { 1699 if(m_clipping) 1700 { 1701 int x1 = lp.x1; 1702 int y1 = lp.y1; 1703 int x2 = lp.x2; 1704 int y2 = lp.y2; 1705 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 1706 if((flags & 4) == 0) 1707 { 1708 if(flags) 1709 { 1710 line_parameters lp2(x1, y1, x2, y2, 1711 uround(calc_distance(x1, y1, x2, y2))); 1712 if(flags & 2) 1713 { 1714 ex = x2 + (y2 - y1); 1715 ey = y2 - (x2 - x1); 1716 } 1717 else 1718 { 1719 while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) 1720 { 1721 ex = (lp.x2 + ex) >> 1; 1722 ey = (lp.y2 + ey) >> 1; 1723 } 1724 } 1725 line2_no_clip(lp2, ex, ey); 1726 } 1727 else 1728 { 1729 line2_no_clip(lp, ex, ey); 1730 } 1731 } 1732 } 1733 else 1734 { 1735 line2_no_clip(lp, ex, ey); 1736 } 1737 } 1738 1739 //------------------------------------------------------------------------- 1740 void line3_no_clip(const line_parameters& lp, 1741 int sx, int sy, int ex, int ey) 1742 { 1743 if(lp.len > line_max_length) 1744 { 1745 line_parameters lp1, lp2; 1746 lp.divide(lp1, lp2); 1747 int mx = lp1.x2 + (lp1.y2 - lp1.y1); 1748 int my = lp1.y2 - (lp1.x2 - lp1.x1); 1749 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); 1750 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); 1751 return; 1752 } 1753 1754 fix_degenerate_bisectrix_start(lp, &sx, &sy); 1755 fix_degenerate_bisectrix_end(lp, &ex, &ey); 1756 line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey); 1757 if(li.vertical()) 1758 { 1759 while(li.step_ver()); 1760 } 1761 else 1762 { 1763 while(li.step_hor()); 1764 } 1765 } 1766 1767 //------------------------------------------------------------------------- 1768 void line3(const line_parameters& lp, 1769 int sx, int sy, int ex, int ey) 1770 { 1771 if(m_clipping) 1772 { 1773 int x1 = lp.x1; 1774 int y1 = lp.y1; 1775 int x2 = lp.x2; 1776 int y2 = lp.y2; 1777 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 1778 if((flags & 4) == 0) 1779 { 1780 if(flags) 1781 { 1782 line_parameters lp2(x1, y1, x2, y2, 1783 uround(calc_distance(x1, y1, x2, y2))); 1784 if(flags & 1) 1785 { 1786 sx = x1 + (y2 - y1); 1787 sy = y1 - (x2 - x1); 1788 } 1789 else 1790 { 1791 while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) 1792 { 1793 sx = (lp.x1 + sx) >> 1; 1794 sy = (lp.y1 + sy) >> 1; 1795 } 1796 } 1797 if(flags & 2) 1798 { 1799 ex = x2 + (y2 - y1); 1800 ey = y2 - (x2 - x1); 1801 } 1802 else 1803 { 1804 while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) 1805 { 1806 ex = (lp.x2 + ex) >> 1; 1807 ey = (lp.y2 + ey) >> 1; 1808 } 1809 } 1810 line3_no_clip(lp2, sx, sy, ex, ey); 1811 } 1812 else 1813 { 1814 line3_no_clip(lp, sx, sy, ex, ey); 1815 } 1816 } 1817 } 1818 else 1819 { 1820 line3_no_clip(lp, sx, sy, ex, ey); 1821 } 1822 } 1823 1824 1825 private: 1826 base_ren_type* m_ren; 1827 const line_profile_aa* m_profile; 1828 color_type m_color; 1829 rect_i m_clip_box; 1830 bool m_clipping; 1831 }; 1832 1833 1834 1835 } 1836 1837 #endif 1838