29 #ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED 30 #define AGG_RASTERIZER_CELLS_AA_INCLUDED 36 #include "agg_array.h" 47 enum cell_block_scale_e
49 cell_block_shift = 12,
50 cell_block_size = 1 << cell_block_shift,
51 cell_block_mask = cell_block_size - 1,
62 typedef Cell cell_type;
69 void style(
const cell_type& style_cell);
70 void line(
int x1,
int y1,
int x2,
int y2);
72 int min_x()
const {
return m_min_x; }
73 int min_y()
const {
return m_min_y; }
74 int max_x()
const {
return m_max_x; }
75 int max_y()
const {
return m_max_y; }
79 unsigned total_cells()
const 84 unsigned scanline_num_cells(
unsigned y)
const 86 return m_sorted_y[y - m_min_y].num;
89 const cell_type*
const* scanline_cells(
unsigned y)
const 91 return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start;
94 bool sorted()
const {
return m_sorted; }
98 const self_type& operator = (
const self_type&);
100 void set_curr_cell(
int x,
int y);
101 void add_curr_cell();
102 void render_hline(
int ey,
int x1,
int y1,
int x2,
int y2);
103 void allocate_block();
106 unsigned m_num_blocks;
107 unsigned m_max_blocks;
108 unsigned m_curr_block;
109 unsigned m_num_cells;
110 unsigned m_cell_block_limit;
112 cell_type* m_curr_cell_ptr;
115 cell_type m_curr_cell;
116 cell_type m_style_cell;
133 cell_type** ptr = m_cells + m_num_blocks - 1;
134 while(m_num_blocks--)
150 m_cell_block_limit(cell_block_limit),
155 m_min_x(std::numeric_limits<int>::max()),
156 m_min_y(std::numeric_limits<int>::max()),
157 m_max_x(std::numeric_limits<int>::min()),
158 m_max_y(std::numeric_limits<int>::min()),
161 m_style_cell.initial();
162 m_curr_cell.initial();
171 m_curr_cell.initial();
172 m_style_cell.initial();
174 m_min_x = std::numeric_limits<int>::max();
175 m_min_y = std::numeric_limits<int>::max();
176 m_max_x = std::numeric_limits<int>::min();
177 m_max_y = std::numeric_limits<int>::min();
184 if(m_curr_cell.area | m_curr_cell.cover)
186 if((m_num_cells & cell_block_mask) == 0)
188 if(m_num_blocks >= m_cell_block_limit)
return;
191 *m_curr_cell_ptr++ = m_curr_cell;
200 if(m_curr_cell.not_equal(x, y, m_style_cell))
203 m_curr_cell.style(m_style_cell);
206 m_curr_cell.cover = 0;
207 m_curr_cell.area = 0;
217 int ex1 = x1 >> poly_subpixel_shift;
218 int ex2 = x2 >> poly_subpixel_shift;
219 int fx1 = x1 & poly_subpixel_mask;
220 int fx2 = x2 & poly_subpixel_mask;
224 int incr, lift, mod, rem;
229 set_curr_cell(ex2, ey);
237 m_curr_cell.cover += delta;
238 m_curr_cell.area += (fx1 + fx2) * delta;
244 p = (poly_subpixel_scale - fx1) * (y2 - y1);
245 first = poly_subpixel_scale;
248 dx = (
long long)x2 - (
long long)x1;
258 delta = (int)(p / dx);
267 m_curr_cell.cover += delta;
268 m_curr_cell.area += (fx1 + first) * delta;
271 set_curr_cell(ex1, ey);
276 p = poly_subpixel_scale * (y2 - y1 + delta);
277 lift = (int)(p / dx);
298 m_curr_cell.cover += delta;
299 m_curr_cell.area += poly_subpixel_scale * delta;
302 set_curr_cell(ex1, ey);
306 m_curr_cell.cover += delta;
307 m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta;
314 m_style_cell.style(style_cell);
321 enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };
323 long long dx = (
long long)x2 - (
long long)x1;
325 if(dx >= dx_limit || dx <= -dx_limit)
327 int cx = (int)(((
long long)x1 + (
long long)x2) >> 1);
328 int cy = (int)(((
long long)y1 + (
long long)y2) >> 1);
329 line(x1, y1, cx, cy);
330 line(cx, cy, x2, y2);
333 long long dy = (
long long)y2 - (
long long)y1;
334 int ex1 = x1 >> poly_subpixel_shift;
335 int ex2 = x2 >> poly_subpixel_shift;
336 int ey1 = y1 >> poly_subpixel_shift;
337 int ey2 = y2 >> poly_subpixel_shift;
338 int fy1 = y1 & poly_subpixel_mask;
339 int fy2 = y2 & poly_subpixel_mask;
342 int rem, mod, lift, delta, first, incr;
345 if(ex1 < m_min_x) m_min_x = ex1;
346 if(ex1 > m_max_x) m_max_x = ex1;
347 if(ey1 < m_min_y) m_min_y = ey1;
348 if(ey1 > m_max_y) m_max_y = ey1;
349 if(ex2 < m_min_x) m_min_x = ex2;
350 if(ex2 > m_max_x) m_max_x = ex2;
351 if(ey2 < m_min_y) m_min_y = ey2;
352 if(ey2 > m_max_y) m_max_y = ey2;
354 set_curr_cell(ex1, ey1);
359 render_hline(ey1, x1, fy1, x2, fy2);
370 int ex = x1 >> poly_subpixel_shift;
371 int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1;
374 first = poly_subpixel_scale;
385 m_curr_cell.cover += delta;
386 m_curr_cell.area += two_fx * delta;
389 set_curr_cell(ex, ey1);
391 delta = first + first - poly_subpixel_scale;
392 area = two_fx * delta;
396 m_curr_cell.cover = delta;
397 m_curr_cell.area = area;
399 set_curr_cell(ex, ey1);
402 delta = fy2 - poly_subpixel_scale + first;
403 m_curr_cell.cover += delta;
404 m_curr_cell.area += two_fx * delta;
409 p = (poly_subpixel_scale - fy1) * dx;
410 first = poly_subpixel_scale;
420 delta = (int)(p / dy);
430 render_hline(ey1, x1, fy1, x_from, first);
433 set_curr_cell(x_from >> poly_subpixel_shift, ey1);
437 p = poly_subpixel_scale * dx;
438 lift = (int)(p / dy);
458 x_to = x_from + delta;
459 render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first);
463 set_curr_cell(x_from >> poly_subpixel_shift, ey1);
466 render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2);
473 if(m_curr_block >= m_num_blocks)
475 if(m_num_blocks >= m_max_blocks)
477 cell_type** new_cells =
483 std::memcpy(new_cells, m_cells, m_max_blocks *
sizeof(cell_type*));
487 m_max_blocks += cell_block_pool;
490 m_cells[m_num_blocks++] =
494 m_curr_cell_ptr = m_cells[m_curr_block++];
500 template <
class T>
static AGG_INLINE
void swap_cells(T* a, T* b)
517 void qsort_cells(Cell** start,
unsigned num)
530 int len = int(limit - base);
536 if(len > qsort_threshold)
539 pivot = base + len / 2;
540 swap_cells(base, pivot);
546 if((*j)->x < (*i)->x)
551 if((*base)->x < (*i)->x)
556 if((*j)->x < (*base)->x)
564 do i++;
while( (*i)->x < x );
565 do j--;
while( x < (*j)->x );
578 if(j - base > limit - i)
598 for(; i < limit; j = i, i++)
600 for(; j[1]->x < (*j)->x; j--)
602 swap_cells(j + 1, j);
632 m_curr_cell.x = std::numeric_limits<int>::max();
633 m_curr_cell.y = std::numeric_limits<int>::max();
634 m_curr_cell.cover = 0;
635 m_curr_cell.area = 0;
637 if(m_num_cells == 0)
return;
652 m_sorted_cells.allocate(m_num_cells, 16);
655 m_sorted_y.allocate(m_max_y - m_min_y + 1, 16);
659 cell_type** block_ptr = m_cells;
661 unsigned nb = m_num_cells;
665 cell_ptr = *block_ptr++;
666 i = (nb > cell_block_size) ?
unsigned(cell_block_size) : nb;
670 m_sorted_y[cell_ptr->y - m_min_y].start++;
677 for(i = 0; i < m_sorted_y.size(); i++)
679 unsigned v = m_sorted_y[i].start;
680 m_sorted_y[i].start = start;
689 cell_ptr = *block_ptr++;
690 i = (nb > cell_block_size) ?
unsigned(cell_block_size) : nb;
694 sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
695 m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
702 for(i = 0; i < m_sorted_y.size(); i++)
704 const sorted_y& curr_y = m_sorted_y[i];
707 qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num);
721 void reset_spans() {}
722 void finalize(
int) {}
723 void add_cell(
int x,
int)
725 if(m_x == x) m_hit =
true;
727 void add_span(
int x,
int len,
int)
729 if(m_x >= x && m_x < x+len) m_hit =
true;
731 unsigned num_spans()
const {
return 1; }
732 bool hit()
const {
return m_hit; }