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 #ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED 16 #define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED 17 18 #include <math.h> 19 #include "agg_line_aa_basics.h" 20 #include "agg_dda_line.h" 21 #include "agg_rendering_buffer.h" 22 23 24 namespace agg 25 { 26 //========================================================line_image_scale 27 template<class Source> class line_image_scale 28 { 29 public: 30 typedef typename Source::color_type color_type; 31 32 line_image_scale(const Source& src, double height) : 33 m_source(src), 34 m_height(height), 35 m_scale(src.height() / height) 36 { 37 } 38 39 double width() const { return m_source.width(); } 40 double height() const { return m_height; } 41 42 color_type pixel(int x, int y) const 43 { 44 //double src_y = (y + 0.5) * m_scale - 0.5; 45 double src_y = y * m_scale; 46 int h = int(m_source.height()) - 1; 47 int y1 = int(floor(src_y)); 48 int y2 = y1 + 1; 49 color_type pix1 = (y1 < 0) ? m_source.pixel(x, 0).transparent() : m_source.pixel(x, y1); 50 color_type pix2 = (y2 > h) ? m_source.pixel(x, h).transparent() : m_source.pixel(x, y2); 51 return pix1.gradient(pix2, src_y - y1); 52 } 53 54 private: 55 line_image_scale(const line_image_scale<Source>&); 56 const line_image_scale<Source>& operator = (const line_image_scale<Source>&); 57 58 const Source& m_source; 59 double m_height; 60 double m_scale; 61 }; 62 63 64 65 //======================================================line_image_pattern 66 template<class Filter> class line_image_pattern 67 { 68 public: 69 typedef Filter filter_type; 70 typedef typename filter_type::color_type color_type; 71 72 //-------------------------------------------------------------------- 73 ~line_image_pattern() 74 { 75 delete [] m_data; 76 } 77 78 //-------------------------------------------------------------------- 79 line_image_pattern(const Filter& filter) : 80 m_filter(&filter), 81 m_dilation(filter.dilation() + 1), 82 m_dilation_hr(m_dilation << line_subpixel_shift), 83 m_data(0), 84 m_width(0), 85 m_height(0), 86 m_width_hr(0), 87 m_half_height_hr(0), 88 m_offset_y_hr(0) 89 { 90 } 91 92 // Create 93 //-------------------------------------------------------------------- 94 template<class Source> 95 line_image_pattern(const Filter& filter, const Source& src) : 96 m_filter(&filter), 97 m_dilation(filter.dilation() + 1), 98 m_dilation_hr(m_dilation << line_subpixel_shift), 99 m_data(0), 100 m_width(0), 101 m_height(0), 102 m_width_hr(0), 103 m_half_height_hr(0), 104 m_offset_y_hr(0) 105 { 106 create(src); 107 } 108 109 // Create 110 //-------------------------------------------------------------------- 111 template<class Source> void create(const Source& src) 112 { 113 m_height = unsigned(ceil((double)src.height())); 114 m_width = unsigned(ceil((double)src.width())); 115 m_width_hr = int(src.width() * line_subpixel_size); 116 m_half_height_hr = int(src.height() * line_subpixel_size/2); 117 m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_size/2; 118 m_half_height_hr += line_subpixel_size/2; 119 120 delete [] m_data; 121 m_data = new color_type [(m_width + m_dilation * 2) * (m_height + m_dilation * 2)]; 122 123 m_buf.attach(m_data, m_width + m_dilation * 2, 124 m_height + m_dilation * 2, 125 m_width + m_dilation * 2); 126 unsigned x, y; 127 color_type* d1; 128 color_type* d2; 129 for(y = 0; y < m_height; y++) 130 { 131 d1 = m_buf.row(y + m_dilation) + m_dilation; 132 for(x = 0; x < m_width; x++) 133 { 134 *d1++ = src.pixel(x, y); 135 } 136 } 137 138 const color_type* s1; 139 const color_type* s2; 140 for(y = 0; y < m_dilation; y++) 141 { 142 s1 = m_buf.row(m_height + m_dilation - 1) + m_dilation; 143 s2 = m_buf.row(m_dilation) + m_dilation; 144 d1 = m_buf.row(m_dilation + m_height + y) + m_dilation; 145 d2 = m_buf.row(m_dilation - y - 1) + m_dilation; 146 for(x = 0; x < m_width; x++) 147 { 148 *d1++ = color_type(*s1++, 0); 149 *d2++ = color_type(*s2++, 0); 150 } 151 } 152 153 unsigned h = m_height + m_dilation * 2; 154 for(y = 0; y < h; y++) 155 { 156 s1 = m_buf.row(y) + m_dilation; 157 s2 = m_buf.row(y) + m_dilation + m_width; 158 d1 = m_buf.row(y) + m_dilation + m_width; 159 d2 = m_buf.row(y) + m_dilation; 160 161 for(x = 0; x < m_dilation; x++) 162 { 163 *d1++ = *s1++; 164 *--d2 = *--s2; 165 } 166 } 167 } 168 169 //-------------------------------------------------------------------- 170 int pattern_width() const { return m_width_hr; } 171 int line_width() const { return m_half_height_hr; } 172 173 //-------------------------------------------------------------------- 174 void pixel(color_type* p, int x, int y) const 175 { 176 m_filter->pixel_high_res(m_buf.rows(), 177 p, 178 x % m_width_hr + m_dilation_hr, 179 y + m_offset_y_hr); 180 } 181 182 //-------------------------------------------------------------------- 183 const filter_type& filter() const { return *m_filter; } 184 185 private: 186 line_image_pattern(const line_image_pattern<filter_type>&); 187 const line_image_pattern<filter_type>& 188 operator = (const line_image_pattern<filter_type>&); 189 190 protected: 191 row_ptr_cache<color_type> m_buf; 192 const filter_type* m_filter; 193 unsigned m_dilation; 194 int m_dilation_hr; 195 color_type* m_data; 196 unsigned m_width; 197 unsigned m_height; 198 int m_width_hr; 199 int m_half_height_hr; 200 int m_offset_y_hr; 201 }; 202 203 204 205 206 207 208 //=================================================line_image_pattern_pow2 209 template<class Filter> class line_image_pattern_pow2 : 210 public line_image_pattern<Filter> 211 { 212 public: 213 typedef Filter filter_type; 214 typedef typename filter_type::color_type color_type; 215 typedef line_image_pattern<Filter> base_type; 216 217 //-------------------------------------------------------------------- 218 line_image_pattern_pow2(const Filter& filter) : 219 line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {} 220 221 //-------------------------------------------------------------------- 222 template<class Source> 223 line_image_pattern_pow2(const Filter& filter, const Source& src) : 224 line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) 225 { 226 create(src); 227 } 228 229 //-------------------------------------------------------------------- 230 template<class Source> void create(const Source& src) 231 { 232 line_image_pattern<Filter>::create(src); 233 m_mask = 1; 234 while(m_mask < base_type::m_width) 235 { 236 m_mask <<= 1; 237 m_mask |= 1; 238 } 239 m_mask <<= line_subpixel_shift - 1; 240 m_mask |= line_subpixel_mask; 241 base_type::m_width_hr = m_mask + 1; 242 } 243 244 //-------------------------------------------------------------------- 245 void pixel(color_type* p, int x, int y) const 246 { 247 base_type::m_filter->pixel_high_res( 248 base_type::m_buf.rows(), 249 p, 250 (x & m_mask) + base_type::m_dilation_hr, 251 y + base_type::m_offset_y_hr); 252 } 253 private: 254 unsigned m_mask; 255 }; 256 257 258 259 260 261 262 263 //===================================================distance_interpolator4 264 class distance_interpolator4 265 { 266 public: 267 //--------------------------------------------------------------------- 268 distance_interpolator4() {} 269 distance_interpolator4(int x1, int y1, int x2, int y2, 270 int sx, int sy, int ex, int ey, 271 int len, double scale, int x, int y) : 272 m_dx(x2 - x1), 273 m_dy(y2 - y1), 274 m_dx_start(line_mr(sx) - line_mr(x1)), 275 m_dy_start(line_mr(sy) - line_mr(y1)), 276 m_dx_end(line_mr(ex) - line_mr(x2)), 277 m_dy_end(line_mr(ey) - line_mr(y2)), 278 279 m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - 280 double(y + line_subpixel_size/2 - y2) * double(m_dx))), 281 282 m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start - 283 (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start), 284 285 m_dist_end((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_end - 286 (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_end), 287 m_len(int(len / scale)) 288 { 289 double d = len * scale; 290 int dx = int(((x2 - x1) << line_subpixel_shift) / d); 291 int dy = int(((y2 - y1) << line_subpixel_shift) / d); 292 m_dx_pict = -dy; 293 m_dy_pict = dx; 294 m_dist_pict = ((x + line_subpixel_size/2 - (x1 - dy)) * m_dy_pict - 295 (y + line_subpixel_size/2 - (y1 + dx)) * m_dx_pict) >> 296 line_subpixel_shift; 297 298 m_dx <<= line_subpixel_shift; 299 m_dy <<= line_subpixel_shift; 300 m_dx_start <<= line_mr_subpixel_shift; 301 m_dy_start <<= line_mr_subpixel_shift; 302 m_dx_end <<= line_mr_subpixel_shift; 303 m_dy_end <<= line_mr_subpixel_shift; 304 } 305 306 //--------------------------------------------------------------------- 307 void inc_x() 308 { 309 m_dist += m_dy; 310 m_dist_start += m_dy_start; 311 m_dist_pict += m_dy_pict; 312 m_dist_end += m_dy_end; 313 } 314 315 //--------------------------------------------------------------------- 316 void dec_x() 317 { 318 m_dist -= m_dy; 319 m_dist_start -= m_dy_start; 320 m_dist_pict -= m_dy_pict; 321 m_dist_end -= m_dy_end; 322 } 323 324 //--------------------------------------------------------------------- 325 void inc_y() 326 { 327 m_dist -= m_dx; 328 m_dist_start -= m_dx_start; 329 m_dist_pict -= m_dx_pict; 330 m_dist_end -= m_dx_end; 331 } 332 333 //--------------------------------------------------------------------- 334 void dec_y() 335 { 336 m_dist += m_dx; 337 m_dist_start += m_dx_start; 338 m_dist_pict += m_dx_pict; 339 m_dist_end += m_dx_end; 340 } 341 342 //--------------------------------------------------------------------- 343 void inc_x(int dy) 344 { 345 m_dist += m_dy; 346 m_dist_start += m_dy_start; 347 m_dist_pict += m_dy_pict; 348 m_dist_end += m_dy_end; 349 if(dy > 0) 350 { 351 m_dist -= m_dx; 352 m_dist_start -= m_dx_start; 353 m_dist_pict -= m_dx_pict; 354 m_dist_end -= m_dx_end; 355 } 356 if(dy < 0) 357 { 358 m_dist += m_dx; 359 m_dist_start += m_dx_start; 360 m_dist_pict += m_dx_pict; 361 m_dist_end += m_dx_end; 362 } 363 } 364 365 //--------------------------------------------------------------------- 366 void dec_x(int dy) 367 { 368 m_dist -= m_dy; 369 m_dist_start -= m_dy_start; 370 m_dist_pict -= m_dy_pict; 371 m_dist_end -= m_dy_end; 372 if(dy > 0) 373 { 374 m_dist -= m_dx; 375 m_dist_start -= m_dx_start; 376 m_dist_pict -= m_dx_pict; 377 m_dist_end -= m_dx_end; 378 } 379 if(dy < 0) 380 { 381 m_dist += m_dx; 382 m_dist_start += m_dx_start; 383 m_dist_pict += m_dx_pict; 384 m_dist_end += m_dx_end; 385 } 386 } 387 388 //--------------------------------------------------------------------- 389 void inc_y(int dx) 390 { 391 m_dist -= m_dx; 392 m_dist_start -= m_dx_start; 393 m_dist_pict -= m_dx_pict; 394 m_dist_end -= m_dx_end; 395 if(dx > 0) 396 { 397 m_dist += m_dy; 398 m_dist_start += m_dy_start; 399 m_dist_pict += m_dy_pict; 400 m_dist_end += m_dy_end; 401 } 402 if(dx < 0) 403 { 404 m_dist -= m_dy; 405 m_dist_start -= m_dy_start; 406 m_dist_pict -= m_dy_pict; 407 m_dist_end -= m_dy_end; 408 } 409 } 410 411 //--------------------------------------------------------------------- 412 void dec_y(int dx) 413 { 414 m_dist += m_dx; 415 m_dist_start += m_dx_start; 416 m_dist_pict += m_dx_pict; 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_pict += m_dy_pict; 423 m_dist_end += m_dy_end; 424 } 425 if(dx < 0) 426 { 427 m_dist -= m_dy; 428 m_dist_start -= m_dy_start; 429 m_dist_pict -= m_dy_pict; 430 m_dist_end -= m_dy_end; 431 } 432 } 433 434 //--------------------------------------------------------------------- 435 int dist() const { return m_dist; } 436 int dist_start() const { return m_dist_start; } 437 int dist_pict() const { return m_dist_pict; } 438 int dist_end() const { return m_dist_end; } 439 440 //--------------------------------------------------------------------- 441 int dx() const { return m_dx; } 442 int dy() const { return m_dy; } 443 int dx_start() const { return m_dx_start; } 444 int dy_start() const { return m_dy_start; } 445 int dx_pict() const { return m_dx_pict; } 446 int dy_pict() const { return m_dy_pict; } 447 int dx_end() const { return m_dx_end; } 448 int dy_end() const { return m_dy_end; } 449 int len() const { return m_len; } 450 451 private: 452 //--------------------------------------------------------------------- 453 int m_dx; 454 int m_dy; 455 int m_dx_start; 456 int m_dy_start; 457 int m_dx_pict; 458 int m_dy_pict; 459 int m_dx_end; 460 int m_dy_end; 461 462 int m_dist; 463 int m_dist_start; 464 int m_dist_pict; 465 int m_dist_end; 466 int m_len; 467 }; 468 469 470 471 472 473 //==================================================line_interpolator_image 474 template<class Renderer> class line_interpolator_image 475 { 476 public: 477 typedef Renderer renderer_type; 478 typedef typename Renderer::color_type color_type; 479 480 //--------------------------------------------------------------------- 481 enum 482 { 483 max_half_width = 64 484 }; 485 486 //--------------------------------------------------------------------- 487 line_interpolator_image(renderer_type& ren, const line_parameters& lp, 488 int sx, int sy, int ex, int ey, 489 int pattern_start, 490 double scale_x) : 491 m_lp(lp), 492 m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : 493 line_dbl_hr(lp.y2 - lp.y1), 494 lp.vertical ? abs(lp.y2 - lp.y1) : 495 abs(lp.x2 - lp.x1) + 1), 496 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x, 497 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask), 498 m_ren(ren), 499 m_x(lp.x1 >> line_subpixel_shift), 500 m_y(lp.y1 >> line_subpixel_shift), 501 m_old_x(m_x), 502 m_old_y(m_y), 503 m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : 504 abs((lp.x2 >> line_subpixel_shift) - m_x))), 505 m_width(ren.subpixel_width()), 506 m_max_extent(m_width >> (line_subpixel_shift - 2)), 507 m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()), 508 m_step(0) 509 { 510 agg::dda2_line_interpolator li(0, lp.vertical ? 511 (lp.dy << agg::line_subpixel_shift) : 512 (lp.dx << agg::line_subpixel_shift), 513 lp.len); 514 515 unsigned i; 516 int stop = m_width + line_subpixel_size * 2; 517 for(i = 0; i < max_half_width; ++i) 518 { 519 m_dist_pos[i] = li.y(); 520 if(m_dist_pos[i] >= stop) break; 521 ++li; 522 } 523 m_dist_pos[i] = 0x7FFF0000; 524 525 int dist1_start; 526 int dist2_start; 527 int npix = 1; 528 529 if(lp.vertical) 530 { 531 do 532 { 533 --m_li; 534 m_y -= lp.inc; 535 m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; 536 537 if(lp.inc > 0) m_di.dec_y(m_x - m_old_x); 538 else m_di.inc_y(m_x - m_old_x); 539 540 m_old_x = m_x; 541 542 dist1_start = dist2_start = m_di.dist_start(); 543 544 int dx = 0; 545 if(dist1_start < 0) ++npix; 546 do 547 { 548 dist1_start += m_di.dy_start(); 549 dist2_start -= m_di.dy_start(); 550 if(dist1_start < 0) ++npix; 551 if(dist2_start < 0) ++npix; 552 ++dx; 553 } 554 while(m_dist_pos[dx] <= m_width); 555 if(npix == 0) break; 556 557 npix = 0; 558 } 559 while(--m_step >= -m_max_extent); 560 } 561 else 562 { 563 do 564 { 565 --m_li; 566 567 m_x -= lp.inc; 568 m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; 569 570 if(lp.inc > 0) m_di.dec_x(m_y - m_old_y); 571 else m_di.inc_x(m_y - m_old_y); 572 573 m_old_y = m_y; 574 575 dist1_start = dist2_start = m_di.dist_start(); 576 577 int dy = 0; 578 if(dist1_start < 0) ++npix; 579 do 580 { 581 dist1_start -= m_di.dx_start(); 582 dist2_start += m_di.dx_start(); 583 if(dist1_start < 0) ++npix; 584 if(dist2_start < 0) ++npix; 585 ++dy; 586 } 587 while(m_dist_pos[dy] <= m_width); 588 if(npix == 0) break; 589 590 npix = 0; 591 } 592 while(--m_step >= -m_max_extent); 593 } 594 m_li.adjust_forward(); 595 m_step -= m_max_extent; 596 } 597 598 //--------------------------------------------------------------------- 599 bool step_hor() 600 { 601 ++m_li; 602 m_x += m_lp.inc; 603 m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; 604 605 if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y); 606 else m_di.dec_x(m_y - m_old_y); 607 608 m_old_y = m_y; 609 610 int s1 = m_di.dist() / m_lp.len; 611 int s2 = -s1; 612 613 if(m_lp.inc < 0) s1 = -s1; 614 615 int dist_start; 616 int dist_pict; 617 int dist_end; 618 int dy; 619 int dist; 620 621 dist_start = m_di.dist_start(); 622 dist_pict = m_di.dist_pict() + m_start; 623 dist_end = m_di.dist_end(); 624 color_type* p0 = m_colors + max_half_width + 2; 625 color_type* p1 = p0; 626 627 int npix = 0; 628 p1->clear(); 629 if(dist_end > 0) 630 { 631 if(dist_start <= 0) 632 { 633 m_ren.pixel(p1, dist_pict, s2); 634 } 635 ++npix; 636 } 637 ++p1; 638 639 dy = 1; 640 while((dist = m_dist_pos[dy]) - s1 <= m_width) 641 { 642 dist_start -= m_di.dx_start(); 643 dist_pict -= m_di.dx_pict(); 644 dist_end -= m_di.dx_end(); 645 p1->clear(); 646 if(dist_end > 0 && dist_start <= 0) 647 { 648 if(m_lp.inc > 0) dist = -dist; 649 m_ren.pixel(p1, dist_pict, s2 - dist); 650 ++npix; 651 } 652 ++p1; 653 ++dy; 654 } 655 656 dy = 1; 657 dist_start = m_di.dist_start(); 658 dist_pict = m_di.dist_pict() + m_start; 659 dist_end = m_di.dist_end(); 660 while((dist = m_dist_pos[dy]) + s1 <= m_width) 661 { 662 dist_start += m_di.dx_start(); 663 dist_pict += m_di.dx_pict(); 664 dist_end += m_di.dx_end(); 665 --p0; 666 p0->clear(); 667 if(dist_end > 0 && dist_start <= 0) 668 { 669 if(m_lp.inc > 0) dist = -dist; 670 m_ren.pixel(p0, dist_pict, s2 + dist); 671 ++npix; 672 } 673 ++dy; 674 } 675 m_ren.blend_color_vspan(m_x, 676 m_y - dy + 1, 677 unsigned(p1 - p0), 678 p0); 679 return npix && ++m_step < m_count; 680 } 681 682 683 684 //--------------------------------------------------------------------- 685 bool step_ver() 686 { 687 ++m_li; 688 m_y += m_lp.inc; 689 m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; 690 691 if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x); 692 else m_di.dec_y(m_x - m_old_x); 693 694 m_old_x = m_x; 695 696 int s1 = m_di.dist() / m_lp.len; 697 int s2 = -s1; 698 699 if(m_lp.inc > 0) s1 = -s1; 700 701 int dist_start; 702 int dist_pict; 703 int dist_end; 704 int dist; 705 int dx; 706 707 dist_start = m_di.dist_start(); 708 dist_pict = m_di.dist_pict() + m_start; 709 dist_end = m_di.dist_end(); 710 color_type* p0 = m_colors + max_half_width + 2; 711 color_type* p1 = p0; 712 713 int npix = 0; 714 p1->clear(); 715 if(dist_end > 0) 716 { 717 if(dist_start <= 0) 718 { 719 m_ren.pixel(p1, dist_pict, s2); 720 } 721 ++npix; 722 } 723 ++p1; 724 725 dx = 1; 726 while((dist = m_dist_pos[dx]) - s1 <= m_width) 727 { 728 dist_start += m_di.dy_start(); 729 dist_pict += m_di.dy_pict(); 730 dist_end += m_di.dy_end(); 731 p1->clear(); 732 if(dist_end > 0 && dist_start <= 0) 733 { 734 if(m_lp.inc > 0) dist = -dist; 735 m_ren.pixel(p1, dist_pict, s2 + dist); 736 ++npix; 737 } 738 ++p1; 739 ++dx; 740 } 741 742 dx = 1; 743 dist_start = m_di.dist_start(); 744 dist_pict = m_di.dist_pict() + m_start; 745 dist_end = m_di.dist_end(); 746 while((dist = m_dist_pos[dx]) + s1 <= m_width) 747 { 748 dist_start -= m_di.dy_start(); 749 dist_pict -= m_di.dy_pict(); 750 dist_end -= m_di.dy_end(); 751 --p0; 752 p0->clear(); 753 if(dist_end > 0 && dist_start <= 0) 754 { 755 if(m_lp.inc > 0) dist = -dist; 756 m_ren.pixel(p0, dist_pict, s2 - dist); 757 ++npix; 758 } 759 ++dx; 760 } 761 m_ren.blend_color_hspan(m_x - dx + 1, 762 m_y, 763 unsigned(p1 - p0), 764 p0); 765 return npix && ++m_step < m_count; 766 } 767 768 769 //--------------------------------------------------------------------- 770 int pattern_end() const { return m_start + m_di.len(); } 771 772 //--------------------------------------------------------------------- 773 bool vertical() const { return m_lp.vertical; } 774 int width() const { return m_width; } 775 int count() const { return m_count; } 776 777 private: 778 line_interpolator_image(const line_interpolator_image<Renderer>&); 779 const line_interpolator_image<Renderer>& 780 operator = (const line_interpolator_image<Renderer>&); 781 782 protected: 783 const line_parameters& m_lp; 784 dda2_line_interpolator m_li; 785 distance_interpolator4 m_di; 786 renderer_type& m_ren; 787 int m_plen; 788 int m_x; 789 int m_y; 790 int m_old_x; 791 int m_old_y; 792 int m_count; 793 int m_width; 794 int m_max_extent; 795 int m_start; 796 int m_step; 797 int m_dist_pos[max_half_width + 1]; 798 color_type m_colors[max_half_width * 2 + 4]; 799 }; 800 801 802 803 804 805 806 807 808 //===================================================renderer_outline_image 809 template<class BaseRenderer, class ImagePattern> 810 class renderer_outline_image 811 { 812 public: 813 //--------------------------------------------------------------------- 814 typedef BaseRenderer base_ren_type; 815 typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type; 816 typedef typename base_ren_type::color_type color_type; 817 typedef ImagePattern pattern_type; 818 819 820 //--------------------------------------------------------------------- 821 renderer_outline_image(base_ren_type& ren, const pattern_type& patt) : 822 m_ren(&ren), 823 m_pattern(&patt), 824 m_start(0), 825 m_scale_x(1.0) 826 { 827 } 828 829 //--------------------------------------------------------------------- 830 void pattern(const pattern_type& p) { m_pattern = &p; } 831 const pattern_type& pattern() const { return *m_pattern; } 832 833 //--------------------------------------------------------------------- 834 void scale_x(double s) { m_scale_x = s; } 835 double scale_x() const { return m_scale_x; } 836 837 //--------------------------------------------------------------------- 838 void start_x(double s) { m_start = int(s * line_subpixel_size); } 839 double start_x() const { return double(m_start) / line_subpixel_size; } 840 841 //--------------------------------------------------------------------- 842 int subpixel_width() const { return m_pattern->line_width(); } 843 int pattern_width() const { return m_pattern->pattern_width(); } 844 845 //------------------------------------------------------------------------- 846 void pixel(color_type* p, int x, int y) const 847 { 848 m_pattern->pixel(p, x, y); 849 } 850 851 //------------------------------------------------------------------------- 852 void blend_color_hspan(int x, int y, unsigned len, const color_type* colors) 853 { 854 m_ren->blend_color_hspan(x, y, len, colors, 0); 855 } 856 857 //------------------------------------------------------------------------- 858 void blend_color_vspan(int x, int y, unsigned len, const color_type* colors) 859 { 860 m_ren->blend_color_vspan(x, y, len, colors, 0); 861 } 862 863 //------------------------------------------------------------------------- 864 static bool accurate_join_only() { return true; } 865 866 //------------------------------------------------------------------------- 867 template<class Cmp> 868 void semidot(Cmp, int, int, int, int) 869 { 870 } 871 872 //------------------------------------------------------------------------- 873 void line0(const line_parameters&) 874 { 875 } 876 877 //------------------------------------------------------------------------- 878 void line1(const line_parameters&, int, int) 879 { 880 } 881 882 //------------------------------------------------------------------------- 883 void line2(const line_parameters&, int, int) 884 { 885 } 886 887 //------------------------------------------------------------------------- 888 void line3(const line_parameters& lp, 889 int sx, int sy, int ex, int ey) 890 { 891 line_interpolator_image<self_type> li(*this, lp, 892 sx, sy, 893 ex, ey, 894 m_start, m_scale_x); 895 if(li.vertical()) 896 { 897 while(li.step_ver()); 898 } 899 else 900 { 901 while(li.step_hor()); 902 } 903 m_start = li.pattern_end(); 904 } 905 906 private: 907 base_ren_type* m_ren; 908 const pattern_type* m_pattern; 909 int m_start; 910 double m_scale_x; 911 }; 912 913 914 915 916 917 } 918 919 920 921 #endif 922