29 #ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED 30 #define AGG_RASTERIZER_SCANLINE_AA_INCLUDED 32 #include "agg_rasterizer_cells_aa.h" 33 #include "agg_rasterizer_sl_clip.h" 34 #include "agg_rasterizer_scanline_aa_nogamma.h" 35 #include "agg_gamma_functions.h" 82 typedef Clip clip_type;
83 typedef typename Clip::conv_type conv_type;
84 typedef typename Clip::coord_type coord_type;
89 aa_scale = 1 << aa_shift,
90 aa_mask = aa_scale - 1,
91 aa_scale2 = aa_scale * 2,
92 aa_mask2 = aa_scale2 - 1
97 m_outline(cell_block_limit),
99 m_filling_rule(fill_non_zero),
103 m_status(status_initial)
106 for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
110 template<
class GammaF>
112 m_outline(cell_block_limit),
113 m_clipper(m_outline),
114 m_filling_rule(fill_non_zero),
118 m_status(status_initial)
120 gamma(gamma_function);
125 void reset_clipping();
126 void clip_box(
double x1,
double y1,
double x2,
double y2);
127 void filling_rule(filling_rule_e filling_rule);
128 void auto_close(
bool flag) { m_auto_close = flag; }
131 template<
class GammaF>
void gamma(
const GammaF& gamma_function)
134 for(i = 0; i < aa_scale; i++)
136 m_gamma[i] = uround(gamma_function(
double(i) / aa_mask) * aa_mask);
141 unsigned apply_gamma(
unsigned cover)
const 143 return m_gamma[cover];
147 void move_to(
int x,
int y);
148 void line_to(
int x,
int y);
149 void move_to_d(
double x,
double y);
150 void line_to_d(
double x,
double y);
151 void close_polygon();
152 void add_vertex(
double x,
double y,
unsigned cmd);
154 void edge(
int x1,
int y1,
int x2,
int y2);
155 void edge_d(
double x1,
double y1,
double x2,
double y2);
158 template<
class VertexSource>
159 void add_path(VertexSource& vs,
unsigned path_id=0)
166 if(m_outline.sorted()) reset();
167 while(!is_stop(cmd = vs.vertex(&x, &y)))
169 add_vertex(x, y, cmd);
174 int min_x()
const {
return m_outline.min_x(); }
175 int min_y()
const {
return m_outline.min_y(); }
176 int max_x()
const {
return m_outline.max_x(); }
177 int max_y()
const {
return m_outline.max_y(); }
181 bool rewind_scanlines();
182 bool navigate_scanline(
int y);
185 AGG_INLINE
unsigned calculate_alpha(
int area)
const 187 int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
189 if(cover < 0) cover = -cover;
190 if(m_filling_rule == fill_even_odd)
195 cover = aa_scale2 - cover;
198 if(cover > aa_mask) cover = aa_mask;
199 return m_gamma[cover];
203 template<
class Scanline>
bool sweep_scanline(Scanline& sl)
207 if(m_scan_y > m_outline.max_y())
return false;
209 unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
210 const cell_aa*
const* cells = m_outline.scanline_cells(m_scan_y);
215 const cell_aa* cur_cell = *cells;
217 int area = cur_cell->area;
220 cover += cur_cell->cover;
226 if(cur_cell->x != x)
break;
227 area += cur_cell->area;
228 cover += cur_cell->cover;
233 alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
236 sl.add_cell(x, alpha);
241 if(num_cells && cur_cell->x > x)
243 alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
246 sl.add_span(x, cur_cell->x - x, alpha);
251 if(sl.num_spans())
break;
255 sl.finalize(m_scan_y);
261 bool hit_test(
int tx,
int ty);
274 int m_gamma[aa_scale];
275 filling_rule_e m_filling_rule;
277 coord_type m_start_x;
278 coord_type m_start_y;
299 m_status = status_initial;
306 m_filling_rule = filling_rule;
312 double x2,
double y2)
315 m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
316 conv_type::upscale(x2), conv_type::upscale(y2));
324 m_clipper.reset_clipping();
331 if(m_status == status_line_to)
333 m_clipper.line_to(m_outline, m_start_x, m_start_y);
334 m_status = status_closed;
342 if(m_outline.sorted()) reset();
343 if(m_auto_close) close_polygon();
344 m_clipper.move_to(m_start_x = conv_type::downscale(x),
345 m_start_y = conv_type::downscale(y));
346 m_status = status_move_to;
353 m_clipper.line_to(m_outline,
354 conv_type::downscale(x),
355 conv_type::downscale(y));
356 m_status = status_line_to;
363 if(m_outline.sorted()) reset();
364 if(m_auto_close) close_polygon();
365 m_clipper.move_to(m_start_x = conv_type::upscale(x),
366 m_start_y = conv_type::upscale(y));
367 m_status = status_move_to;
374 m_clipper.line_to(m_outline,
375 conv_type::upscale(x),
376 conv_type::upscale(y));
377 m_status = status_line_to;
404 if(m_outline.sorted()) reset();
405 m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
406 m_clipper.line_to(m_outline,
407 conv_type::downscale(x2),
408 conv_type::downscale(y2));
409 m_status = status_move_to;
415 double x2,
double y2)
417 if(m_outline.sorted()) reset();
418 m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
419 m_clipper.line_to(m_outline,
420 conv_type::upscale(x2),
421 conv_type::upscale(y2));
422 m_status = status_move_to;
429 if(m_auto_close) close_polygon();
430 m_outline.sort_cells();
437 if(m_auto_close) close_polygon();
438 m_outline.sort_cells();
439 if(m_outline.total_cells() == 0)
443 m_scan_y = m_outline.min_y();
452 if(m_auto_close) close_polygon();
453 m_outline.sort_cells();
454 if(m_outline.total_cells() == 0 ||
455 y < m_outline.min_y() ||
456 y > m_outline.max_y())
468 if(!navigate_scanline(ty))
return false;