Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 00025 #ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED 00026 #define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED 00027 00028 #include "agg_array.h" 00029 #include "agg_math.h" 00030 #include "agg_line_aa_basics.h" 00031 #include "agg_dda_line.h" 00032 #include "agg_rendering_buffer.h" 00033 #include "agg_clip_liang_barsky.h" 00034 00035 00036 namespace agg 00037 { 00038 //========================================================line_image_scale 00039 template<class Source> class line_image_scale 00040 { 00041 public: 00042 typedef typename Source::color_type color_type; 00043 00044 line_image_scale(const Source& src, double height) : 00045 m_source(src), 00046 m_height(height), 00047 m_scale(src.height() / height) 00048 { 00049 } 00050 00051 double width() const { return m_source.width(); } 00052 double height() const { return m_height; } 00053 00054 color_type pixel(int x, int y) const 00055 { 00056 double src_y = (y + 0.5) * m_scale - 0.5; 00057 int h = m_source.height() - 1; 00058 int y1 = ufloor(src_y); 00059 int y2 = y1 + 1; 00060 color_type pix1 = (y1 < 0) ? color_type::no_color() : m_source.pixel(x, y1); 00061 color_type pix2 = (y2 > h) ? color_type::no_color() : m_source.pixel(x, y2); 00062 return pix1.gradient(pix2, src_y - y1); 00063 } 00064 00065 private: 00066 line_image_scale(const line_image_scale<Source>&); 00067 const line_image_scale<Source>& operator = (const line_image_scale<Source>&); 00068 00069 const Source& m_source; 00070 double m_height; 00071 double m_scale; 00072 }; 00073 00074 00075 00076 //======================================================line_image_pattern 00077 template<class Filter> class line_image_pattern 00078 { 00079 public: 00080 typedef Filter filter_type; 00081 typedef typename filter_type::color_type color_type; 00082 00083 //-------------------------------------------------------------------- 00084 line_image_pattern(const Filter& filter) : 00085 m_filter(&filter), 00086 m_dilation(filter.dilation() + 1), 00087 m_dilation_hr(m_dilation << line_subpixel_shift), 00088 m_data(), 00089 m_width(0), 00090 m_height(0), 00091 m_width_hr(0), 00092 m_half_height_hr(0), 00093 m_offset_y_hr(0) 00094 { 00095 } 00096 00097 // Create 00098 //-------------------------------------------------------------------- 00099 template<class Source> 00100 line_image_pattern(const Filter& filter, const Source& src) : 00101 m_filter(&filter), 00102 m_dilation(filter.dilation() + 1), 00103 m_dilation_hr(m_dilation << line_subpixel_shift), 00104 m_data(), 00105 m_width(0), 00106 m_height(0), 00107 m_width_hr(0), 00108 m_half_height_hr(0), 00109 m_offset_y_hr(0) 00110 { 00111 create(src); 00112 } 00113 00114 // Create 00115 //-------------------------------------------------------------------- 00116 template<class Source> void create(const Source& src) 00117 { 00118 m_height = uceil(src.height()); 00119 m_width = uceil(src.width()); 00120 m_width_hr = uround(src.width() * line_subpixel_scale); 00121 m_half_height_hr = uround(src.height() * line_subpixel_scale/2); 00122 m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2; 00123 m_half_height_hr += line_subpixel_scale/2; 00124 00125 m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2)); 00126 00127 m_buf.attach(&m_data[0], m_width + m_dilation * 2, 00128 m_height + m_dilation * 2, 00129 m_width + m_dilation * 2); 00130 unsigned x, y; 00131 color_type* d1; 00132 color_type* d2; 00133 for(y = 0; y < m_height; y++) 00134 { 00135 d1 = m_buf.row_ptr(y + m_dilation) + m_dilation; 00136 for(x = 0; x < m_width; x++) 00137 { 00138 *d1++ = src.pixel(x, y); 00139 } 00140 } 00141 00142 const color_type* s1; 00143 const color_type* s2; 00144 for(y = 0; y < m_dilation; y++) 00145 { 00146 //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation; 00147 //s2 = m_buf.row_ptr(m_dilation) + m_dilation; 00148 d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation; 00149 d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation; 00150 for(x = 0; x < m_width; x++) 00151 { 00152 //*d1++ = color_type(*s1++, 0); 00153 //*d2++ = color_type(*s2++, 0); 00154 *d1++ = color_type::no_color(); 00155 *d2++ = color_type::no_color(); 00156 } 00157 } 00158 00159 unsigned h = m_height + m_dilation * 2; 00160 for(y = 0; y < h; y++) 00161 { 00162 s1 = m_buf.row_ptr(y) + m_dilation; 00163 s2 = m_buf.row_ptr(y) + m_dilation + m_width; 00164 d1 = m_buf.row_ptr(y) + m_dilation + m_width; 00165 d2 = m_buf.row_ptr(y) + m_dilation; 00166 00167 for(x = 0; x < m_dilation; x++) 00168 { 00169 *d1++ = *s1++; 00170 *--d2 = *--s2; 00171 } 00172 } 00173 } 00174 00175 //-------------------------------------------------------------------- 00176 int pattern_width() const { return m_width_hr; } 00177 int line_width() const { return m_half_height_hr; } 00178 double width() const { return m_height; } 00179 00180 //-------------------------------------------------------------------- 00181 void pixel(color_type* p, int x, int y) const 00182 { 00183 m_filter->pixel_high_res(m_buf.rows(), 00184 p, 00185 x % m_width_hr + m_dilation_hr, 00186 y + m_offset_y_hr); 00187 } 00188 00189 //-------------------------------------------------------------------- 00190 const filter_type& filter() const { return *m_filter; } 00191 00192 private: 00193 line_image_pattern(const line_image_pattern<filter_type>&); 00194 const line_image_pattern<filter_type>& 00195 operator = (const line_image_pattern<filter_type>&); 00196 00197 protected: 00198 row_ptr_cache<color_type> m_buf; 00199 const filter_type* m_filter; 00200 unsigned m_dilation; 00201 int m_dilation_hr; 00202 pod_array<color_type> m_data; 00203 unsigned m_width; 00204 unsigned m_height; 00205 int m_width_hr; 00206 int m_half_height_hr; 00207 int m_offset_y_hr; 00208 }; 00209 00210 00211 00212 00213 00214 00215 //=================================================line_image_pattern_pow2 00216 template<class Filter> class line_image_pattern_pow2 : 00217 public line_image_pattern<Filter> 00218 { 00219 public: 00220 typedef Filter filter_type; 00221 typedef typename filter_type::color_type color_type; 00222 typedef line_image_pattern<Filter> base_type; 00223 00224 //-------------------------------------------------------------------- 00225 line_image_pattern_pow2(const Filter& filter) : 00226 line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {} 00227 00228 //-------------------------------------------------------------------- 00229 template<class Source> 00230 line_image_pattern_pow2(const Filter& filter, const Source& src) : 00231 line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) 00232 { 00233 create(src); 00234 } 00235 00236 //-------------------------------------------------------------------- 00237 template<class Source> void create(const Source& src) 00238 { 00239 line_image_pattern<Filter>::create(src); 00240 m_mask = 1; 00241 while(m_mask < base_type::m_width) 00242 { 00243 m_mask <<= 1; 00244 m_mask |= 1; 00245 } 00246 m_mask <<= line_subpixel_shift - 1; 00247 m_mask |= line_subpixel_mask; 00248 base_type::m_width_hr = m_mask + 1; 00249 } 00250 00251 //-------------------------------------------------------------------- 00252 void pixel(color_type* p, int x, int y) const 00253 { 00254 base_type::m_filter->pixel_high_res( 00255 base_type::m_buf.rows(), 00256 p, 00257 (x & m_mask) + base_type::m_dilation_hr, 00258 y + base_type::m_offset_y_hr); 00259 } 00260 private: 00261 unsigned m_mask; 00262 }; 00263 00264 00265 00266 00267 00268 00269 00270 //===================================================distance_interpolator4 00271 class distance_interpolator4 00272 { 00273 public: 00274 //--------------------------------------------------------------------- 00275 distance_interpolator4() {} 00276 distance_interpolator4(int x1, int y1, int x2, int y2, 00277 int sx, int sy, int ex, int ey, 00278 int len, double scale, int x, int y) : 00279 m_dx(x2 - x1), 00280 m_dy(y2 - y1), 00281 m_dx_start(line_mr(sx) - line_mr(x1)), 00282 m_dy_start(line_mr(sy) - line_mr(y1)), 00283 m_dx_end(line_mr(ex) - line_mr(x2)), 00284 m_dy_end(line_mr(ey) - line_mr(y2)), 00285 00286 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 00287 double(y + line_subpixel_scale/2 - y2) * double(m_dx))), 00288 00289 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - 00290 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), 00291 00292 m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - 00293 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end), 00294 m_len(uround(len / scale)) 00295 { 00296 double d = len * scale; 00297 int dx = iround(((x2 - x1) << line_subpixel_shift) / d); 00298 int dy = iround(((y2 - y1) << line_subpixel_shift) / d); 00299 m_dx_pict = -dy; 00300 m_dy_pict = dx; 00301 m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict - 00302 (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >> 00303 line_subpixel_shift; 00304 00305 m_dx <<= line_subpixel_shift; 00306 m_dy <<= line_subpixel_shift; 00307 m_dx_start <<= line_mr_subpixel_shift; 00308 m_dy_start <<= line_mr_subpixel_shift; 00309 m_dx_end <<= line_mr_subpixel_shift; 00310 m_dy_end <<= line_mr_subpixel_shift; 00311 } 00312 00313 //--------------------------------------------------------------------- 00314 void inc_x() 00315 { 00316 m_dist += m_dy; 00317 m_dist_start += m_dy_start; 00318 m_dist_pict += m_dy_pict; 00319 m_dist_end += m_dy_end; 00320 } 00321 00322 //--------------------------------------------------------------------- 00323 void dec_x() 00324 { 00325 m_dist -= m_dy; 00326 m_dist_start -= m_dy_start; 00327 m_dist_pict -= m_dy_pict; 00328 m_dist_end -= m_dy_end; 00329 } 00330 00331 //--------------------------------------------------------------------- 00332 void inc_y() 00333 { 00334 m_dist -= m_dx; 00335 m_dist_start -= m_dx_start; 00336 m_dist_pict -= m_dx_pict; 00337 m_dist_end -= m_dx_end; 00338 } 00339 00340 //--------------------------------------------------------------------- 00341 void dec_y() 00342 { 00343 m_dist += m_dx; 00344 m_dist_start += m_dx_start; 00345 m_dist_pict += m_dx_pict; 00346 m_dist_end += m_dx_end; 00347 } 00348 00349 //--------------------------------------------------------------------- 00350 void inc_x(int dy) 00351 { 00352 m_dist += m_dy; 00353 m_dist_start += m_dy_start; 00354 m_dist_pict += m_dy_pict; 00355 m_dist_end += m_dy_end; 00356 if(dy > 0) 00357 { 00358 m_dist -= m_dx; 00359 m_dist_start -= m_dx_start; 00360 m_dist_pict -= m_dx_pict; 00361 m_dist_end -= m_dx_end; 00362 } 00363 if(dy < 0) 00364 { 00365 m_dist += m_dx; 00366 m_dist_start += m_dx_start; 00367 m_dist_pict += m_dx_pict; 00368 m_dist_end += m_dx_end; 00369 } 00370 } 00371 00372 //--------------------------------------------------------------------- 00373 void dec_x(int dy) 00374 { 00375 m_dist -= m_dy; 00376 m_dist_start -= m_dy_start; 00377 m_dist_pict -= m_dy_pict; 00378 m_dist_end -= m_dy_end; 00379 if(dy > 0) 00380 { 00381 m_dist -= m_dx; 00382 m_dist_start -= m_dx_start; 00383 m_dist_pict -= m_dx_pict; 00384 m_dist_end -= m_dx_end; 00385 } 00386 if(dy < 0) 00387 { 00388 m_dist += m_dx; 00389 m_dist_start += m_dx_start; 00390 m_dist_pict += m_dx_pict; 00391 m_dist_end += m_dx_end; 00392 } 00393 } 00394 00395 //--------------------------------------------------------------------- 00396 void inc_y(int dx) 00397 { 00398 m_dist -= m_dx; 00399 m_dist_start -= m_dx_start; 00400 m_dist_pict -= m_dx_pict; 00401 m_dist_end -= m_dx_end; 00402 if(dx > 0) 00403 { 00404 m_dist += m_dy; 00405 m_dist_start += m_dy_start; 00406 m_dist_pict += m_dy_pict; 00407 m_dist_end += m_dy_end; 00408 } 00409 if(dx < 0) 00410 { 00411 m_dist -= m_dy; 00412 m_dist_start -= m_dy_start; 00413 m_dist_pict -= m_dy_pict; 00414 m_dist_end -= m_dy_end; 00415 } 00416 } 00417 00418 //--------------------------------------------------------------------- 00419 void dec_y(int dx) 00420 { 00421 m_dist += m_dx; 00422 m_dist_start += m_dx_start; 00423 m_dist_pict += m_dx_pict; 00424 m_dist_end += m_dx_end; 00425 if(dx > 0) 00426 { 00427 m_dist += m_dy; 00428 m_dist_start += m_dy_start; 00429 m_dist_pict += m_dy_pict; 00430 m_dist_end += m_dy_end; 00431 } 00432 if(dx < 0) 00433 { 00434 m_dist -= m_dy; 00435 m_dist_start -= m_dy_start; 00436 m_dist_pict -= m_dy_pict; 00437 m_dist_end -= m_dy_end; 00438 } 00439 } 00440 00441 //--------------------------------------------------------------------- 00442 int dist() const { return m_dist; } 00443 int dist_start() const { return m_dist_start; } 00444 int dist_pict() const { return m_dist_pict; } 00445 int dist_end() const { return m_dist_end; } 00446 00447 //--------------------------------------------------------------------- 00448 int dx() const { return m_dx; } 00449 int dy() const { return m_dy; } 00450 int dx_start() const { return m_dx_start; } 00451 int dy_start() const { return m_dy_start; } 00452 int dx_pict() const { return m_dx_pict; } 00453 int dy_pict() const { return m_dy_pict; } 00454 int dx_end() const { return m_dx_end; } 00455 int dy_end() const { return m_dy_end; } 00456 int len() const { return m_len; } 00457 00458 private: 00459 //--------------------------------------------------------------------- 00460 int m_dx; 00461 int m_dy; 00462 int m_dx_start; 00463 int m_dy_start; 00464 int m_dx_pict; 00465 int m_dy_pict; 00466 int m_dx_end; 00467 int m_dy_end; 00468 00469 int m_dist; 00470 int m_dist_start; 00471 int m_dist_pict; 00472 int m_dist_end; 00473 int m_len; 00474 }; 00475 00476 00477 00478 00479 00480 //==================================================line_interpolator_image 00481 template<class Renderer> class line_interpolator_image 00482 { 00483 public: 00484 typedef Renderer renderer_type; 00485 typedef typename Renderer::color_type color_type; 00486 00487 //--------------------------------------------------------------------- 00488 enum max_half_width_e 00489 { 00490 max_half_width = 64 00491 }; 00492 00493 //--------------------------------------------------------------------- 00494 line_interpolator_image(renderer_type& ren, const line_parameters& lp, 00495 int sx, int sy, int ex, int ey, 00496 int pattern_start, 00497 double scale_x) : 00498 m_lp(lp), 00499 m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : 00500 line_dbl_hr(lp.y2 - lp.y1), 00501 lp.vertical ? abs(lp.y2 - lp.y1) : 00502 abs(lp.x2 - lp.x1) + 1), 00503 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x, 00504 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask), 00505 m_ren(ren), 00506 m_x(lp.x1 >> line_subpixel_shift), 00507 m_y(lp.y1 >> line_subpixel_shift), 00508 m_old_x(m_x), 00509 m_old_y(m_y), 00510 m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : 00511 abs((lp.x2 >> line_subpixel_shift) - m_x))), 00512 m_width(ren.subpixel_width()), 00513 //m_max_extent(m_width >> (line_subpixel_shift - 2)), 00514 m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift), 00515 m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()), 00516 m_step(0) 00517 { 00518 agg::dda2_line_interpolator li(0, lp.vertical ? 00519 (lp.dy << agg::line_subpixel_shift) : 00520 (lp.dx << agg::line_subpixel_shift), 00521 lp.len); 00522 00523 unsigned i; 00524 int stop = m_width + line_subpixel_scale * 2; 00525 for(i = 0; i < max_half_width; ++i) 00526 { 00527 m_dist_pos[i] = li.y(); 00528 if(m_dist_pos[i] >= stop) break; 00529 ++li; 00530 } 00531 m_dist_pos[i] = 0x7FFF0000; 00532 00533 int dist1_start; 00534 int dist2_start; 00535 int npix = 1; 00536 00537 if(lp.vertical) 00538 { 00539 do 00540 { 00541 --m_li; 00542 m_y -= lp.inc; 00543 m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; 00544 00545 if(lp.inc > 0) m_di.dec_y(m_x - m_old_x); 00546 else m_di.inc_y(m_x - m_old_x); 00547 00548 m_old_x = m_x; 00549 00550 dist1_start = dist2_start = m_di.dist_start(); 00551 00552 int dx = 0; 00553 if(dist1_start < 0) ++npix; 00554 do 00555 { 00556 dist1_start += m_di.dy_start(); 00557 dist2_start -= m_di.dy_start(); 00558 if(dist1_start < 0) ++npix; 00559 if(dist2_start < 0) ++npix; 00560 ++dx; 00561 } 00562 while(m_dist_pos[dx] <= m_width); 00563 if(npix == 0) break; 00564 00565 npix = 0; 00566 } 00567 while(--m_step >= -m_max_extent); 00568 } 00569 else 00570 { 00571 do 00572 { 00573 --m_li; 00574 00575 m_x -= lp.inc; 00576 m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; 00577 00578 if(lp.inc > 0) m_di.dec_x(m_y - m_old_y); 00579 else m_di.inc_x(m_y - m_old_y); 00580 00581 m_old_y = m_y; 00582 00583 dist1_start = dist2_start = m_di.dist_start(); 00584 00585 int dy = 0; 00586 if(dist1_start < 0) ++npix; 00587 do 00588 { 00589 dist1_start -= m_di.dx_start(); 00590 dist2_start += m_di.dx_start(); 00591 if(dist1_start < 0) ++npix; 00592 if(dist2_start < 0) ++npix; 00593 ++dy; 00594 } 00595 while(m_dist_pos[dy] <= m_width); 00596 if(npix == 0) break; 00597 00598 npix = 0; 00599 } 00600 while(--m_step >= -m_max_extent); 00601 } 00602 m_li.adjust_forward(); 00603 m_step -= m_max_extent; 00604 } 00605 00606 //--------------------------------------------------------------------- 00607 bool step_hor() 00608 { 00609 ++m_li; 00610 m_x += m_lp.inc; 00611 m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; 00612 00613 if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y); 00614 else m_di.dec_x(m_y - m_old_y); 00615 00616 m_old_y = m_y; 00617 00618 int s1 = m_di.dist() / m_lp.len; 00619 int s2 = -s1; 00620 00621 if(m_lp.inc < 0) s1 = -s1; 00622 00623 int dist_start; 00624 int dist_pict; 00625 int dist_end; 00626 int dy; 00627 int dist; 00628 00629 dist_start = m_di.dist_start(); 00630 dist_pict = m_di.dist_pict() + m_start; 00631 dist_end = m_di.dist_end(); 00632 color_type* p0 = m_colors + max_half_width + 2; 00633 color_type* p1 = p0; 00634 00635 int npix = 0; 00636 p1->clear(); 00637 if(dist_end > 0) 00638 { 00639 if(dist_start <= 0) 00640 { 00641 m_ren.pixel(p1, dist_pict, s2); 00642 } 00643 ++npix; 00644 } 00645 ++p1; 00646 00647 dy = 1; 00648 while((dist = m_dist_pos[dy]) - s1 <= m_width) 00649 { 00650 dist_start -= m_di.dx_start(); 00651 dist_pict -= m_di.dx_pict(); 00652 dist_end -= m_di.dx_end(); 00653 p1->clear(); 00654 if(dist_end > 0 && dist_start <= 0) 00655 { 00656 if(m_lp.inc > 0) dist = -dist; 00657 m_ren.pixel(p1, dist_pict, s2 - dist); 00658 ++npix; 00659 } 00660 ++p1; 00661 ++dy; 00662 } 00663 00664 dy = 1; 00665 dist_start = m_di.dist_start(); 00666 dist_pict = m_di.dist_pict() + m_start; 00667 dist_end = m_di.dist_end(); 00668 while((dist = m_dist_pos[dy]) + s1 <= m_width) 00669 { 00670 dist_start += m_di.dx_start(); 00671 dist_pict += m_di.dx_pict(); 00672 dist_end += m_di.dx_end(); 00673 --p0; 00674 p0->clear(); 00675 if(dist_end > 0 && dist_start <= 0) 00676 { 00677 if(m_lp.inc > 0) dist = -dist; 00678 m_ren.pixel(p0, dist_pict, s2 + dist); 00679 ++npix; 00680 } 00681 ++dy; 00682 } 00683 m_ren.blend_color_vspan(m_x, 00684 m_y - dy + 1, 00685 unsigned(p1 - p0), 00686 p0); 00687 return npix && ++m_step < m_count; 00688 } 00689 00690 00691 00692 //--------------------------------------------------------------------- 00693 bool step_ver() 00694 { 00695 ++m_li; 00696 m_y += m_lp.inc; 00697 m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; 00698 00699 if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x); 00700 else m_di.dec_y(m_x - m_old_x); 00701 00702 m_old_x = m_x; 00703 00704 int s1 = m_di.dist() / m_lp.len; 00705 int s2 = -s1; 00706 00707 if(m_lp.inc > 0) s1 = -s1; 00708 00709 int dist_start; 00710 int dist_pict; 00711 int dist_end; 00712 int dist; 00713 int dx; 00714 00715 dist_start = m_di.dist_start(); 00716 dist_pict = m_di.dist_pict() + m_start; 00717 dist_end = m_di.dist_end(); 00718 color_type* p0 = m_colors + max_half_width + 2; 00719 color_type* p1 = p0; 00720 00721 int npix = 0; 00722 p1->clear(); 00723 if(dist_end > 0) 00724 { 00725 if(dist_start <= 0) 00726 { 00727 m_ren.pixel(p1, dist_pict, s2); 00728 } 00729 ++npix; 00730 } 00731 ++p1; 00732 00733 dx = 1; 00734 while((dist = m_dist_pos[dx]) - s1 <= m_width) 00735 { 00736 dist_start += m_di.dy_start(); 00737 dist_pict += m_di.dy_pict(); 00738 dist_end += m_di.dy_end(); 00739 p1->clear(); 00740 if(dist_end > 0 && dist_start <= 0) 00741 { 00742 if(m_lp.inc > 0) dist = -dist; 00743 m_ren.pixel(p1, dist_pict, s2 + dist); 00744 ++npix; 00745 } 00746 ++p1; 00747 ++dx; 00748 } 00749 00750 dx = 1; 00751 dist_start = m_di.dist_start(); 00752 dist_pict = m_di.dist_pict() + m_start; 00753 dist_end = m_di.dist_end(); 00754 while((dist = m_dist_pos[dx]) + s1 <= m_width) 00755 { 00756 dist_start -= m_di.dy_start(); 00757 dist_pict -= m_di.dy_pict(); 00758 dist_end -= m_di.dy_end(); 00759 --p0; 00760 p0->clear(); 00761 if(dist_end > 0 && dist_start <= 0) 00762 { 00763 if(m_lp.inc > 0) dist = -dist; 00764 m_ren.pixel(p0, dist_pict, s2 - dist); 00765 ++npix; 00766 } 00767 ++dx; 00768 } 00769 m_ren.blend_color_hspan(m_x - dx + 1, 00770 m_y, 00771 unsigned(p1 - p0), 00772 p0); 00773 return npix && ++m_step < m_count; 00774 } 00775 00776 00777 //--------------------------------------------------------------------- 00778 int pattern_end() const { return m_start + m_di.len(); } 00779 00780 //--------------------------------------------------------------------- 00781 bool vertical() const { return m_lp.vertical; } 00782 int width() const { return m_width; } 00783 int count() const { return m_count; } 00784 00785 private: 00786 line_interpolator_image(const line_interpolator_image<Renderer>&); 00787 const line_interpolator_image<Renderer>& 00788 operator = (const line_interpolator_image<Renderer>&); 00789 00790 protected: 00791 const line_parameters& m_lp; 00792 dda2_line_interpolator m_li; 00793 distance_interpolator4 m_di; 00794 renderer_type& m_ren; 00795 int m_plen; 00796 int m_x; 00797 int m_y; 00798 int m_old_x; 00799 int m_old_y; 00800 int m_count; 00801 int m_width; 00802 int m_max_extent; 00803 int m_start; 00804 int m_step; 00805 int m_dist_pos[max_half_width + 1]; 00806 color_type m_colors[max_half_width * 2 + 4]; 00807 }; 00808 00809 00810 00811 00812 00813 00814 00815 00816 //===================================================renderer_outline_image 00817 template<class BaseRenderer, class ImagePattern> 00818 class renderer_outline_image 00819 { 00820 public: 00821 //--------------------------------------------------------------------- 00822 typedef BaseRenderer base_ren_type; 00823 typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type; 00824 typedef typename base_ren_type::color_type color_type; 00825 typedef ImagePattern pattern_type; 00826 00827 00828 //--------------------------------------------------------------------- 00829 renderer_outline_image(base_ren_type& ren, const pattern_type& patt) : 00830 m_ren(&ren), 00831 m_pattern(&patt), 00832 m_start(0), 00833 m_scale_x(1.0), 00834 m_clip_box(0,0,0,0), 00835 m_clipping(false) 00836 {} 00837 void attach(base_ren_type& ren) { m_ren = &ren; } 00838 00839 //--------------------------------------------------------------------- 00840 void pattern(const pattern_type& p) { m_pattern = &p; } 00841 const pattern_type& pattern() const { return *m_pattern; } 00842 00843 //--------------------------------------------------------------------- 00844 void reset_clipping() { m_clipping = false; } 00845 void clip_box(double x1, double y1, double x2, double y2) 00846 { 00847 m_clip_box.x1 = line_coord_sat::conv(x1); 00848 m_clip_box.y1 = line_coord_sat::conv(y1); 00849 m_clip_box.x2 = line_coord_sat::conv(x2); 00850 m_clip_box.y2 = line_coord_sat::conv(y2); 00851 m_clipping = true; 00852 } 00853 00854 //--------------------------------------------------------------------- 00855 void scale_x(double s) { m_scale_x = s; } 00856 double scale_x() const { return m_scale_x; } 00857 00858 //--------------------------------------------------------------------- 00859 void start_x(double s) { m_start = iround(s * line_subpixel_scale); } 00860 double start_x() const { return double(m_start) / line_subpixel_scale; } 00861 00862 //--------------------------------------------------------------------- 00863 int subpixel_width() const { return m_pattern->line_width(); } 00864 int pattern_width() const { return m_pattern->pattern_width(); } 00865 double width() const { return double(subpixel_width()) / line_subpixel_scale; } 00866 00867 //------------------------------------------------------------------------- 00868 void pixel(color_type* p, int x, int y) const 00869 { 00870 m_pattern->pixel(p, x, y); 00871 } 00872 00873 //------------------------------------------------------------------------- 00874 void blend_color_hspan(int x, int y, unsigned len, const color_type* colors) 00875 { 00876 m_ren->blend_color_hspan(x, y, len, colors, 0); 00877 } 00878 00879 //------------------------------------------------------------------------- 00880 void blend_color_vspan(int x, int y, unsigned len, const color_type* colors) 00881 { 00882 m_ren->blend_color_vspan(x, y, len, colors, 0); 00883 } 00884 00885 //------------------------------------------------------------------------- 00886 static bool accurate_join_only() { return true; } 00887 00888 //------------------------------------------------------------------------- 00889 template<class Cmp> 00890 void semidot(Cmp, int, int, int, int) 00891 { 00892 } 00893 00894 //------------------------------------------------------------------------- 00895 void pie(int, int, int, int, int, int) 00896 { 00897 } 00898 00899 //------------------------------------------------------------------------- 00900 void line0(const line_parameters&) 00901 { 00902 } 00903 00904 //------------------------------------------------------------------------- 00905 void line1(const line_parameters&, int, int) 00906 { 00907 } 00908 00909 //------------------------------------------------------------------------- 00910 void line2(const line_parameters&, int, int) 00911 { 00912 } 00913 00914 //------------------------------------------------------------------------- 00915 void line3_no_clip(const line_parameters& lp, 00916 int sx, int sy, int ex, int ey) 00917 { 00918 if(lp.len > line_max_length) 00919 { 00920 line_parameters lp1, lp2; 00921 lp.divide(lp1, lp2); 00922 int mx = lp1.x2 + (lp1.y2 - lp1.y1); 00923 int my = lp1.y2 - (lp1.x2 - lp1.x1); 00924 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); 00925 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); 00926 return; 00927 } 00928 00929 fix_degenerate_bisectrix_start(lp, &sx, &sy); 00930 fix_degenerate_bisectrix_end(lp, &ex, &ey); 00931 line_interpolator_image<self_type> li(*this, lp, 00932 sx, sy, 00933 ex, ey, 00934 m_start, m_scale_x); 00935 if(li.vertical()) 00936 { 00937 while(li.step_ver()); 00938 } 00939 else 00940 { 00941 while(li.step_hor()); 00942 } 00943 m_start += uround(lp.len / m_scale_x); 00944 } 00945 00946 //------------------------------------------------------------------------- 00947 void line3(const line_parameters& lp, 00948 int sx, int sy, int ex, int ey) 00949 { 00950 if(m_clipping) 00951 { 00952 int x1 = lp.x1; 00953 int y1 = lp.y1; 00954 int x2 = lp.x2; 00955 int y2 = lp.y2; 00956 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 00957 int start = m_start; 00958 if((flags & 4) == 0) 00959 { 00960 if(flags) 00961 { 00962 line_parameters lp2(x1, y1, x2, y2, 00963 uround(calc_distance(x1, y1, x2, y2))); 00964 if(flags & 1) 00965 { 00966 m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x); 00967 sx = x1 + (y2 - y1); 00968 sy = y1 - (x2 - x1); 00969 } 00970 else 00971 { 00972 while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) 00973 { 00974 sx = (lp.x1 + sx) >> 1; 00975 sy = (lp.y1 + sy) >> 1; 00976 } 00977 } 00978 if(flags & 2) 00979 { 00980 ex = x2 + (y2 - y1); 00981 ey = y2 - (x2 - x1); 00982 } 00983 else 00984 { 00985 while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) 00986 { 00987 ex = (lp.x2 + ex) >> 1; 00988 ey = (lp.y2 + ey) >> 1; 00989 } 00990 } 00991 line3_no_clip(lp2, sx, sy, ex, ey); 00992 } 00993 else 00994 { 00995 line3_no_clip(lp, sx, sy, ex, ey); 00996 } 00997 } 00998 m_start = start + uround(lp.len / m_scale_x); 00999 } 01000 else 01001 { 01002 line3_no_clip(lp, sx, sy, ex, ey); 01003 } 01004 } 01005 01006 private: 01007 base_ren_type* m_ren; 01008 const pattern_type* m_pattern; 01009 int m_start; 01010 double m_scale_x; 01011 rect_i m_clip_box; 01012 bool m_clipping; 01013 }; 01014 01015 01016 01017 01018 01019 } 01020 01021 01022 01023 #endif