139241fe2SDarkWyrm //---------------------------------------------------------------------------- 2e39da397SStephan Aßmus // Anti-Grain Geometry - Version 2.4 3e39da397SStephan Aßmus // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 439241fe2SDarkWyrm // 539241fe2SDarkWyrm // Permission to copy, use, modify, sell and distribute this software 639241fe2SDarkWyrm // is granted provided this copyright notice appears in all copies. 739241fe2SDarkWyrm // This software is provided "as is" without express or implied 839241fe2SDarkWyrm // warranty, and with no claim as to its suitability for any purpose. 939241fe2SDarkWyrm // 10e39da397SStephan Aßmus //---------------------------------------------------------------------------- 11e39da397SStephan Aßmus // 1239241fe2SDarkWyrm // The author gratefully acknowleges the support of David Turner, 1339241fe2SDarkWyrm // Robert Wilhelm, and Werner Lemberg - the authors of the FreeType 1439241fe2SDarkWyrm // libray - in producing this work. See http://www.freetype.org for details. 1539241fe2SDarkWyrm // 1639241fe2SDarkWyrm //---------------------------------------------------------------------------- 1739241fe2SDarkWyrm // Contact: mcseem@antigrain.com 1839241fe2SDarkWyrm // mcseemagg@yahoo.com 1939241fe2SDarkWyrm // http://www.antigrain.com 2039241fe2SDarkWyrm //---------------------------------------------------------------------------- 2139241fe2SDarkWyrm // 22e39da397SStephan Aßmus // Adaptation for 32-bit screen coordinates has been sponsored by 23e39da397SStephan Aßmus // Liberty Technology Systems, Inc., visit http://lib-sys.com 2439241fe2SDarkWyrm // 25e39da397SStephan Aßmus // Liberty Technology Systems, Inc. is the provider of 26e39da397SStephan Aßmus // PostScript and PDF technology for software developers. 2739241fe2SDarkWyrm // 2839241fe2SDarkWyrm //---------------------------------------------------------------------------- 2939241fe2SDarkWyrm #ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED 3039241fe2SDarkWyrm #define AGG_RASTERIZER_SCANLINE_AA_INCLUDED 3139241fe2SDarkWyrm 32e39da397SStephan Aßmus #include "agg_rasterizer_cells_aa.h" 33e39da397SStephan Aßmus #include "agg_rasterizer_sl_clip.h" 3439241fe2SDarkWyrm #include "agg_gamma_functions.h" 3539241fe2SDarkWyrm 3639241fe2SDarkWyrm 3739241fe2SDarkWyrm namespace agg 3839241fe2SDarkWyrm { 3939241fe2SDarkWyrm 4039241fe2SDarkWyrm 4139241fe2SDarkWyrm //-----------------------------------------------------------------cell_aa 4239241fe2SDarkWyrm // A pixel cell. There're no constructors defined and it was done 4339241fe2SDarkWyrm // intentionally in order to avoid extra overhead when allocating an 4439241fe2SDarkWyrm // array of cells. 4539241fe2SDarkWyrm struct cell_aa 4639241fe2SDarkWyrm { 47e39da397SStephan Aßmus int x; 48e39da397SStephan Aßmus int y; 4939241fe2SDarkWyrm int cover; 5039241fe2SDarkWyrm int area; 5139241fe2SDarkWyrm initialcell_aa52e39da397SStephan Aßmus void initial() 5339241fe2SDarkWyrm { 54e39da397SStephan Aßmus x = 0x7FFFFFFF; 55e39da397SStephan Aßmus y = 0x7FFFFFFF; 56e39da397SStephan Aßmus cover = 0; 57e39da397SStephan Aßmus area = 0; 58e39da397SStephan Aßmus } 59e39da397SStephan Aßmus stylecell_aa60e39da397SStephan Aßmus void style(const cell_aa&) {} 61e39da397SStephan Aßmus not_equalcell_aa62e39da397SStephan Aßmus int not_equal(int ex, int ey, const cell_aa&) const 6339241fe2SDarkWyrm { 64e39da397SStephan Aßmus return (ex - x) | (ey - y); 65e39da397SStephan Aßmus } 6639241fe2SDarkWyrm }; 6739241fe2SDarkWyrm 6839241fe2SDarkWyrm 6939241fe2SDarkWyrm //==================================================rasterizer_scanline_aa 7039241fe2SDarkWyrm // Polygon rasterizer that is used to render filled polygons with 7139241fe2SDarkWyrm // high-quality Anti-Aliasing. Internally, by default, the class uses 7239241fe2SDarkWyrm // integer coordinates in format 24.8, i.e. 24 bits for integer part 73e39da397SStephan Aßmus // and 8 bits for fractional - see poly_subpixel_shift. This class can be 7439241fe2SDarkWyrm // used in the following way: 7539241fe2SDarkWyrm // 7639241fe2SDarkWyrm // 1. filling_rule(filling_rule_e ft) - optional. 7739241fe2SDarkWyrm // 7839241fe2SDarkWyrm // 2. gamma() - optional. 7939241fe2SDarkWyrm // 8039241fe2SDarkWyrm // 3. reset() 8139241fe2SDarkWyrm // 8239241fe2SDarkWyrm // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create 8339241fe2SDarkWyrm // more than one contour, but each contour must consist of at least 3 8439241fe2SDarkWyrm // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3); 8539241fe2SDarkWyrm // is the absolute minimum of vertices that define a triangle. 8639241fe2SDarkWyrm // The algorithm does not check either the number of vertices nor 8739241fe2SDarkWyrm // coincidence of their coordinates, but in the worst case it just 8839241fe2SDarkWyrm // won't draw anything. 8939241fe2SDarkWyrm // The orger of the vertices (clockwise or counterclockwise) 9039241fe2SDarkWyrm // is important when using the non-zero filling rule (fill_non_zero). 9139241fe2SDarkWyrm // In this case the vertex order of all the contours must be the same 9239241fe2SDarkWyrm // if you want your intersecting polygons to be without "holes". 9339241fe2SDarkWyrm // You actually can use different vertices order. If the contours do not 9439241fe2SDarkWyrm // intersect each other the order is not important anyway. If they do, 9539241fe2SDarkWyrm // contours with the same vertex order will be rendered without "holes" 9639241fe2SDarkWyrm // while the intersecting contours with different orders will have "holes". 9739241fe2SDarkWyrm // 9839241fe2SDarkWyrm // filling_rule() and gamma() can be called anytime before "sweeping". 9939241fe2SDarkWyrm //------------------------------------------------------------------------ 100e39da397SStephan Aßmus template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa 10139241fe2SDarkWyrm { 10239241fe2SDarkWyrm enum status 10339241fe2SDarkWyrm { 10439241fe2SDarkWyrm status_initial, 105e39da397SStephan Aßmus status_move_to, 10639241fe2SDarkWyrm status_line_to, 10739241fe2SDarkWyrm status_closed 10839241fe2SDarkWyrm }; 10939241fe2SDarkWyrm 11039241fe2SDarkWyrm public: 111e39da397SStephan Aßmus typedef Clip clip_type; 112e39da397SStephan Aßmus typedef typename Clip::conv_type conv_type; 113e39da397SStephan Aßmus typedef typename Clip::coord_type coord_type; 114e39da397SStephan Aßmus 115e39da397SStephan Aßmus enum aa_scale_e 11639241fe2SDarkWyrm { 117e39da397SStephan Aßmus aa_shift = 8, 118e39da397SStephan Aßmus aa_scale = 1 << aa_shift, 119e39da397SStephan Aßmus aa_mask = aa_scale - 1, 120e39da397SStephan Aßmus aa_scale2 = aa_scale * 2, 121e39da397SStephan Aßmus aa_mask2 = aa_scale2 - 1 12239241fe2SDarkWyrm }; 12339241fe2SDarkWyrm 12439241fe2SDarkWyrm //-------------------------------------------------------------------- rasterizer_scanline_aa()12539241fe2SDarkWyrm rasterizer_scanline_aa() : 126e39da397SStephan Aßmus m_outline(), 127e39da397SStephan Aßmus m_clipper(), 12839241fe2SDarkWyrm m_filling_rule(fill_non_zero), 129e39da397SStephan Aßmus m_auto_close(true), 13039241fe2SDarkWyrm m_start_x(0), 13139241fe2SDarkWyrm m_start_y(0), 132e39da397SStephan Aßmus m_status(status_initial) 13339241fe2SDarkWyrm { 13439241fe2SDarkWyrm int i; 135e39da397SStephan Aßmus for(i = 0; i < aa_scale; i++) m_gamma[i] = i; 13639241fe2SDarkWyrm } 13739241fe2SDarkWyrm 13839241fe2SDarkWyrm //-------------------------------------------------------------------- 13939241fe2SDarkWyrm template<class GammaF> rasterizer_scanline_aa(const GammaF & gamma_function)14039241fe2SDarkWyrm rasterizer_scanline_aa(const GammaF& gamma_function) : 141e39da397SStephan Aßmus m_outline(), 142e39da397SStephan Aßmus m_clipper(m_outline), 14339241fe2SDarkWyrm m_filling_rule(fill_non_zero), 144e39da397SStephan Aßmus m_auto_close(true), 14539241fe2SDarkWyrm m_start_x(0), 14639241fe2SDarkWyrm m_start_y(0), 147e39da397SStephan Aßmus m_status(status_initial) 14839241fe2SDarkWyrm { 14939241fe2SDarkWyrm gamma(gamma_function); 15039241fe2SDarkWyrm } 15139241fe2SDarkWyrm 15239241fe2SDarkWyrm //-------------------------------------------------------------------- 15339241fe2SDarkWyrm void reset(); 15439241fe2SDarkWyrm void reset_clipping(); 155e39da397SStephan Aßmus void clip_box(double x1, double y1, double x2, double y2); 156e39da397SStephan Aßmus void filling_rule(filling_rule_e filling_rule); auto_close(bool flag)157e39da397SStephan Aßmus void auto_close(bool flag) { m_auto_close = flag; } 15839241fe2SDarkWyrm 15939241fe2SDarkWyrm //-------------------------------------------------------------------- gamma(const GammaF & gamma_function)16039241fe2SDarkWyrm template<class GammaF> void gamma(const GammaF& gamma_function) 16139241fe2SDarkWyrm { 16239241fe2SDarkWyrm int i; 163e39da397SStephan Aßmus for(i = 0; i < aa_scale; i++) 16439241fe2SDarkWyrm { 165e39da397SStephan Aßmus m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); 16639241fe2SDarkWyrm } 16739241fe2SDarkWyrm } 16839241fe2SDarkWyrm 16939241fe2SDarkWyrm //-------------------------------------------------------------------- apply_gamma(unsigned cover)17039241fe2SDarkWyrm unsigned apply_gamma(unsigned cover) const 17139241fe2SDarkWyrm { 17239241fe2SDarkWyrm return m_gamma[cover]; 17339241fe2SDarkWyrm } 17439241fe2SDarkWyrm 17539241fe2SDarkWyrm //-------------------------------------------------------------------- 17639241fe2SDarkWyrm void move_to(int x, int y); 17739241fe2SDarkWyrm void line_to(int x, int y); 17839241fe2SDarkWyrm void move_to_d(double x, double y); 17939241fe2SDarkWyrm void line_to_d(double x, double y); 180e39da397SStephan Aßmus void close_polygon(); 181e39da397SStephan Aßmus void add_vertex(double x, double y, unsigned cmd); 182e39da397SStephan Aßmus 183e39da397SStephan Aßmus void edge(int x1, int y1, int x2, int y2); 184e39da397SStephan Aßmus void edge_d(double x1, double y1, double x2, double y2); 185e39da397SStephan Aßmus 186e39da397SStephan Aßmus //------------------------------------------------------------------- 187e39da397SStephan Aßmus template<class VertexSource> 188e39da397SStephan Aßmus void add_path(VertexSource& vs, unsigned path_id=0) 189e39da397SStephan Aßmus { 190*70b978fdSMurai Takashi double x = 0; 191*70b978fdSMurai Takashi double y = 0; 192e39da397SStephan Aßmus 193e39da397SStephan Aßmus unsigned cmd; 194e39da397SStephan Aßmus vs.rewind(path_id); 195e39da397SStephan Aßmus if(m_outline.sorted()) reset(); 196e39da397SStephan Aßmus while(!is_stop(cmd = vs.vertex(&x, &y))) 197e39da397SStephan Aßmus { 198e39da397SStephan Aßmus add_vertex(x, y, cmd); 199e39da397SStephan Aßmus } 200e39da397SStephan Aßmus } 20139241fe2SDarkWyrm 20239241fe2SDarkWyrm //-------------------------------------------------------------------- min_x()20339241fe2SDarkWyrm int min_x() const { return m_outline.min_x(); } min_y()20439241fe2SDarkWyrm int min_y() const { return m_outline.min_y(); } max_x()20539241fe2SDarkWyrm int max_x() const { return m_outline.max_x(); } max_y()20639241fe2SDarkWyrm int max_y() const { return m_outline.max_y(); } 20739241fe2SDarkWyrm 20839241fe2SDarkWyrm //-------------------------------------------------------------------- 209e39da397SStephan Aßmus void sort(); 210e39da397SStephan Aßmus bool rewind_scanlines(); 211e39da397SStephan Aßmus bool navigate_scanline(int y); 212e39da397SStephan Aßmus 213e39da397SStephan Aßmus //-------------------------------------------------------------------- calculate_alpha(int area)214e39da397SStephan Aßmus AGG_INLINE unsigned calculate_alpha(int area) const 21539241fe2SDarkWyrm { 216e39da397SStephan Aßmus int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); 21739241fe2SDarkWyrm 21839241fe2SDarkWyrm if(cover < 0) cover = -cover; 21939241fe2SDarkWyrm if(m_filling_rule == fill_even_odd) 22039241fe2SDarkWyrm { 221e39da397SStephan Aßmus cover &= aa_mask2; 222e39da397SStephan Aßmus if(cover > aa_scale) 22339241fe2SDarkWyrm { 224e39da397SStephan Aßmus cover = aa_scale2 - cover; 22539241fe2SDarkWyrm } 22639241fe2SDarkWyrm } 22739241fe2SDarkWyrm if(cover > aa_mask) cover = aa_mask; 22839241fe2SDarkWyrm return m_gamma[cover]; 22939241fe2SDarkWyrm } 23039241fe2SDarkWyrm 23139241fe2SDarkWyrm //-------------------------------------------------------------------- sweep_scanline(Scanline & sl)23239241fe2SDarkWyrm template<class Scanline> bool sweep_scanline(Scanline& sl) 23339241fe2SDarkWyrm { 234e39da397SStephan Aßmus for(;;) 235e39da397SStephan Aßmus { 236e39da397SStephan Aßmus if(m_scan_y > m_outline.max_y()) return false; 23739241fe2SDarkWyrm sl.reset_spans(); 238e39da397SStephan Aßmus unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); 239e39da397SStephan Aßmus const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); 240e39da397SStephan Aßmus int cover = 0; 24139241fe2SDarkWyrm 242e39da397SStephan Aßmus while(num_cells) 24339241fe2SDarkWyrm { 244e39da397SStephan Aßmus const cell_aa* cur_cell = *cells; 245e39da397SStephan Aßmus int x = cur_cell->x; 24639241fe2SDarkWyrm int area = cur_cell->area; 247e39da397SStephan Aßmus unsigned alpha; 24839241fe2SDarkWyrm 249e39da397SStephan Aßmus cover += cur_cell->cover; 25039241fe2SDarkWyrm 251e39da397SStephan Aßmus //accumulate all cells with the same X 252e39da397SStephan Aßmus while(--num_cells) 25339241fe2SDarkWyrm { 254e39da397SStephan Aßmus cur_cell = *++cells; 255e39da397SStephan Aßmus if(cur_cell->x != x) break; 25639241fe2SDarkWyrm area += cur_cell->area; 257e39da397SStephan Aßmus cover += cur_cell->cover; 25839241fe2SDarkWyrm } 25939241fe2SDarkWyrm 26039241fe2SDarkWyrm if(area) 26139241fe2SDarkWyrm { 262e39da397SStephan Aßmus alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); 26339241fe2SDarkWyrm if(alpha) 26439241fe2SDarkWyrm { 265e39da397SStephan Aßmus sl.add_cell(x, alpha); 26639241fe2SDarkWyrm } 267e39da397SStephan Aßmus x++; 26839241fe2SDarkWyrm } 26939241fe2SDarkWyrm 270e39da397SStephan Aßmus if(num_cells && cur_cell->x > x) 27139241fe2SDarkWyrm { 272e39da397SStephan Aßmus alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); 27339241fe2SDarkWyrm if(alpha) 27439241fe2SDarkWyrm { 275e39da397SStephan Aßmus sl.add_span(x, cur_cell->x - x, alpha); 27639241fe2SDarkWyrm } 277e39da397SStephan Aßmus } 27839241fe2SDarkWyrm } 27939241fe2SDarkWyrm 280e39da397SStephan Aßmus if(sl.num_spans()) break; 281e39da397SStephan Aßmus ++m_scan_y; 28239241fe2SDarkWyrm } 283e39da397SStephan Aßmus 284e39da397SStephan Aßmus sl.finalize(m_scan_y); 285e39da397SStephan Aßmus ++m_scan_y; 28639241fe2SDarkWyrm return true; 28739241fe2SDarkWyrm } 28839241fe2SDarkWyrm 28939241fe2SDarkWyrm //-------------------------------------------------------------------- 29039241fe2SDarkWyrm bool hit_test(int tx, int ty); 29139241fe2SDarkWyrm 29239241fe2SDarkWyrm 29339241fe2SDarkWyrm private: 29439241fe2SDarkWyrm //-------------------------------------------------------------------- 29539241fe2SDarkWyrm // Disable copying 296e39da397SStephan Aßmus rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&); 297e39da397SStephan Aßmus const rasterizer_scanline_aa<Clip>& 298e39da397SStephan Aßmus operator = (const rasterizer_scanline_aa<Clip>&); 29939241fe2SDarkWyrm 30039241fe2SDarkWyrm private: 301e39da397SStephan Aßmus rasterizer_cells_aa<cell_aa> m_outline; 302e39da397SStephan Aßmus clip_type m_clipper; 303e39da397SStephan Aßmus int m_gamma[aa_scale]; 30439241fe2SDarkWyrm filling_rule_e m_filling_rule; 305e39da397SStephan Aßmus bool m_auto_close; 306e39da397SStephan Aßmus coord_type m_start_x; 307e39da397SStephan Aßmus coord_type m_start_y; 30839241fe2SDarkWyrm unsigned m_status; 309e39da397SStephan Aßmus int m_scan_y; 31039241fe2SDarkWyrm }; 31139241fe2SDarkWyrm 31239241fe2SDarkWyrm 31339241fe2SDarkWyrm 31439241fe2SDarkWyrm 31539241fe2SDarkWyrm 31639241fe2SDarkWyrm 31739241fe2SDarkWyrm 31839241fe2SDarkWyrm 31939241fe2SDarkWyrm 32039241fe2SDarkWyrm 321e39da397SStephan Aßmus 322e39da397SStephan Aßmus 32339241fe2SDarkWyrm //------------------------------------------------------------------------ 324e39da397SStephan Aßmus template<class Clip> reset()325e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::reset() 32639241fe2SDarkWyrm { 32739241fe2SDarkWyrm m_outline.reset(); 32839241fe2SDarkWyrm m_status = status_initial; 32939241fe2SDarkWyrm } 33039241fe2SDarkWyrm 33139241fe2SDarkWyrm //------------------------------------------------------------------------ 332e39da397SStephan Aßmus template<class Clip> filling_rule(filling_rule_e filling_rule)333e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule) 33439241fe2SDarkWyrm { 33539241fe2SDarkWyrm m_filling_rule = filling_rule; 33639241fe2SDarkWyrm } 33739241fe2SDarkWyrm 33839241fe2SDarkWyrm //------------------------------------------------------------------------ 339e39da397SStephan Aßmus template<class Clip> clip_box(double x1,double y1,double x2,double y2)340e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1, 341e39da397SStephan Aßmus double x2, double y2) 34239241fe2SDarkWyrm { 34339241fe2SDarkWyrm reset(); 344e39da397SStephan Aßmus m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), 345e39da397SStephan Aßmus conv_type::upscale(x2), conv_type::upscale(y2)); 34639241fe2SDarkWyrm } 34739241fe2SDarkWyrm 34839241fe2SDarkWyrm //------------------------------------------------------------------------ 349e39da397SStephan Aßmus template<class Clip> reset_clipping()350e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::reset_clipping() 35139241fe2SDarkWyrm { 35239241fe2SDarkWyrm reset(); 353e39da397SStephan Aßmus m_clipper.reset_clipping(); 35439241fe2SDarkWyrm } 35539241fe2SDarkWyrm 35639241fe2SDarkWyrm //------------------------------------------------------------------------ 357e39da397SStephan Aßmus template<class Clip> close_polygon()358e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::close_polygon() 35939241fe2SDarkWyrm { 36039241fe2SDarkWyrm if(m_status == status_line_to) 36139241fe2SDarkWyrm { 362e39da397SStephan Aßmus m_clipper.line_to(m_outline, m_start_x, m_start_y); 36339241fe2SDarkWyrm m_status = status_closed; 36439241fe2SDarkWyrm } 36539241fe2SDarkWyrm } 36639241fe2SDarkWyrm 367e39da397SStephan Aßmus //------------------------------------------------------------------------ 368e39da397SStephan Aßmus template<class Clip> move_to(int x,int y)369e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::move_to(int x, int y) 370e39da397SStephan Aßmus { 371e39da397SStephan Aßmus if(m_outline.sorted()) reset(); 372e39da397SStephan Aßmus if(m_auto_close) close_polygon(); 373e39da397SStephan Aßmus m_clipper.move_to(m_start_x = conv_type::downscale(x), 374e39da397SStephan Aßmus m_start_y = conv_type::downscale(y)); 375e39da397SStephan Aßmus m_status = status_move_to; 376e39da397SStephan Aßmus } 37739241fe2SDarkWyrm 37839241fe2SDarkWyrm //------------------------------------------------------------------------ 379e39da397SStephan Aßmus template<class Clip> line_to(int x,int y)380e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::line_to(int x, int y) 38139241fe2SDarkWyrm { 382e39da397SStephan Aßmus m_clipper.line_to(m_outline, 383e39da397SStephan Aßmus conv_type::downscale(x), 384e39da397SStephan Aßmus conv_type::downscale(y)); 385e39da397SStephan Aßmus m_status = status_line_to; 38639241fe2SDarkWyrm } 38739241fe2SDarkWyrm 38839241fe2SDarkWyrm //------------------------------------------------------------------------ 389e39da397SStephan Aßmus template<class Clip> move_to_d(double x,double y)390e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y) 39139241fe2SDarkWyrm { 392e39da397SStephan Aßmus if(m_outline.sorted()) reset(); 393e39da397SStephan Aßmus if(m_auto_close) close_polygon(); 394e39da397SStephan Aßmus m_clipper.move_to(m_start_x = conv_type::upscale(x), 395e39da397SStephan Aßmus m_start_y = conv_type::upscale(y)); 396e39da397SStephan Aßmus m_status = status_move_to; 397e39da397SStephan Aßmus } 398e39da397SStephan Aßmus 399e39da397SStephan Aßmus //------------------------------------------------------------------------ 400e39da397SStephan Aßmus template<class Clip> line_to_d(double x,double y)401e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y) 402e39da397SStephan Aßmus { 403e39da397SStephan Aßmus m_clipper.line_to(m_outline, 404e39da397SStephan Aßmus conv_type::upscale(x), 405e39da397SStephan Aßmus conv_type::upscale(y)); 406e39da397SStephan Aßmus m_status = status_line_to; 407e39da397SStephan Aßmus } 408e39da397SStephan Aßmus 409e39da397SStephan Aßmus //------------------------------------------------------------------------ 410e39da397SStephan Aßmus template<class Clip> add_vertex(double x,double y,unsigned cmd)411e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd) 412e39da397SStephan Aßmus { 413e39da397SStephan Aßmus if(is_move_to(cmd)) 414e39da397SStephan Aßmus { 415e39da397SStephan Aßmus move_to_d(x, y); 416e39da397SStephan Aßmus } 417e39da397SStephan Aßmus else 418e39da397SStephan Aßmus if(is_vertex(cmd)) 419e39da397SStephan Aßmus { 420e39da397SStephan Aßmus line_to_d(x, y); 421e39da397SStephan Aßmus } 422e39da397SStephan Aßmus else 42339241fe2SDarkWyrm if(is_close(cmd)) 42439241fe2SDarkWyrm { 42539241fe2SDarkWyrm close_polygon(); 42639241fe2SDarkWyrm } 42739241fe2SDarkWyrm } 42839241fe2SDarkWyrm 42939241fe2SDarkWyrm //------------------------------------------------------------------------ 430e39da397SStephan Aßmus template<class Clip> edge(int x1,int y1,int x2,int y2)431e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2) 43239241fe2SDarkWyrm { 433e39da397SStephan Aßmus if(m_outline.sorted()) reset(); 434e39da397SStephan Aßmus m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); 435e39da397SStephan Aßmus m_clipper.line_to(m_outline, 436e39da397SStephan Aßmus conv_type::downscale(x2), 437e39da397SStephan Aßmus conv_type::downscale(y2)); 438e39da397SStephan Aßmus m_status = status_move_to; 43939241fe2SDarkWyrm } 44039241fe2SDarkWyrm 44139241fe2SDarkWyrm //------------------------------------------------------------------------ 442e39da397SStephan Aßmus template<class Clip> edge_d(double x1,double y1,double x2,double y2)443e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1, 444e39da397SStephan Aßmus double x2, double y2) 44539241fe2SDarkWyrm { 446e39da397SStephan Aßmus if(m_outline.sorted()) reset(); 447e39da397SStephan Aßmus m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); 448e39da397SStephan Aßmus m_clipper.line_to(m_outline, 449e39da397SStephan Aßmus conv_type::upscale(x2), 450e39da397SStephan Aßmus conv_type::upscale(y2)); 451e39da397SStephan Aßmus m_status = status_move_to; 45239241fe2SDarkWyrm } 45339241fe2SDarkWyrm 45439241fe2SDarkWyrm //------------------------------------------------------------------------ 455e39da397SStephan Aßmus template<class Clip> sort()456e39da397SStephan Aßmus void rasterizer_scanline_aa<Clip>::sort() 45739241fe2SDarkWyrm { 458e39da397SStephan Aßmus m_outline.sort_cells(); 45939241fe2SDarkWyrm } 46039241fe2SDarkWyrm 46139241fe2SDarkWyrm //------------------------------------------------------------------------ 462e39da397SStephan Aßmus template<class Clip> rewind_scanlines()463e39da397SStephan Aßmus AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines() 46439241fe2SDarkWyrm { 465e39da397SStephan Aßmus if(m_auto_close) close_polygon(); 466e39da397SStephan Aßmus m_outline.sort_cells(); 467e39da397SStephan Aßmus if(m_outline.total_cells() == 0) 46839241fe2SDarkWyrm { 46939241fe2SDarkWyrm return false; 47039241fe2SDarkWyrm } 471e39da397SStephan Aßmus m_scan_y = m_outline.min_y(); 472e39da397SStephan Aßmus return true; 473e39da397SStephan Aßmus } 474e39da397SStephan Aßmus 475e39da397SStephan Aßmus 476e39da397SStephan Aßmus //------------------------------------------------------------------------ 477e39da397SStephan Aßmus template<class Clip> navigate_scanline(int y)478e39da397SStephan Aßmus AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y) 479e39da397SStephan Aßmus { 480e39da397SStephan Aßmus if(m_auto_close) close_polygon(); 481e39da397SStephan Aßmus m_outline.sort_cells(); 482e39da397SStephan Aßmus if(m_outline.total_cells() == 0 || 483e39da397SStephan Aßmus y < m_outline.min_y() || 484e39da397SStephan Aßmus y > m_outline.max_y()) 485e39da397SStephan Aßmus { 486e39da397SStephan Aßmus return false; 487e39da397SStephan Aßmus } 488e39da397SStephan Aßmus m_scan_y = y; 489e39da397SStephan Aßmus return true; 490e39da397SStephan Aßmus } 491e39da397SStephan Aßmus 492e39da397SStephan Aßmus //------------------------------------------------------------------------ 493e39da397SStephan Aßmus template<class Clip> hit_test(int tx,int ty)494e39da397SStephan Aßmus bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty) 495e39da397SStephan Aßmus { 496e39da397SStephan Aßmus if(!navigate_scanline(ty)) return false; 497e39da397SStephan Aßmus scanline_hit_test sl(tx); 498e39da397SStephan Aßmus sweep_scanline(sl); 499e39da397SStephan Aßmus return sl.hit(); 500e39da397SStephan Aßmus } 501e39da397SStephan Aßmus 502e39da397SStephan Aßmus 50339241fe2SDarkWyrm 50439241fe2SDarkWyrm } 50539241fe2SDarkWyrm 50639241fe2SDarkWyrm 50739241fe2SDarkWyrm 50839241fe2SDarkWyrm #endif 50939241fe2SDarkWyrm 510