29 #ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED 30 #define AGG_RASTERIZER_COMPOUND_AA_INCLUDED 33 #include "agg_rasterizer_cells_aa.h" 34 #include "agg_rasterizer_sl_clip.h" 53 x = std::numeric_limits<int>::max();
54 y = std::numeric_limits<int>::max();
69 return ((
unsigned)ex - (
unsigned)x) | ((unsigned)ey - (
unsigned)y) |
70 ((
unsigned)left - (unsigned)c.left) | ((unsigned)right - (
unsigned)c.right);
100 typedef Clip clip_type;
101 typedef typename Clip::conv_type conv_type;
102 typedef typename Clip::coord_type coord_type;
107 aa_scale = 1 << aa_shift,
108 aa_mask = aa_scale - 1,
109 aa_scale2 = aa_scale * 2,
110 aa_mask2 = aa_scale2 - 1
117 m_filling_rule(fill_non_zero),
118 m_layer_order(layer_direct),
124 m_min_style(std::numeric_limits<int>::max()),
125 m_max_style(std::numeric_limits<int>::min()),
128 m_scan_y(std::numeric_limits<int>::max()),
135 void reset_clipping();
136 void clip_box(
double x1,
double y1,
double x2,
double y2);
137 void filling_rule(filling_rule_e filling_rule);
138 void layer_order(layer_order_e order);
141 void styles(
int left,
int right);
142 void move_to(
int x,
int y);
143 void line_to(
int x,
int y);
144 void move_to_d(
double x,
double y);
145 void line_to_d(
double x,
double y);
146 void add_vertex(
double x,
double y,
unsigned cmd);
148 void edge(
int x1,
int y1,
int x2,
int y2);
149 void edge_d(
double x1,
double y1,
double x2,
double y2);
152 template<
class VertexSource>
153 void add_path(VertexSource& vs,
unsigned path_id=0)
160 if(m_outline.sorted()) reset();
161 while(!is_stop(cmd = vs.vertex(&x, &y)))
163 add_vertex(x, y, cmd);
169 int min_x()
const {
return m_outline.min_x(); }
170 int min_y()
const {
return m_outline.min_y(); }
171 int max_x()
const {
return m_outline.max_x(); }
172 int max_y()
const {
return m_outline.max_y(); }
173 int min_style()
const {
return m_min_style; }
174 int max_style()
const {
return m_max_style; }
178 bool rewind_scanlines();
179 unsigned sweep_styles();
180 int scanline_start()
const {
return m_sl_start; }
181 unsigned scanline_length()
const {
return m_sl_len; }
182 unsigned style(
unsigned style_idx)
const;
184 cover_type* allocate_cover_buffer(
unsigned len);
187 bool navigate_scanline(
int y);
188 bool hit_test(
int tx,
int ty);
191 AGG_INLINE
unsigned calculate_alpha(
int area)
const 193 int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
194 if(cover < 0) cover = -cover;
195 if(m_filling_rule == fill_even_odd)
200 cover = aa_scale2 - cover;
203 if(cover > aa_mask) cover = aa_mask;
210 template<
class Scanline>
bool sweep_scanline(Scanline& sl,
int style_idx)
212 int scan_y = m_scan_y - 1;
213 if(scan_y > m_outline.max_y())
return false;
226 const style_info& st = m_styles[m_ast[style_idx]];
228 unsigned num_cells = st.num_cells;
229 cell_info* cell = &m_cells[st.start_cell];
236 int area = cell->area;
238 cover += cell->cover;
244 alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
245 sl.add_cell(x, alpha);
249 if(num_cells && cell->x > x)
251 alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
254 sl.add_span(x, cell->x - x, alpha);
259 if(sl.num_spans() == 0)
return false;
265 void add_style(
int style_id);
276 filling_rule_e m_filling_rule;
277 layer_order_e m_layer_order;
286 coord_type m_start_x;
287 coord_type m_start_y;
307 m_min_style = std::numeric_limits<int>::max();
308 m_max_style = std::numeric_limits<int>::min();
309 m_scan_y = std::numeric_limits<int>::max();
318 m_filling_rule = filling_rule;
325 m_layer_order = order;
331 double x2,
double y2)
334 m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
335 conv_type::upscale(x2), conv_type::upscale(y2));
343 m_clipper.reset_clipping();
352 cell.left = (int16)left;
353 cell.right = (int16)right;
354 m_outline.style(cell);
355 if(left >= 0 && left < m_min_style) m_min_style = left;
356 if(left >= 0 && left > m_max_style) m_max_style = left;
357 if(right >= 0 && right < m_min_style) m_min_style = right;
358 if(right >= 0 && right > m_max_style) m_max_style = right;
365 if(m_outline.sorted()) reset();
366 m_clipper.move_to(m_start_x = conv_type::downscale(x),
367 m_start_y = conv_type::downscale(y));
374 m_clipper.line_to(m_outline,
375 conv_type::downscale(x),
376 conv_type::downscale(y));
383 if(m_outline.sorted()) reset();
384 m_clipper.move_to(m_start_x = conv_type::upscale(x),
385 m_start_y = conv_type::upscale(y));
392 m_clipper.line_to(m_outline,
393 conv_type::upscale(x),
394 conv_type::upscale(y));
413 m_clipper.line_to(m_outline, m_start_x, m_start_y);
421 if(m_outline.sorted()) reset();
422 m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
423 m_clipper.line_to(m_outline,
424 conv_type::downscale(x2),
425 conv_type::downscale(y2));
431 double x2,
double y2)
433 if(m_outline.sorted()) reset();
434 m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
435 m_clipper.line_to(m_outline,
436 conv_type::upscale(x2),
437 conv_type::upscale(y2));
444 m_outline.sort_cells();
451 m_outline.sort_cells();
452 if(m_outline.total_cells() == 0)
456 if(m_max_style < m_min_style)
460 m_scan_y = m_outline.min_y();
461 m_styles.allocate(m_max_style - m_min_style + 2, 128);
469 if(style_id < 0) style_id = 0;
470 else style_id -= m_min_style - 1;
472 unsigned nbyte = style_id >> 3;
473 unsigned mask = 1 << (style_id & 7);
475 style_info* style = &m_styles[style_id];
476 if((m_asm[nbyte] & mask) == 0)
479 m_asm[nbyte] |= mask;
480 style->start_cell = 0;
481 style->num_cells = 0;
482 style->last_x = std::numeric_limits<int>::min();
494 if(m_scan_y > m_outline.max_y())
return 0;
495 unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
496 const cell_style_aa*
const* cells = m_outline.scanline_cells(m_scan_y);
497 unsigned num_styles = m_max_style - m_min_style + 2;
503 m_cells.allocate(num_cells * 2, 256);
504 m_ast.capacity(num_styles, 64);
505 m_asm.allocate((num_styles + 7) >> 3, 8);
514 style = &m_styles[0];
515 style->start_cell = 0;
516 style->num_cells = 0;
517 style->last_x = std::numeric_limits<int>::min();
519 m_sl_start = cells[0]->x;
520 m_sl_len = cells[num_cells-1]->x - m_sl_start + 1;
523 curr_cell = *cells++;
524 add_style(curr_cell->left);
525 add_style(curr_cell->right);
530 unsigned start_cell = 0;
531 for(i = 0; i < m_ast.size(); i++)
533 style_info& st = m_styles[m_ast[i]];
534 unsigned v = st.start_cell;
535 st.start_cell = start_cell;
539 cells = m_outline.scanline_cells(m_scan_y);
540 num_cells = m_outline.scanline_num_cells(m_scan_y);
544 curr_cell = *cells++;
545 style_id = (curr_cell->left < 0) ? 0 :
546 curr_cell->left - m_min_style + 1;
548 style = &m_styles[style_id];
549 if(curr_cell->x == style->last_x)
551 cell = &m_cells[style->start_cell + style->num_cells - 1];
552 cell->area += curr_cell->area;
553 cell->cover += curr_cell->cover;
557 cell = &m_cells[style->start_cell + style->num_cells];
558 cell->x = curr_cell->x;
559 cell->area = curr_cell->area;
560 cell->cover = curr_cell->cover;
561 style->last_x = curr_cell->x;
565 style_id = (curr_cell->right < 0) ? 0 :
566 curr_cell->right - m_min_style + 1;
568 style = &m_styles[style_id];
569 if(curr_cell->x == style->last_x)
571 cell = &m_cells[style->start_cell + style->num_cells - 1];
572 cell->area -= curr_cell->area;
573 cell->cover -= curr_cell->cover;
577 cell = &m_cells[style->start_cell + style->num_cells];
578 cell->x = curr_cell->x;
579 cell->area = -curr_cell->area;
580 cell->cover = -curr_cell->cover;
581 style->last_x = curr_cell->x;
586 if(m_ast.size() > 1)
break;
591 if(m_layer_order != layer_unsorted)
594 if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater);
595 else quick_sort(ra, unsigned_less);
598 return m_ast.size() - 1;
607 return m_ast[style_idx + 1] + m_min_style - 1;
614 m_outline.sort_cells();
615 if(m_outline.total_cells() == 0)
619 if(m_max_style < m_min_style)
623 if(y < m_outline.min_y() || y > m_outline.max_y())
628 m_styles.allocate(m_max_style - m_min_style + 2, 128);
636 if(!navigate_scanline(ty))
641 unsigned num_styles = sweep_styles();
648 sweep_scanline(sl, -1);
656 m_cover_buf.allocate(len, 256);
657 return &m_cover_buf[0];