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_AA_INCLUDED 00026 #define AGG_RENDERER_OUTLINE_AA_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_ellipse_bresenham.h" 00033 #include "agg_renderer_base.h" 00034 #include "agg_gamma_functions.h" 00035 #include "agg_clip_liang_barsky.h" 00036 00037 namespace agg 00038 { 00039 00040 //===================================================distance_interpolator0 00041 class distance_interpolator0 00042 { 00043 public: 00044 //--------------------------------------------------------------------- 00045 distance_interpolator0() {} 00046 distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) : 00047 m_dx(line_mr(x2) - line_mr(x1)), 00048 m_dy(line_mr(y2) - line_mr(y1)), 00049 m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy - 00050 (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx) 00051 { 00052 m_dx <<= line_mr_subpixel_shift; 00053 m_dy <<= line_mr_subpixel_shift; 00054 } 00055 00056 //--------------------------------------------------------------------- 00057 void inc_x() { m_dist += m_dy; } 00058 int dist() const { return m_dist; } 00059 00060 private: 00061 //--------------------------------------------------------------------- 00062 int m_dx; 00063 int m_dy; 00064 int m_dist; 00065 }; 00066 00067 //==================================================distance_interpolator00 00068 class distance_interpolator00 00069 { 00070 public: 00071 //--------------------------------------------------------------------- 00072 distance_interpolator00() {} 00073 distance_interpolator00(int xc, int yc, 00074 int x1, int y1, int x2, int y2, 00075 int x, int y) : 00076 m_dx1(line_mr(x1) - line_mr(xc)), 00077 m_dy1(line_mr(y1) - line_mr(yc)), 00078 m_dx2(line_mr(x2) - line_mr(xc)), 00079 m_dy2(line_mr(y2) - line_mr(yc)), 00080 m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 - 00081 (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1), 00082 m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 - 00083 (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2) 00084 { 00085 m_dx1 <<= line_mr_subpixel_shift; 00086 m_dy1 <<= line_mr_subpixel_shift; 00087 m_dx2 <<= line_mr_subpixel_shift; 00088 m_dy2 <<= line_mr_subpixel_shift; 00089 } 00090 00091 //--------------------------------------------------------------------- 00092 void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; } 00093 int dist1() const { return m_dist1; } 00094 int dist2() const { return m_dist2; } 00095 00096 private: 00097 //--------------------------------------------------------------------- 00098 int m_dx1; 00099 int m_dy1; 00100 int m_dx2; 00101 int m_dy2; 00102 int m_dist1; 00103 int m_dist2; 00104 }; 00105 00106 //===================================================distance_interpolator1 00107 class distance_interpolator1 00108 { 00109 public: 00110 //--------------------------------------------------------------------- 00111 distance_interpolator1() {} 00112 distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) : 00113 m_dx(x2 - x1), 00114 m_dy(y2 - y1), 00115 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 00116 double(y + line_subpixel_scale/2 - y2) * double(m_dx))) 00117 { 00118 m_dx <<= line_subpixel_shift; 00119 m_dy <<= line_subpixel_shift; 00120 } 00121 00122 //--------------------------------------------------------------------- 00123 void inc_x() { m_dist += m_dy; } 00124 void dec_x() { m_dist -= m_dy; } 00125 void inc_y() { m_dist -= m_dx; } 00126 void dec_y() { m_dist += m_dx; } 00127 00128 //--------------------------------------------------------------------- 00129 void inc_x(int dy) 00130 { 00131 m_dist += m_dy; 00132 if(dy > 0) m_dist -= m_dx; 00133 if(dy < 0) m_dist += m_dx; 00134 } 00135 00136 //--------------------------------------------------------------------- 00137 void dec_x(int dy) 00138 { 00139 m_dist -= m_dy; 00140 if(dy > 0) m_dist -= m_dx; 00141 if(dy < 0) m_dist += m_dx; 00142 } 00143 00144 //--------------------------------------------------------------------- 00145 void inc_y(int dx) 00146 { 00147 m_dist -= m_dx; 00148 if(dx > 0) m_dist += m_dy; 00149 if(dx < 0) m_dist -= m_dy; 00150 } 00151 00152 void dec_y(int dx) 00153 //--------------------------------------------------------------------- 00154 { 00155 m_dist += m_dx; 00156 if(dx > 0) m_dist += m_dy; 00157 if(dx < 0) m_dist -= m_dy; 00158 } 00159 00160 //--------------------------------------------------------------------- 00161 int dist() const { return m_dist; } 00162 int dx() const { return m_dx; } 00163 int dy() const { return m_dy; } 00164 00165 private: 00166 //--------------------------------------------------------------------- 00167 int m_dx; 00168 int m_dy; 00169 int m_dist; 00170 }; 00171 00172 00173 00174 00175 00176 //===================================================distance_interpolator2 00177 class distance_interpolator2 00178 { 00179 public: 00180 //--------------------------------------------------------------------- 00181 distance_interpolator2() {} 00182 distance_interpolator2(int x1, int y1, int x2, int y2, 00183 int sx, int sy, int x, int y) : 00184 m_dx(x2 - x1), 00185 m_dy(y2 - y1), 00186 m_dx_start(line_mr(sx) - line_mr(x1)), 00187 m_dy_start(line_mr(sy) - line_mr(y1)), 00188 00189 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 00190 double(y + line_subpixel_scale/2 - y2) * double(m_dx))), 00191 00192 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - 00193 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start) 00194 { 00195 m_dx <<= line_subpixel_shift; 00196 m_dy <<= line_subpixel_shift; 00197 m_dx_start <<= line_mr_subpixel_shift; 00198 m_dy_start <<= line_mr_subpixel_shift; 00199 } 00200 00201 distance_interpolator2(int x1, int y1, int x2, int y2, 00202 int ex, int ey, int x, int y, int) : 00203 m_dx(x2 - x1), 00204 m_dy(y2 - y1), 00205 m_dx_start(line_mr(ex) - line_mr(x2)), 00206 m_dy_start(line_mr(ey) - line_mr(y2)), 00207 00208 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 00209 double(y + line_subpixel_scale/2 - y2) * double(m_dx))), 00210 00211 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start - 00212 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start) 00213 { 00214 m_dx <<= line_subpixel_shift; 00215 m_dy <<= line_subpixel_shift; 00216 m_dx_start <<= line_mr_subpixel_shift; 00217 m_dy_start <<= line_mr_subpixel_shift; 00218 } 00219 00220 00221 //--------------------------------------------------------------------- 00222 void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; } 00223 void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; } 00224 void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; } 00225 void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; } 00226 00227 //--------------------------------------------------------------------- 00228 void inc_x(int dy) 00229 { 00230 m_dist += m_dy; 00231 m_dist_start += m_dy_start; 00232 if(dy > 0) 00233 { 00234 m_dist -= m_dx; 00235 m_dist_start -= m_dx_start; 00236 } 00237 if(dy < 0) 00238 { 00239 m_dist += m_dx; 00240 m_dist_start += m_dx_start; 00241 } 00242 } 00243 00244 //--------------------------------------------------------------------- 00245 void dec_x(int dy) 00246 { 00247 m_dist -= m_dy; 00248 m_dist_start -= m_dy_start; 00249 if(dy > 0) 00250 { 00251 m_dist -= m_dx; 00252 m_dist_start -= m_dx_start; 00253 } 00254 if(dy < 0) 00255 { 00256 m_dist += m_dx; 00257 m_dist_start += m_dx_start; 00258 } 00259 } 00260 00261 //--------------------------------------------------------------------- 00262 void inc_y(int dx) 00263 { 00264 m_dist -= m_dx; 00265 m_dist_start -= m_dx_start; 00266 if(dx > 0) 00267 { 00268 m_dist += m_dy; 00269 m_dist_start += m_dy_start; 00270 } 00271 if(dx < 0) 00272 { 00273 m_dist -= m_dy; 00274 m_dist_start -= m_dy_start; 00275 } 00276 } 00277 00278 //--------------------------------------------------------------------- 00279 void dec_y(int dx) 00280 { 00281 m_dist += m_dx; 00282 m_dist_start += m_dx_start; 00283 if(dx > 0) 00284 { 00285 m_dist += m_dy; 00286 m_dist_start += m_dy_start; 00287 } 00288 if(dx < 0) 00289 { 00290 m_dist -= m_dy; 00291 m_dist_start -= m_dy_start; 00292 } 00293 } 00294 00295 //--------------------------------------------------------------------- 00296 int dist() const { return m_dist; } 00297 int dist_start() const { return m_dist_start; } 00298 int dist_end() const { return m_dist_start; } 00299 00300 //--------------------------------------------------------------------- 00301 int dx() const { return m_dx; } 00302 int dy() const { return m_dy; } 00303 int dx_start() const { return m_dx_start; } 00304 int dy_start() const { return m_dy_start; } 00305 int dx_end() const { return m_dx_start; } 00306 int dy_end() const { return m_dy_start; } 00307 00308 private: 00309 //--------------------------------------------------------------------- 00310 int m_dx; 00311 int m_dy; 00312 int m_dx_start; 00313 int m_dy_start; 00314 00315 int m_dist; 00316 int m_dist_start; 00317 }; 00318 00319 00320 00321 00322 00323 //===================================================distance_interpolator3 00324 class distance_interpolator3 00325 { 00326 public: 00327 //--------------------------------------------------------------------- 00328 distance_interpolator3() {} 00329 distance_interpolator3(int x1, int y1, int x2, int y2, 00330 int sx, int sy, int ex, int ey, 00331 int x, int y) : 00332 m_dx(x2 - x1), 00333 m_dy(y2 - y1), 00334 m_dx_start(line_mr(sx) - line_mr(x1)), 00335 m_dy_start(line_mr(sy) - line_mr(y1)), 00336 m_dx_end(line_mr(ex) - line_mr(x2)), 00337 m_dy_end(line_mr(ey) - line_mr(y2)), 00338 00339 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 00340 double(y + line_subpixel_scale/2 - y2) * double(m_dx))), 00341 00342 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - 00343 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), 00344 00345 m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - 00346 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end) 00347 { 00348 m_dx <<= line_subpixel_shift; 00349 m_dy <<= line_subpixel_shift; 00350 m_dx_start <<= line_mr_subpixel_shift; 00351 m_dy_start <<= line_mr_subpixel_shift; 00352 m_dx_end <<= line_mr_subpixel_shift; 00353 m_dy_end <<= line_mr_subpixel_shift; 00354 } 00355 00356 //--------------------------------------------------------------------- 00357 void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } 00358 void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; } 00359 void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } 00360 void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } 00361 00362 //--------------------------------------------------------------------- 00363 void inc_x(int dy) 00364 { 00365 m_dist += m_dy; 00366 m_dist_start += m_dy_start; 00367 m_dist_end += m_dy_end; 00368 if(dy > 0) 00369 { 00370 m_dist -= m_dx; 00371 m_dist_start -= m_dx_start; 00372 m_dist_end -= m_dx_end; 00373 } 00374 if(dy < 0) 00375 { 00376 m_dist += m_dx; 00377 m_dist_start += m_dx_start; 00378 m_dist_end += m_dx_end; 00379 } 00380 } 00381 00382 //--------------------------------------------------------------------- 00383 void dec_x(int dy) 00384 { 00385 m_dist -= m_dy; 00386 m_dist_start -= m_dy_start; 00387 m_dist_end -= m_dy_end; 00388 if(dy > 0) 00389 { 00390 m_dist -= m_dx; 00391 m_dist_start -= m_dx_start; 00392 m_dist_end -= m_dx_end; 00393 } 00394 if(dy < 0) 00395 { 00396 m_dist += m_dx; 00397 m_dist_start += m_dx_start; 00398 m_dist_end += m_dx_end; 00399 } 00400 } 00401 00402 //--------------------------------------------------------------------- 00403 void inc_y(int dx) 00404 { 00405 m_dist -= m_dx; 00406 m_dist_start -= m_dx_start; 00407 m_dist_end -= m_dx_end; 00408 if(dx > 0) 00409 { 00410 m_dist += m_dy; 00411 m_dist_start += m_dy_start; 00412 m_dist_end += m_dy_end; 00413 } 00414 if(dx < 0) 00415 { 00416 m_dist -= m_dy; 00417 m_dist_start -= m_dy_start; 00418 m_dist_end -= m_dy_end; 00419 } 00420 } 00421 00422 //--------------------------------------------------------------------- 00423 void dec_y(int dx) 00424 { 00425 m_dist += m_dx; 00426 m_dist_start += m_dx_start; 00427 m_dist_end += m_dx_end; 00428 if(dx > 0) 00429 { 00430 m_dist += m_dy; 00431 m_dist_start += m_dy_start; 00432 m_dist_end += m_dy_end; 00433 } 00434 if(dx < 0) 00435 { 00436 m_dist -= m_dy; 00437 m_dist_start -= m_dy_start; 00438 m_dist_end -= m_dy_end; 00439 } 00440 } 00441 00442 //--------------------------------------------------------------------- 00443 int dist() const { return m_dist; } 00444 int dist_start() const { return m_dist_start; } 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_end() const { return m_dx_end; } 00453 int dy_end() const { return m_dy_end; } 00454 00455 private: 00456 //--------------------------------------------------------------------- 00457 int m_dx; 00458 int m_dy; 00459 int m_dx_start; 00460 int m_dy_start; 00461 int m_dx_end; 00462 int m_dy_end; 00463 00464 int m_dist; 00465 int m_dist_start; 00466 int m_dist_end; 00467 }; 00468 00469 00470 00471 00472 00473 //================================================line_interpolator_aa_base 00474 template<class Renderer> class line_interpolator_aa_base 00475 { 00476 public: 00477 typedef Renderer renderer_type; 00478 typedef typename Renderer::color_type color_type; 00479 00480 //--------------------------------------------------------------------- 00481 enum max_half_width_e 00482 { 00483 max_half_width = 64 00484 }; 00485 00486 //--------------------------------------------------------------------- 00487 line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) : 00488 m_lp(&lp), 00489 m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : 00490 line_dbl_hr(lp.y2 - lp.y1), 00491 lp.vertical ? abs(lp.y2 - lp.y1) : 00492 abs(lp.x2 - lp.x1) + 1), 00493 m_ren(ren), 00494 m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len), 00495 m_x(lp.x1 >> line_subpixel_shift), 00496 m_y(lp.y1 >> line_subpixel_shift), 00497 m_old_x(m_x), 00498 m_old_y(m_y), 00499 m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : 00500 abs((lp.x2 >> line_subpixel_shift) - m_x))), 00501 m_width(ren.subpixel_width()), 00502 //m_max_extent(m_width >> (line_subpixel_shift - 2)), 00503 m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift), 00504 m_step(0) 00505 { 00506 agg::dda2_line_interpolator li(0, lp.vertical ? 00507 (lp.dy << agg::line_subpixel_shift) : 00508 (lp.dx << agg::line_subpixel_shift), 00509 lp.len); 00510 00511 unsigned i; 00512 int stop = m_width + line_subpixel_scale * 2; 00513 for(i = 0; i < max_half_width; ++i) 00514 { 00515 m_dist[i] = li.y(); 00516 if(m_dist[i] >= stop) break; 00517 ++li; 00518 } 00519 m_dist[i++] = 0x7FFF0000; 00520 } 00521 00522 //--------------------------------------------------------------------- 00523 template<class DI> int step_hor_base(DI& di) 00524 { 00525 ++m_li; 00526 m_x += m_lp->inc; 00527 m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift; 00528 00529 if(m_lp->inc > 0) di.inc_x(m_y - m_old_y); 00530 else di.dec_x(m_y - m_old_y); 00531 00532 m_old_y = m_y; 00533 00534 return di.dist() / m_len; 00535 } 00536 00537 //--------------------------------------------------------------------- 00538 template<class DI> int step_ver_base(DI& di) 00539 { 00540 ++m_li; 00541 m_y += m_lp->inc; 00542 m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift; 00543 00544 if(m_lp->inc > 0) di.inc_y(m_x - m_old_x); 00545 else di.dec_y(m_x - m_old_x); 00546 00547 m_old_x = m_x; 00548 00549 return di.dist() / m_len; 00550 } 00551 00552 //--------------------------------------------------------------------- 00553 bool vertical() const { return m_lp->vertical; } 00554 int width() const { return m_width; } 00555 int count() const { return m_count; } 00556 00557 private: 00558 line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&); 00559 const line_interpolator_aa_base<Renderer>& 00560 operator = (const line_interpolator_aa_base<Renderer>&); 00561 00562 protected: 00563 const line_parameters* m_lp; 00564 dda2_line_interpolator m_li; 00565 renderer_type& m_ren; 00566 int m_len; 00567 int m_x; 00568 int m_y; 00569 int m_old_x; 00570 int m_old_y; 00571 int m_count; 00572 int m_width; 00573 int m_max_extent; 00574 int m_step; 00575 int m_dist[max_half_width + 1]; 00576 cover_type m_covers[max_half_width * 2 + 4]; 00577 }; 00578 00579 00580 00581 00582 00583 00584 00585 //====================================================line_interpolator_aa0 00586 template<class Renderer> class line_interpolator_aa0 : 00587 public line_interpolator_aa_base<Renderer> 00588 { 00589 public: 00590 typedef Renderer renderer_type; 00591 typedef typename Renderer::color_type color_type; 00592 typedef line_interpolator_aa_base<Renderer> base_type; 00593 00594 //--------------------------------------------------------------------- 00595 line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) : 00596 line_interpolator_aa_base<Renderer>(ren, lp), 00597 m_di(lp.x1, lp.y1, lp.x2, lp.y2, 00598 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) 00599 { 00600 base_type::m_li.adjust_forward(); 00601 } 00602 00603 //--------------------------------------------------------------------- 00604 bool step_hor() 00605 { 00606 int dist; 00607 int dy; 00608 int s1 = base_type::step_hor_base(m_di); 00609 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 00610 cover_type* p1 = p0; 00611 00612 *p1++ = (cover_type)base_type::m_ren.cover(s1); 00613 00614 dy = 1; 00615 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) 00616 { 00617 *p1++ = (cover_type)base_type::m_ren.cover(dist); 00618 ++dy; 00619 } 00620 00621 dy = 1; 00622 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) 00623 { 00624 *--p0 = (cover_type)base_type::m_ren.cover(dist); 00625 ++dy; 00626 } 00627 base_type::m_ren.blend_solid_vspan(base_type::m_x, 00628 base_type::m_y - dy + 1, 00629 unsigned(p1 - p0), 00630 p0); 00631 return ++base_type::m_step < base_type::m_count; 00632 } 00633 00634 //--------------------------------------------------------------------- 00635 bool step_ver() 00636 { 00637 int dist; 00638 int dx; 00639 int s1 = base_type::step_ver_base(m_di); 00640 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 00641 cover_type* p1 = p0; 00642 00643 *p1++ = (cover_type)base_type::m_ren.cover(s1); 00644 00645 dx = 1; 00646 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) 00647 { 00648 *p1++ = (cover_type)base_type::m_ren.cover(dist); 00649 ++dx; 00650 } 00651 00652 dx = 1; 00653 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) 00654 { 00655 *--p0 = (cover_type)base_type::m_ren.cover(dist); 00656 ++dx; 00657 } 00658 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 00659 base_type::m_y, 00660 unsigned(p1 - p0), 00661 p0); 00662 return ++base_type::m_step < base_type::m_count; 00663 } 00664 00665 private: 00666 line_interpolator_aa0(const line_interpolator_aa0<Renderer>&); 00667 const line_interpolator_aa0<Renderer>& 00668 operator = (const line_interpolator_aa0<Renderer>&); 00669 00670 //--------------------------------------------------------------------- 00671 distance_interpolator1 m_di; 00672 }; 00673 00674 00675 00676 00677 00678 00679 //====================================================line_interpolator_aa1 00680 template<class Renderer> class line_interpolator_aa1 : 00681 public line_interpolator_aa_base<Renderer> 00682 { 00683 public: 00684 typedef Renderer renderer_type; 00685 typedef typename Renderer::color_type color_type; 00686 typedef line_interpolator_aa_base<Renderer> base_type; 00687 00688 //--------------------------------------------------------------------- 00689 line_interpolator_aa1(renderer_type& ren, const line_parameters& lp, 00690 int sx, int sy) : 00691 line_interpolator_aa_base<Renderer>(ren, lp), 00692 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, 00693 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) 00694 { 00695 int dist1_start; 00696 int dist2_start; 00697 00698 int npix = 1; 00699 00700 if(lp.vertical) 00701 { 00702 do 00703 { 00704 --base_type::m_li; 00705 base_type::m_y -= lp.inc; 00706 base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; 00707 00708 if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); 00709 else m_di.inc_y(base_type::m_x - base_type::m_old_x); 00710 00711 base_type::m_old_x = base_type::m_x; 00712 00713 dist1_start = dist2_start = m_di.dist_start(); 00714 00715 int dx = 0; 00716 if(dist1_start < 0) ++npix; 00717 do 00718 { 00719 dist1_start += m_di.dy_start(); 00720 dist2_start -= m_di.dy_start(); 00721 if(dist1_start < 0) ++npix; 00722 if(dist2_start < 0) ++npix; 00723 ++dx; 00724 } 00725 while(base_type::m_dist[dx] <= base_type::m_width); 00726 --base_type::m_step; 00727 if(npix == 0) break; 00728 npix = 0; 00729 } 00730 while(base_type::m_step >= -base_type::m_max_extent); 00731 } 00732 else 00733 { 00734 do 00735 { 00736 --base_type::m_li; 00737 base_type::m_x -= lp.inc; 00738 base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; 00739 00740 if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); 00741 else m_di.inc_x(base_type::m_y - base_type::m_old_y); 00742 00743 base_type::m_old_y = base_type::m_y; 00744 00745 dist1_start = dist2_start = m_di.dist_start(); 00746 00747 int dy = 0; 00748 if(dist1_start < 0) ++npix; 00749 do 00750 { 00751 dist1_start -= m_di.dx_start(); 00752 dist2_start += m_di.dx_start(); 00753 if(dist1_start < 0) ++npix; 00754 if(dist2_start < 0) ++npix; 00755 ++dy; 00756 } 00757 while(base_type::m_dist[dy] <= base_type::m_width); 00758 --base_type::m_step; 00759 if(npix == 0) break; 00760 npix = 0; 00761 } 00762 while(base_type::m_step >= -base_type::m_max_extent); 00763 } 00764 base_type::m_li.adjust_forward(); 00765 } 00766 00767 //--------------------------------------------------------------------- 00768 bool step_hor() 00769 { 00770 int dist_start; 00771 int dist; 00772 int dy; 00773 int s1 = base_type::step_hor_base(m_di); 00774 00775 dist_start = m_di.dist_start(); 00776 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 00777 cover_type* p1 = p0; 00778 00779 *p1 = 0; 00780 if(dist_start <= 0) 00781 { 00782 *p1 = (cover_type)base_type::m_ren.cover(s1); 00783 } 00784 ++p1; 00785 00786 dy = 1; 00787 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) 00788 { 00789 dist_start -= m_di.dx_start(); 00790 *p1 = 0; 00791 if(dist_start <= 0) 00792 { 00793 *p1 = (cover_type)base_type::m_ren.cover(dist); 00794 } 00795 ++p1; 00796 ++dy; 00797 } 00798 00799 dy = 1; 00800 dist_start = m_di.dist_start(); 00801 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) 00802 { 00803 dist_start += m_di.dx_start(); 00804 *--p0 = 0; 00805 if(dist_start <= 0) 00806 { 00807 *p0 = (cover_type)base_type::m_ren.cover(dist); 00808 } 00809 ++dy; 00810 } 00811 00812 base_type::m_ren.blend_solid_vspan(base_type::m_x, 00813 base_type::m_y - dy + 1, 00814 unsigned(p1 - p0), 00815 p0); 00816 return ++base_type::m_step < base_type::m_count; 00817 } 00818 00819 //--------------------------------------------------------------------- 00820 bool step_ver() 00821 { 00822 int dist_start; 00823 int dist; 00824 int dx; 00825 int s1 = base_type::step_ver_base(m_di); 00826 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 00827 cover_type* p1 = p0; 00828 00829 dist_start = m_di.dist_start(); 00830 00831 *p1 = 0; 00832 if(dist_start <= 0) 00833 { 00834 *p1 = (cover_type)base_type::m_ren.cover(s1); 00835 } 00836 ++p1; 00837 00838 dx = 1; 00839 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) 00840 { 00841 dist_start += m_di.dy_start(); 00842 *p1 = 0; 00843 if(dist_start <= 0) 00844 { 00845 *p1 = (cover_type)base_type::m_ren.cover(dist); 00846 } 00847 ++p1; 00848 ++dx; 00849 } 00850 00851 dx = 1; 00852 dist_start = m_di.dist_start(); 00853 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) 00854 { 00855 dist_start -= m_di.dy_start(); 00856 *--p0 = 0; 00857 if(dist_start <= 0) 00858 { 00859 *p0 = (cover_type)base_type::m_ren.cover(dist); 00860 } 00861 ++dx; 00862 } 00863 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 00864 base_type::m_y, 00865 unsigned(p1 - p0), 00866 p0); 00867 return ++base_type::m_step < base_type::m_count; 00868 } 00869 00870 private: 00871 line_interpolator_aa1(const line_interpolator_aa1<Renderer>&); 00872 const line_interpolator_aa1<Renderer>& 00873 operator = (const line_interpolator_aa1<Renderer>&); 00874 00875 //--------------------------------------------------------------------- 00876 distance_interpolator2 m_di; 00877 }; 00878 00879 00880 00881 00882 00883 00884 00885 00886 00887 00888 00889 00890 //====================================================line_interpolator_aa2 00891 template<class Renderer> class line_interpolator_aa2 : 00892 public line_interpolator_aa_base<Renderer> 00893 { 00894 public: 00895 typedef Renderer renderer_type; 00896 typedef typename Renderer::color_type color_type; 00897 typedef line_interpolator_aa_base<Renderer> base_type; 00898 00899 //--------------------------------------------------------------------- 00900 line_interpolator_aa2(renderer_type& ren, const line_parameters& lp, 00901 int ex, int ey) : 00902 line_interpolator_aa_base<Renderer>(ren, lp), 00903 m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey, 00904 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask, 00905 0) 00906 { 00907 base_type::m_li.adjust_forward(); 00908 base_type::m_step -= base_type::m_max_extent; 00909 } 00910 00911 //--------------------------------------------------------------------- 00912 bool step_hor() 00913 { 00914 int dist_end; 00915 int dist; 00916 int dy; 00917 int s1 = base_type::step_hor_base(m_di); 00918 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 00919 cover_type* p1 = p0; 00920 00921 dist_end = m_di.dist_end(); 00922 00923 int npix = 0; 00924 *p1 = 0; 00925 if(dist_end > 0) 00926 { 00927 *p1 = (cover_type)base_type::m_ren.cover(s1); 00928 ++npix; 00929 } 00930 ++p1; 00931 00932 dy = 1; 00933 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) 00934 { 00935 dist_end -= m_di.dx_end(); 00936 *p1 = 0; 00937 if(dist_end > 0) 00938 { 00939 *p1 = (cover_type)base_type::m_ren.cover(dist); 00940 ++npix; 00941 } 00942 ++p1; 00943 ++dy; 00944 } 00945 00946 dy = 1; 00947 dist_end = m_di.dist_end(); 00948 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) 00949 { 00950 dist_end += m_di.dx_end(); 00951 *--p0 = 0; 00952 if(dist_end > 0) 00953 { 00954 *p0 = (cover_type)base_type::m_ren.cover(dist); 00955 ++npix; 00956 } 00957 ++dy; 00958 } 00959 base_type::m_ren.blend_solid_vspan(base_type::m_x, 00960 base_type::m_y - dy + 1, 00961 unsigned(p1 - p0), 00962 p0); 00963 return npix && ++base_type::m_step < base_type::m_count; 00964 } 00965 00966 //--------------------------------------------------------------------- 00967 bool step_ver() 00968 { 00969 int dist_end; 00970 int dist; 00971 int dx; 00972 int s1 = base_type::step_ver_base(m_di); 00973 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 00974 cover_type* p1 = p0; 00975 00976 dist_end = m_di.dist_end(); 00977 00978 int npix = 0; 00979 *p1 = 0; 00980 if(dist_end > 0) 00981 { 00982 *p1 = (cover_type)base_type::m_ren.cover(s1); 00983 ++npix; 00984 } 00985 ++p1; 00986 00987 dx = 1; 00988 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) 00989 { 00990 dist_end += m_di.dy_end(); 00991 *p1 = 0; 00992 if(dist_end > 0) 00993 { 00994 *p1 = (cover_type)base_type::m_ren.cover(dist); 00995 ++npix; 00996 } 00997 ++p1; 00998 ++dx; 00999 } 01000 01001 dx = 1; 01002 dist_end = m_di.dist_end(); 01003 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) 01004 { 01005 dist_end -= m_di.dy_end(); 01006 *--p0 = 0; 01007 if(dist_end > 0) 01008 { 01009 *p0 = (cover_type)base_type::m_ren.cover(dist); 01010 ++npix; 01011 } 01012 ++dx; 01013 } 01014 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 01015 base_type::m_y, 01016 unsigned(p1 - p0), 01017 p0); 01018 return npix && ++base_type::m_step < base_type::m_count; 01019 } 01020 01021 private: 01022 line_interpolator_aa2(const line_interpolator_aa2<Renderer>&); 01023 const line_interpolator_aa2<Renderer>& 01024 operator = (const line_interpolator_aa2<Renderer>&); 01025 01026 //--------------------------------------------------------------------- 01027 distance_interpolator2 m_di; 01028 }; 01029 01030 01031 01032 01033 01034 01035 01036 01037 01038 01039 //====================================================line_interpolator_aa3 01040 template<class Renderer> class line_interpolator_aa3 : 01041 public line_interpolator_aa_base<Renderer> 01042 { 01043 public: 01044 typedef Renderer renderer_type; 01045 typedef typename Renderer::color_type color_type; 01046 typedef line_interpolator_aa_base<Renderer> base_type; 01047 01048 //--------------------------------------------------------------------- 01049 line_interpolator_aa3(renderer_type& ren, const line_parameters& lp, 01050 int sx, int sy, int ex, int ey) : 01051 line_interpolator_aa_base<Renderer>(ren, lp), 01052 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, 01053 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) 01054 { 01055 int dist1_start; 01056 int dist2_start; 01057 int npix = 1; 01058 if(lp.vertical) 01059 { 01060 do 01061 { 01062 --base_type::m_li; 01063 base_type::m_y -= lp.inc; 01064 base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; 01065 01066 if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); 01067 else m_di.inc_y(base_type::m_x - base_type::m_old_x); 01068 01069 base_type::m_old_x = base_type::m_x; 01070 01071 dist1_start = dist2_start = m_di.dist_start(); 01072 01073 int dx = 0; 01074 if(dist1_start < 0) ++npix; 01075 do 01076 { 01077 dist1_start += m_di.dy_start(); 01078 dist2_start -= m_di.dy_start(); 01079 if(dist1_start < 0) ++npix; 01080 if(dist2_start < 0) ++npix; 01081 ++dx; 01082 } 01083 while(base_type::m_dist[dx] <= base_type::m_width); 01084 if(npix == 0) break; 01085 npix = 0; 01086 } 01087 while(--base_type::m_step >= -base_type::m_max_extent); 01088 } 01089 else 01090 { 01091 do 01092 { 01093 --base_type::m_li; 01094 base_type::m_x -= lp.inc; 01095 base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; 01096 01097 if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); 01098 else m_di.inc_x(base_type::m_y - base_type::m_old_y); 01099 01100 base_type::m_old_y = base_type::m_y; 01101 01102 dist1_start = dist2_start = m_di.dist_start(); 01103 01104 int dy = 0; 01105 if(dist1_start < 0) ++npix; 01106 do 01107 { 01108 dist1_start -= m_di.dx_start(); 01109 dist2_start += m_di.dx_start(); 01110 if(dist1_start < 0) ++npix; 01111 if(dist2_start < 0) ++npix; 01112 ++dy; 01113 } 01114 while(base_type::m_dist[dy] <= base_type::m_width); 01115 if(npix == 0) break; 01116 npix = 0; 01117 } 01118 while(--base_type::m_step >= -base_type::m_max_extent); 01119 } 01120 base_type::m_li.adjust_forward(); 01121 base_type::m_step -= base_type::m_max_extent; 01122 } 01123 01124 01125 //--------------------------------------------------------------------- 01126 bool step_hor() 01127 { 01128 int dist_start; 01129 int dist_end; 01130 int dist; 01131 int dy; 01132 int s1 = base_type::step_hor_base(m_di); 01133 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 01134 cover_type* p1 = p0; 01135 01136 dist_start = m_di.dist_start(); 01137 dist_end = m_di.dist_end(); 01138 01139 int npix = 0; 01140 *p1 = 0; 01141 if(dist_end > 0) 01142 { 01143 if(dist_start <= 0) 01144 { 01145 *p1 = (cover_type)base_type::m_ren.cover(s1); 01146 } 01147 ++npix; 01148 } 01149 ++p1; 01150 01151 dy = 1; 01152 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) 01153 { 01154 dist_start -= m_di.dx_start(); 01155 dist_end -= m_di.dx_end(); 01156 *p1 = 0; 01157 if(dist_end > 0 && dist_start <= 0) 01158 { 01159 *p1 = (cover_type)base_type::m_ren.cover(dist); 01160 ++npix; 01161 } 01162 ++p1; 01163 ++dy; 01164 } 01165 01166 dy = 1; 01167 dist_start = m_di.dist_start(); 01168 dist_end = m_di.dist_end(); 01169 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) 01170 { 01171 dist_start += m_di.dx_start(); 01172 dist_end += m_di.dx_end(); 01173 *--p0 = 0; 01174 if(dist_end > 0 && dist_start <= 0) 01175 { 01176 *p0 = (cover_type)base_type::m_ren.cover(dist); 01177 ++npix; 01178 } 01179 ++dy; 01180 } 01181 base_type::m_ren.blend_solid_vspan(base_type::m_x, 01182 base_type::m_y - dy + 1, 01183 unsigned(p1 - p0), 01184 p0); 01185 return npix && ++base_type::m_step < base_type::m_count; 01186 } 01187 01188 //--------------------------------------------------------------------- 01189 bool step_ver() 01190 { 01191 int dist_start; 01192 int dist_end; 01193 int dist; 01194 int dx; 01195 int s1 = base_type::step_ver_base(m_di); 01196 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; 01197 cover_type* p1 = p0; 01198 01199 dist_start = m_di.dist_start(); 01200 dist_end = m_di.dist_end(); 01201 01202 int npix = 0; 01203 *p1 = 0; 01204 if(dist_end > 0) 01205 { 01206 if(dist_start <= 0) 01207 { 01208 *p1 = (cover_type)base_type::m_ren.cover(s1); 01209 } 01210 ++npix; 01211 } 01212 ++p1; 01213 01214 dx = 1; 01215 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) 01216 { 01217 dist_start += m_di.dy_start(); 01218 dist_end += m_di.dy_end(); 01219 *p1 = 0; 01220 if(dist_end > 0 && dist_start <= 0) 01221 { 01222 *p1 = (cover_type)base_type::m_ren.cover(dist); 01223 ++npix; 01224 } 01225 ++p1; 01226 ++dx; 01227 } 01228 01229 dx = 1; 01230 dist_start = m_di.dist_start(); 01231 dist_end = m_di.dist_end(); 01232 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) 01233 { 01234 dist_start -= m_di.dy_start(); 01235 dist_end -= m_di.dy_end(); 01236 *--p0 = 0; 01237 if(dist_end > 0 && dist_start <= 0) 01238 { 01239 *p0 = (cover_type)base_type::m_ren.cover(dist); 01240 ++npix; 01241 } 01242 ++dx; 01243 } 01244 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 01245 base_type::m_y, 01246 unsigned(p1 - p0), 01247 p0); 01248 return npix && ++base_type::m_step < base_type::m_count; 01249 } 01250 01251 private: 01252 line_interpolator_aa3(const line_interpolator_aa3<Renderer>&); 01253 const line_interpolator_aa3<Renderer>& 01254 operator = (const line_interpolator_aa3<Renderer>&); 01255 01256 //--------------------------------------------------------------------- 01257 distance_interpolator3 m_di; 01258 }; 01259 01260 01261 01262 01263 //==========================================================line_profile_aa 01264 // 01265 // See Implementation agg_line_profile_aa.cpp 01266 // 01267 class line_profile_aa 01268 { 01269 public: 01270 //--------------------------------------------------------------------- 01271 typedef int8u value_type; 01272 enum subpixel_scale_e 01273 { 01274 subpixel_shift = line_subpixel_shift, 01275 subpixel_scale = 1 << subpixel_shift, 01276 subpixel_mask = subpixel_scale - 1 01277 }; 01278 01279 enum aa_scale_e 01280 { 01281 aa_shift = 8, 01282 aa_scale = 1 << aa_shift, 01283 aa_mask = aa_scale - 1 01284 }; 01285 01286 //--------------------------------------------------------------------- 01287 line_profile_aa() : 01288 m_subpixel_width(0), 01289 m_min_width(1.0), 01290 m_smoother_width(1.0) 01291 { 01292 int i; 01293 for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i; 01294 } 01295 01296 //--------------------------------------------------------------------- 01297 template<class GammaF> 01298 line_profile_aa(double w, const GammaF& gamma_function) : 01299 m_subpixel_width(0), 01300 m_min_width(1.0), 01301 m_smoother_width(1.0) 01302 { 01303 gamma(gamma_function); 01304 width(w); 01305 } 01306 01307 //--------------------------------------------------------------------- 01308 void min_width(double w) { m_min_width = w; } 01309 void smoother_width(double w) { m_smoother_width = w; } 01310 01311 //--------------------------------------------------------------------- 01312 template<class GammaF> void gamma(const GammaF& gamma_function) 01313 { 01314 int i; 01315 for(i = 0; i < aa_scale; i++) 01316 { 01317 m_gamma[i] = value_type( 01318 uround(gamma_function(double(i) / aa_mask) * aa_mask)); 01319 } 01320 } 01321 01322 void width(double w); 01323 01324 unsigned profile_size() const { return m_profile.size(); } 01325 int subpixel_width() const { return m_subpixel_width; } 01326 01327 //--------------------------------------------------------------------- 01328 double min_width() const { return m_min_width; } 01329 double smoother_width() const { return m_smoother_width; } 01330 01331 //--------------------------------------------------------------------- 01332 value_type value(int dist) const 01333 { 01334 return m_profile[dist + subpixel_scale*2]; 01335 } 01336 01337 private: 01338 line_profile_aa(const line_profile_aa&); 01339 const line_profile_aa& operator = (const line_profile_aa&); 01340 01341 value_type* profile(double w); 01342 void set(double center_width, double smoother_width); 01343 01344 //--------------------------------------------------------------------- 01345 pod_array<value_type> m_profile; 01346 value_type m_gamma[aa_scale]; 01347 int m_subpixel_width; 01348 double m_min_width; 01349 double m_smoother_width; 01350 }; 01351 01352 01353 //======================================================renderer_outline_aa 01354 template<class BaseRenderer> class renderer_outline_aa 01355 { 01356 public: 01357 //--------------------------------------------------------------------- 01358 typedef BaseRenderer base_ren_type; 01359 typedef renderer_outline_aa<base_ren_type> self_type; 01360 typedef typename base_ren_type::color_type color_type; 01361 01362 //--------------------------------------------------------------------- 01363 renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) : 01364 m_ren(&ren), 01365 m_profile(&prof), 01366 m_clip_box(0,0,0,0), 01367 m_clipping(false) 01368 {} 01369 void attach(base_ren_type& ren) { m_ren = &ren; } 01370 01371 //--------------------------------------------------------------------- 01372 void color(const color_type& c) { m_color = c; } 01373 const color_type& color() const { return m_color; } 01374 01375 //--------------------------------------------------------------------- 01376 void profile(const line_profile_aa& prof) { m_profile = &prof; } 01377 const line_profile_aa& profile() const { return *m_profile; } 01378 line_profile_aa& profile() { return *m_profile; } 01379 01380 //--------------------------------------------------------------------- 01381 int subpixel_width() const { return m_profile->subpixel_width(); } 01382 01383 //--------------------------------------------------------------------- 01384 void reset_clipping() { m_clipping = false; } 01385 void clip_box(double x1, double y1, double x2, double y2) 01386 { 01387 m_clip_box.x1 = line_coord_sat::conv(x1); 01388 m_clip_box.y1 = line_coord_sat::conv(y1); 01389 m_clip_box.x2 = line_coord_sat::conv(x2); 01390 m_clip_box.y2 = line_coord_sat::conv(y2); 01391 m_clipping = true; 01392 } 01393 01394 //--------------------------------------------------------------------- 01395 int cover(int d) const 01396 { 01397 return m_profile->value(d); 01398 } 01399 01400 //------------------------------------------------------------------------- 01401 void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers) 01402 { 01403 m_ren->blend_solid_hspan(x, y, len, m_color, covers); 01404 } 01405 01406 //------------------------------------------------------------------------- 01407 void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers) 01408 { 01409 m_ren->blend_solid_vspan(x, y, len, m_color, covers); 01410 } 01411 01412 //------------------------------------------------------------------------- 01413 static bool accurate_join_only() { return false; } 01414 01415 //------------------------------------------------------------------------- 01416 template<class Cmp> 01417 void semidot_hline(Cmp cmp, 01418 int xc1, int yc1, int xc2, int yc2, 01419 int x1, int y1, int x2) 01420 { 01421 cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; 01422 cover_type* p0 = covers; 01423 cover_type* p1 = covers; 01424 int x = x1 << line_subpixel_shift; 01425 int y = y1 << line_subpixel_shift; 01426 int w = subpixel_width(); 01427 distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y); 01428 x += line_subpixel_scale/2; 01429 y += line_subpixel_scale/2; 01430 01431 int x0 = x1; 01432 int dx = x - xc1; 01433 int dy = y - yc1; 01434 do 01435 { 01436 int d = int(fast_sqrt(dx*dx + dy*dy)); 01437 *p1 = 0; 01438 if(cmp(di.dist()) && d <= w) 01439 { 01440 *p1 = (cover_type)cover(d); 01441 } 01442 ++p1; 01443 dx += line_subpixel_scale; 01444 di.inc_x(); 01445 } 01446 while(++x1 <= x2); 01447 m_ren->blend_solid_hspan(x0, y1, 01448 unsigned(p1 - p0), 01449 color(), 01450 p0); 01451 } 01452 01453 //------------------------------------------------------------------------- 01454 template<class Cmp> 01455 void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2) 01456 { 01457 if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return; 01458 01459 int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); 01460 if(r < 1) r = 1; 01461 ellipse_bresenham_interpolator ei(r, r); 01462 int dx = 0; 01463 int dy = -r; 01464 int dy0 = dy; 01465 int dx0 = dx; 01466 int x = xc1 >> line_subpixel_shift; 01467 int y = yc1 >> line_subpixel_shift; 01468 01469 do 01470 { 01471 dx += ei.dx(); 01472 dy += ei.dy(); 01473 01474 if(dy != dy0) 01475 { 01476 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); 01477 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0); 01478 } 01479 dx0 = dx; 01480 dy0 = dy; 01481 ++ei; 01482 } 01483 while(dy < 0); 01484 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); 01485 } 01486 01487 //------------------------------------------------------------------------- 01488 void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2, 01489 int xh1, int yh1, int xh2) 01490 { 01491 if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return; 01492 01493 cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; 01494 cover_type* p0 = covers; 01495 cover_type* p1 = covers; 01496 int x = xh1 << line_subpixel_shift; 01497 int y = yh1 << line_subpixel_shift; 01498 int w = subpixel_width(); 01499 01500 distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y); 01501 x += line_subpixel_scale/2; 01502 y += line_subpixel_scale/2; 01503 01504 int xh0 = xh1; 01505 int dx = x - xc; 01506 int dy = y - yc; 01507 do 01508 { 01509 int d = int(fast_sqrt(dx*dx + dy*dy)); 01510 *p1 = 0; 01511 if(di.dist1() <= 0 && di.dist2() > 0 && d <= w) 01512 { 01513 *p1 = (cover_type)cover(d); 01514 } 01515 ++p1; 01516 dx += line_subpixel_scale; 01517 di.inc_x(); 01518 } 01519 while(++xh1 <= xh2); 01520 m_ren->blend_solid_hspan(xh0, yh1, 01521 unsigned(p1 - p0), 01522 color(), 01523 p0); 01524 } 01525 01526 01527 //------------------------------------------------------------------------- 01528 void pie(int xc, int yc, int x1, int y1, int x2, int y2) 01529 { 01530 int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); 01531 if(r < 1) r = 1; 01532 ellipse_bresenham_interpolator ei(r, r); 01533 int dx = 0; 01534 int dy = -r; 01535 int dy0 = dy; 01536 int dx0 = dx; 01537 int x = xc >> line_subpixel_shift; 01538 int y = yc >> line_subpixel_shift; 01539 01540 do 01541 { 01542 dx += ei.dx(); 01543 dy += ei.dy(); 01544 01545 if(dy != dy0) 01546 { 01547 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); 01548 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0); 01549 } 01550 dx0 = dx; 01551 dy0 = dy; 01552 ++ei; 01553 } 01554 while(dy < 0); 01555 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); 01556 } 01557 01558 //------------------------------------------------------------------------- 01559 void line0_no_clip(const line_parameters& lp) 01560 { 01561 if(lp.len > line_max_length) 01562 { 01563 line_parameters lp1, lp2; 01564 lp.divide(lp1, lp2); 01565 line0_no_clip(lp1); 01566 line0_no_clip(lp2); 01567 return; 01568 } 01569 01570 line_interpolator_aa0<self_type> li(*this, lp); 01571 if(li.count()) 01572 { 01573 if(li.vertical()) 01574 { 01575 while(li.step_ver()); 01576 } 01577 else 01578 { 01579 while(li.step_hor()); 01580 } 01581 } 01582 } 01583 01584 //------------------------------------------------------------------------- 01585 void line0(const line_parameters& lp) 01586 { 01587 if(m_clipping) 01588 { 01589 int x1 = lp.x1; 01590 int y1 = lp.y1; 01591 int x2 = lp.x2; 01592 int y2 = lp.y2; 01593 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 01594 if((flags & 4) == 0) 01595 { 01596 if(flags) 01597 { 01598 line_parameters lp2(x1, y1, x2, y2, 01599 uround(calc_distance(x1, y1, x2, y2))); 01600 line0_no_clip(lp2); 01601 } 01602 else 01603 { 01604 line0_no_clip(lp); 01605 } 01606 } 01607 } 01608 else 01609 { 01610 line0_no_clip(lp); 01611 } 01612 } 01613 01614 //------------------------------------------------------------------------- 01615 void line1_no_clip(const line_parameters& lp, int sx, int sy) 01616 { 01617 if(lp.len > line_max_length) 01618 { 01619 line_parameters lp1, lp2; 01620 lp.divide(lp1, lp2); 01621 line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1); 01622 line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); 01623 return; 01624 } 01625 01626 fix_degenerate_bisectrix_start(lp, &sx, &sy); 01627 line_interpolator_aa1<self_type> li(*this, lp, sx, sy); 01628 if(li.vertical()) 01629 { 01630 while(li.step_ver()); 01631 } 01632 else 01633 { 01634 while(li.step_hor()); 01635 } 01636 } 01637 01638 01639 //------------------------------------------------------------------------- 01640 void line1(const line_parameters& lp, int sx, int sy) 01641 { 01642 if(m_clipping) 01643 { 01644 int x1 = lp.x1; 01645 int y1 = lp.y1; 01646 int x2 = lp.x2; 01647 int y2 = lp.y2; 01648 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 01649 if((flags & 4) == 0) 01650 { 01651 if(flags) 01652 { 01653 line_parameters lp2(x1, y1, x2, y2, 01654 uround(calc_distance(x1, y1, x2, y2))); 01655 if(flags & 1) 01656 { 01657 sx = x1 + (y2 - y1); 01658 sy = y1 - (x2 - x1); 01659 } 01660 else 01661 { 01662 while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) 01663 { 01664 sx = (lp.x1 + sx) >> 1; 01665 sy = (lp.y1 + sy) >> 1; 01666 } 01667 } 01668 line1_no_clip(lp2, sx, sy); 01669 } 01670 else 01671 { 01672 line1_no_clip(lp, sx, sy); 01673 } 01674 } 01675 } 01676 else 01677 { 01678 line1_no_clip(lp, sx, sy); 01679 } 01680 } 01681 01682 //------------------------------------------------------------------------- 01683 void line2_no_clip(const line_parameters& lp, int ex, int ey) 01684 { 01685 if(lp.len > line_max_length) 01686 { 01687 line_parameters lp1, lp2; 01688 lp.divide(lp1, lp2); 01689 line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); 01690 line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); 01691 return; 01692 } 01693 01694 fix_degenerate_bisectrix_end(lp, &ex, &ey); 01695 line_interpolator_aa2<self_type> li(*this, lp, ex, ey); 01696 if(li.vertical()) 01697 { 01698 while(li.step_ver()); 01699 } 01700 else 01701 { 01702 while(li.step_hor()); 01703 } 01704 } 01705 01706 //------------------------------------------------------------------------- 01707 void line2(const line_parameters& lp, int ex, int ey) 01708 { 01709 if(m_clipping) 01710 { 01711 int x1 = lp.x1; 01712 int y1 = lp.y1; 01713 int x2 = lp.x2; 01714 int y2 = lp.y2; 01715 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 01716 if((flags & 4) == 0) 01717 { 01718 if(flags) 01719 { 01720 line_parameters lp2(x1, y1, x2, y2, 01721 uround(calc_distance(x1, y1, x2, y2))); 01722 if(flags & 2) 01723 { 01724 ex = x2 + (y2 - y1); 01725 ey = y2 - (x2 - x1); 01726 } 01727 else 01728 { 01729 while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) 01730 { 01731 ex = (lp.x2 + ex) >> 1; 01732 ey = (lp.y2 + ey) >> 1; 01733 } 01734 } 01735 line2_no_clip(lp2, ex, ey); 01736 } 01737 else 01738 { 01739 line2_no_clip(lp, ex, ey); 01740 } 01741 } 01742 } 01743 else 01744 { 01745 line2_no_clip(lp, ex, ey); 01746 } 01747 } 01748 01749 //------------------------------------------------------------------------- 01750 void line3_no_clip(const line_parameters& lp, 01751 int sx, int sy, int ex, int ey) 01752 { 01753 if(lp.len > line_max_length) 01754 { 01755 line_parameters lp1, lp2; 01756 lp.divide(lp1, lp2); 01757 int mx = lp1.x2 + (lp1.y2 - lp1.y1); 01758 int my = lp1.y2 - (lp1.x2 - lp1.x1); 01759 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); 01760 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); 01761 return; 01762 } 01763 01764 fix_degenerate_bisectrix_start(lp, &sx, &sy); 01765 fix_degenerate_bisectrix_end(lp, &ex, &ey); 01766 line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey); 01767 if(li.vertical()) 01768 { 01769 while(li.step_ver()); 01770 } 01771 else 01772 { 01773 while(li.step_hor()); 01774 } 01775 } 01776 01777 //------------------------------------------------------------------------- 01778 void line3(const line_parameters& lp, 01779 int sx, int sy, int ex, int ey) 01780 { 01781 if(m_clipping) 01782 { 01783 int x1 = lp.x1; 01784 int y1 = lp.y1; 01785 int x2 = lp.x2; 01786 int y2 = lp.y2; 01787 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); 01788 if((flags & 4) == 0) 01789 { 01790 if(flags) 01791 { 01792 line_parameters lp2(x1, y1, x2, y2, 01793 uround(calc_distance(x1, y1, x2, y2))); 01794 if(flags & 1) 01795 { 01796 sx = x1 + (y2 - y1); 01797 sy = y1 - (x2 - x1); 01798 } 01799 else 01800 { 01801 while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) 01802 { 01803 sx = (lp.x1 + sx) >> 1; 01804 sy = (lp.y1 + sy) >> 1; 01805 } 01806 } 01807 if(flags & 2) 01808 { 01809 ex = x2 + (y2 - y1); 01810 ey = y2 - (x2 - x1); 01811 } 01812 else 01813 { 01814 while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) 01815 { 01816 ex = (lp.x2 + ex) >> 1; 01817 ey = (lp.y2 + ey) >> 1; 01818 } 01819 } 01820 line3_no_clip(lp2, sx, sy, ex, ey); 01821 } 01822 else 01823 { 01824 line3_no_clip(lp, sx, sy, ex, ey); 01825 } 01826 } 01827 } 01828 else 01829 { 01830 line3_no_clip(lp, sx, sy, ex, ey); 01831 } 01832 } 01833 01834 01835 private: 01836 base_ren_type* m_ren; 01837 const line_profile_aa* m_profile; 01838 color_type m_color; 01839 rect_i m_clip_box; 01840 bool m_clipping; 01841 }; 01842 01843 01844 01845 } 01846 01847 #endif