xref: /haiku/headers/libs/agg/agg_rasterizer_scanline_aa.h (revision 70b978fd9fc574e72a9f91f58beb36c521ec57c4)
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