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_RASTERIZER_OUTLINE_AA_INCLUDED 00026 #define AGG_RASTERIZER_OUTLINE_AA_INCLUDED 00027 00028 #include "agg_basics.h" 00029 #include "agg_line_aa_basics.h" 00030 #include "agg_vertex_sequence.h" 00031 00032 namespace agg 00033 { 00034 00035 //------------------------------------------------------------------------- 00036 inline bool cmp_dist_start(int d) { return d > 0; } 00037 inline bool cmp_dist_end(int d) { return d <= 0; } 00038 00039 00040 00041 //-----------------------------------------------------------line_aa_vertex 00042 // Vertex (x, y) with the distance to the next one. The last vertex has 00043 // the distance between the last and the first points 00044 struct line_aa_vertex 00045 { 00046 int x; 00047 int y; 00048 int len; 00049 00050 line_aa_vertex() {} 00051 line_aa_vertex(int x_, int y_) : 00052 x(x_), 00053 y(y_), 00054 len(0) 00055 { 00056 } 00057 00058 bool operator () (const line_aa_vertex& val) 00059 { 00060 double dx = val.x - x; 00061 double dy = val.y - y; 00062 return (len = uround(sqrt(dx * dx + dy * dy))) > 00063 (line_subpixel_scale + line_subpixel_scale / 2); 00064 } 00065 }; 00066 00067 00068 //----------------------------------------------------------outline_aa_join_e 00069 enum outline_aa_join_e 00070 { 00071 outline_no_join, //-----outline_no_join 00072 outline_miter_join, //-----outline_miter_join 00073 outline_round_join, //-----outline_round_join 00074 outline_miter_accurate_join //-----outline_accurate_join 00075 }; 00076 00077 //=======================================================rasterizer_outline_aa 00078 template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa 00079 { 00080 private: 00081 //------------------------------------------------------------------------ 00082 struct draw_vars 00083 { 00084 unsigned idx; 00085 int x1, y1, x2, y2; 00086 line_parameters curr, next; 00087 int lcurr, lnext; 00088 int xb1, yb1, xb2, yb2; 00089 unsigned flags; 00090 }; 00091 00092 void draw(draw_vars& dv, unsigned start, unsigned end); 00093 00094 public: 00095 typedef line_aa_vertex vertex_type; 00096 typedef vertex_sequence<vertex_type, 6> vertex_storage_type; 00097 00098 explicit rasterizer_outline_aa(Renderer& ren) : 00099 m_ren(&ren), 00100 m_line_join(ren.accurate_join_only() ? 00101 outline_miter_accurate_join : 00102 outline_round_join), 00103 m_round_cap(false), 00104 m_start_x(0), 00105 m_start_y(0) 00106 {} 00107 void attach(Renderer& ren) { m_ren = &ren; } 00108 00109 //------------------------------------------------------------------------ 00110 void line_join(outline_aa_join_e join) 00111 { 00112 m_line_join = m_ren->accurate_join_only() ? 00113 outline_miter_accurate_join : 00114 join; 00115 } 00116 bool line_join() const { return m_line_join; } 00117 00118 //------------------------------------------------------------------------ 00119 void round_cap(bool v) { m_round_cap = v; } 00120 bool round_cap() const { return m_round_cap; } 00121 00122 //------------------------------------------------------------------------ 00123 void move_to(int x, int y) 00124 { 00125 m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y)); 00126 } 00127 00128 //------------------------------------------------------------------------ 00129 void line_to(int x, int y) 00130 { 00131 m_src_vertices.add(vertex_type(x, y)); 00132 } 00133 00134 //------------------------------------------------------------------------ 00135 void move_to_d(double x, double y) 00136 { 00137 move_to(Coord::conv(x), Coord::conv(y)); 00138 } 00139 00140 //------------------------------------------------------------------------ 00141 void line_to_d(double x, double y) 00142 { 00143 line_to(Coord::conv(x), Coord::conv(y)); 00144 } 00145 00146 //------------------------------------------------------------------------ 00147 void render(bool close_polygon); 00148 00149 //------------------------------------------------------------------------ 00150 void add_vertex(double x, double y, unsigned cmd) 00151 { 00152 if(is_move_to(cmd)) 00153 { 00154 render(false); 00155 move_to_d(x, y); 00156 } 00157 else 00158 { 00159 if(is_end_poly(cmd)) 00160 { 00161 render(is_closed(cmd)); 00162 if(is_closed(cmd)) 00163 { 00164 move_to(m_start_x, m_start_y); 00165 } 00166 } 00167 else 00168 { 00169 line_to_d(x, y); 00170 } 00171 } 00172 } 00173 00174 //------------------------------------------------------------------------ 00175 template<class VertexSource> 00176 void add_path(VertexSource& vs, unsigned path_id=0) 00177 { 00178 double x; 00179 double y; 00180 00181 unsigned cmd; 00182 vs.rewind(path_id); 00183 while(!is_stop(cmd = vs.vertex(&x, &y))) 00184 { 00185 add_vertex(x, y, cmd); 00186 } 00187 render(false); 00188 } 00189 00190 00191 //------------------------------------------------------------------------ 00192 template<class VertexSource, class ColorStorage, class PathId> 00193 void render_all_paths(VertexSource& vs, 00194 const ColorStorage& colors, 00195 const PathId& path_id, 00196 unsigned num_paths) 00197 { 00198 for(unsigned i = 0; i < num_paths; i++) 00199 { 00200 m_ren->color(colors[i]); 00201 add_path(vs, path_id[i]); 00202 } 00203 } 00204 00205 00206 //------------------------------------------------------------------------ 00207 template<class Ctrl> void render_ctrl(Ctrl& c) 00208 { 00209 unsigned i; 00210 for(i = 0; i < c.num_paths(); i++) 00211 { 00212 m_ren->color(c.color(i)); 00213 add_path(c, i); 00214 } 00215 } 00216 00217 private: 00218 rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&); 00219 const rasterizer_outline_aa<Renderer, Coord>& operator = 00220 (const rasterizer_outline_aa<Renderer, Coord>&); 00221 00222 Renderer* m_ren; 00223 vertex_storage_type m_src_vertices; 00224 outline_aa_join_e m_line_join; 00225 bool m_round_cap; 00226 int m_start_x; 00227 int m_start_y; 00228 }; 00229 00230 00231 00232 00233 00234 00235 00236 00237 //---------------------------------------------------------------------------- 00238 template<class Renderer, class Coord> 00239 void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv, 00240 unsigned start, 00241 unsigned end) 00242 { 00243 unsigned i; 00244 const vertex_storage_type::value_type* v; 00245 00246 for(i = start; i < end; i++) 00247 { 00248 if(m_line_join == outline_round_join) 00249 { 00250 dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1); 00251 dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1); 00252 dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1); 00253 dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1); 00254 } 00255 00256 switch(dv.flags) 00257 { 00258 case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; 00259 case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break; 00260 case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break; 00261 case 3: m_ren->line0(dv.curr); break; 00262 } 00263 00264 if(m_line_join == outline_round_join && (dv.flags & 2) == 0) 00265 { 00266 m_ren->pie(dv.curr.x2, dv.curr.y2, 00267 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), 00268 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1), 00269 dv.curr.x2 + (dv.next.y2 - dv.next.y1), 00270 dv.curr.y2 - (dv.next.x2 - dv.next.x1)); 00271 } 00272 00273 dv.x1 = dv.x2; 00274 dv.y1 = dv.y2; 00275 dv.lcurr = dv.lnext; 00276 dv.lnext = m_src_vertices[dv.idx].len; 00277 00278 ++dv.idx; 00279 if(dv.idx >= m_src_vertices.size()) dv.idx = 0; 00280 00281 v = &m_src_vertices[dv.idx]; 00282 dv.x2 = v->x; 00283 dv.y2 = v->y; 00284 00285 dv.curr = dv.next; 00286 dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); 00287 dv.xb1 = dv.xb2; 00288 dv.yb1 = dv.yb2; 00289 00290 switch(m_line_join) 00291 { 00292 case outline_no_join: 00293 dv.flags = 3; 00294 break; 00295 00296 case outline_miter_join: 00297 dv.flags >>= 1; 00298 dv.flags |= ((dv.curr.diagonal_quadrant() == 00299 dv.next.diagonal_quadrant()) << 1); 00300 if((dv.flags & 2) == 0) 00301 { 00302 bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); 00303 } 00304 break; 00305 00306 case outline_round_join: 00307 dv.flags >>= 1; 00308 dv.flags |= ((dv.curr.diagonal_quadrant() == 00309 dv.next.diagonal_quadrant()) << 1); 00310 break; 00311 00312 case outline_miter_accurate_join: 00313 dv.flags = 0; 00314 bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); 00315 break; 00316 } 00317 } 00318 } 00319 00320 00321 00322 00323 //---------------------------------------------------------------------------- 00324 template<class Renderer, class Coord> 00325 void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon) 00326 { 00327 m_src_vertices.close(close_polygon); 00328 draw_vars dv; 00329 const vertex_storage_type::value_type* v; 00330 int x1; 00331 int y1; 00332 int x2; 00333 int y2; 00334 int lprev; 00335 00336 if(close_polygon) 00337 { 00338 if(m_src_vertices.size() >= 3) 00339 { 00340 dv.idx = 2; 00341 00342 v = &m_src_vertices[m_src_vertices.size() - 1]; 00343 x1 = v->x; 00344 y1 = v->y; 00345 lprev = v->len; 00346 00347 v = &m_src_vertices[0]; 00348 x2 = v->x; 00349 y2 = v->y; 00350 dv.lcurr = v->len; 00351 line_parameters prev(x1, y1, x2, y2, lprev); 00352 00353 v = &m_src_vertices[1]; 00354 dv.x1 = v->x; 00355 dv.y1 = v->y; 00356 dv.lnext = v->len; 00357 dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); 00358 00359 v = &m_src_vertices[dv.idx]; 00360 dv.x2 = v->x; 00361 dv.y2 = v->y; 00362 dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); 00363 00364 dv.xb1 = 0; 00365 dv.yb1 = 0; 00366 dv.xb2 = 0; 00367 dv.yb2 = 0; 00368 00369 switch(m_line_join) 00370 { 00371 case outline_no_join: 00372 dv.flags = 3; 00373 break; 00374 00375 case outline_miter_join: 00376 case outline_round_join: 00377 dv.flags = 00378 (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | 00379 ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); 00380 break; 00381 00382 case outline_miter_accurate_join: 00383 dv.flags = 0; 00384 break; 00385 } 00386 00387 if((dv.flags & 1) == 0 && m_line_join != outline_round_join) 00388 { 00389 bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); 00390 } 00391 00392 if((dv.flags & 2) == 0 && m_line_join != outline_round_join) 00393 { 00394 bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); 00395 } 00396 draw(dv, 0, m_src_vertices.size()); 00397 } 00398 } 00399 else 00400 { 00401 switch(m_src_vertices.size()) 00402 { 00403 case 0: 00404 case 1: 00405 break; 00406 00407 case 2: 00408 { 00409 v = &m_src_vertices[0]; 00410 x1 = v->x; 00411 y1 = v->y; 00412 lprev = v->len; 00413 v = &m_src_vertices[1]; 00414 x2 = v->x; 00415 y2 = v->y; 00416 line_parameters lp(x1, y1, x2, y2, lprev); 00417 if(m_round_cap) 00418 { 00419 m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); 00420 } 00421 m_ren->line3(lp, 00422 x1 + (y2 - y1), 00423 y1 - (x2 - x1), 00424 x2 + (y2 - y1), 00425 y2 - (x2 - x1)); 00426 if(m_round_cap) 00427 { 00428 m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); 00429 } 00430 } 00431 break; 00432 00433 case 3: 00434 { 00435 int x3, y3; 00436 int lnext; 00437 v = &m_src_vertices[0]; 00438 x1 = v->x; 00439 y1 = v->y; 00440 lprev = v->len; 00441 v = &m_src_vertices[1]; 00442 x2 = v->x; 00443 y2 = v->y; 00444 lnext = v->len; 00445 v = &m_src_vertices[2]; 00446 x3 = v->x; 00447 y3 = v->y; 00448 line_parameters lp1(x1, y1, x2, y2, lprev); 00449 line_parameters lp2(x2, y2, x3, y3, lnext); 00450 00451 if(m_round_cap) 00452 { 00453 m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); 00454 } 00455 00456 if(m_line_join == outline_round_join) 00457 { 00458 m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), 00459 x2 + (y2 - y1), y2 - (x2 - x1)); 00460 00461 m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), 00462 x2 + (y3 - y2), y2 - (x3 - x2)); 00463 00464 m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), 00465 x3 + (y3 - y2), y3 - (x3 - x2)); 00466 } 00467 else 00468 { 00469 bisectrix(lp1, lp2, &dv.xb1, &dv.yb1); 00470 m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), 00471 dv.xb1, dv.yb1); 00472 00473 m_ren->line3(lp2, dv.xb1, dv.yb1, 00474 x3 + (y3 - y2), y3 - (x3 - x2)); 00475 } 00476 if(m_round_cap) 00477 { 00478 m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2)); 00479 } 00480 } 00481 break; 00482 00483 default: 00484 { 00485 dv.idx = 3; 00486 00487 v = &m_src_vertices[0]; 00488 x1 = v->x; 00489 y1 = v->y; 00490 lprev = v->len; 00491 00492 v = &m_src_vertices[1]; 00493 x2 = v->x; 00494 y2 = v->y; 00495 dv.lcurr = v->len; 00496 line_parameters prev(x1, y1, x2, y2, lprev); 00497 00498 v = &m_src_vertices[2]; 00499 dv.x1 = v->x; 00500 dv.y1 = v->y; 00501 dv.lnext = v->len; 00502 dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); 00503 00504 v = &m_src_vertices[dv.idx]; 00505 dv.x2 = v->x; 00506 dv.y2 = v->y; 00507 dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); 00508 00509 dv.xb1 = 0; 00510 dv.yb1 = 0; 00511 dv.xb2 = 0; 00512 dv.yb2 = 0; 00513 00514 switch(m_line_join) 00515 { 00516 case outline_no_join: 00517 dv.flags = 3; 00518 break; 00519 00520 case outline_miter_join: 00521 case outline_round_join: 00522 dv.flags = 00523 (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | 00524 ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); 00525 break; 00526 00527 case outline_miter_accurate_join: 00528 dv.flags = 0; 00529 break; 00530 } 00531 00532 if(m_round_cap) 00533 { 00534 m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); 00535 } 00536 if((dv.flags & 1) == 0) 00537 { 00538 if(m_line_join == outline_round_join) 00539 { 00540 m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), 00541 x2 + (y2 - y1), y2 - (x2 - x1)); 00542 m_ren->pie(prev.x2, prev.y2, 00543 x2 + (y2 - y1), y2 - (x2 - x1), 00544 dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), 00545 dv.curr.y1 - (dv.curr.x2 - dv.curr.x1)); 00546 } 00547 else 00548 { 00549 bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); 00550 m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), 00551 dv.xb1, dv.yb1); 00552 } 00553 } 00554 else 00555 { 00556 m_ren->line1(prev, 00557 x1 + (y2 - y1), 00558 y1 - (x2 - x1)); 00559 } 00560 if((dv.flags & 2) == 0 && m_line_join != outline_round_join) 00561 { 00562 bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); 00563 } 00564 00565 draw(dv, 1, m_src_vertices.size() - 2); 00566 00567 if((dv.flags & 1) == 0) 00568 { 00569 if(m_line_join == outline_round_join) 00570 { 00571 m_ren->line3(dv.curr, 00572 dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), 00573 dv.curr.y1 - (dv.curr.x2 - dv.curr.x1), 00574 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), 00575 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); 00576 } 00577 else 00578 { 00579 m_ren->line3(dv.curr, dv.xb1, dv.yb1, 00580 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), 00581 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); 00582 } 00583 } 00584 else 00585 { 00586 m_ren->line2(dv.curr, 00587 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), 00588 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); 00589 } 00590 if(m_round_cap) 00591 { 00592 m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, 00593 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), 00594 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); 00595 } 00596 00597 } 00598 break; 00599 } 00600 } 00601 m_src_vertices.remove_all(); 00602 } 00603 00604 00605 } 00606 00607 00608 #endif 00609