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