📄 agg_rasterizer_scanline_aa.cpp.svn-base
字号:
//----------------------------------------------------------------------------// Anti-Grain Geometry - Version 2.3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)//// Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied// warranty, and with no claim as to its suitability for any purpose.//// The author gratefully acknowleges the support of David Turner, // Robert Wilhelm, and Werner Lemberg - the authors of the FreeType // libray - in producing this work. See http://www.freetype.org for details.////----------------------------------------------------------------------------// Contact: mcseem@antigrain.com// mcseemagg@yahoo.com// http://www.antigrain.com//----------------------------------------------------------------------------//// Class outline_aa - implementation.//// Initially the rendering algorithm was designed by David Turner and the // other authors of the FreeType library - see the above notice. I nearly // created a similar renderer, but still I was far from David's work. // I completely redesigned the original code and adapted it for Anti-Grain // ideas. Two functions - render_line and render_hline are the core of // the algorithm - they calculate the exact coverage of each pixel cell// of the polygon. I left these functions almost as is, because there's // no way to improve the perfection - hats off to David and his group!//// All other code is very different from the original. // //----------------------------------------------------------------------------#include <string.h>#include "agg_rasterizer_scanline_aa.h"namespace agg{ //------------------------------------------------------------------------ AGG_INLINE void cell_aa::set_cover(int c, int a) { cover = c; area = a; } //------------------------------------------------------------------------ AGG_INLINE void cell_aa::add_cover(int c, int a) { cover += c; area += a; } //------------------------------------------------------------------------ AGG_INLINE void cell_aa::set_coord(int cx, int cy) { x = int16(cx); y = int16(cy); packed_coord = (cy << 16) + cx; } //------------------------------------------------------------------------ AGG_INLINE void cell_aa::set(int cx, int cy, int c, int a) { x = int16(cx); y = int16(cy); packed_coord = (cy << 16) + cx; cover = c; area = a; } //------------------------------------------------------------------------ outline_aa::~outline_aa() { delete [] m_sorted_cells; if(m_num_blocks) { cell_aa** ptr = m_cells + m_num_blocks - 1; while(m_num_blocks--) { delete [] *ptr; ptr--; } delete [] m_cells; } } //------------------------------------------------------------------------ outline_aa::outline_aa() : m_num_blocks(0), m_max_blocks(0), m_cur_block(0), m_num_cells(0), m_cells(0), m_cur_cell_ptr(0), m_sorted_cells(0), m_sorted_size(0), m_cur_x(0), m_cur_y(0), m_min_x(0x7FFFFFFF), m_min_y(0x7FFFFFFF), m_max_x(-0x7FFFFFFF), m_max_y(-0x7FFFFFFF), m_sorted(false) { m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0); } //------------------------------------------------------------------------ void outline_aa::reset() { m_num_cells = 0; m_cur_block = 0; m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0); m_sorted = false; m_min_x = 0x7FFFFFFF; m_min_y = 0x7FFFFFFF; m_max_x = -0x7FFFFFFF; m_max_y = -0x7FFFFFFF; } //------------------------------------------------------------------------ void outline_aa::allocate_block() { if(m_cur_block >= m_num_blocks) { if(m_num_blocks >= m_max_blocks) { cell_aa** new_cells = new cell_aa* [m_max_blocks + cell_block_pool]; if(m_cells) { memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_aa*)); delete [] m_cells; } m_cells = new_cells; m_max_blocks += cell_block_pool; } m_cells[m_num_blocks++] = new cell_aa [unsigned(cell_block_size)]; } m_cur_cell_ptr = m_cells[m_cur_block++]; } //------------------------------------------------------------------------ AGG_INLINE void outline_aa::add_cur_cell() { if(m_cur_cell.area | m_cur_cell.cover) { if((m_num_cells & cell_block_mask) == 0) { if(m_num_blocks >= cell_block_limit) return; allocate_block(); } *m_cur_cell_ptr++ = m_cur_cell; ++m_num_cells; if(m_cur_cell.x < m_min_x) m_min_x = m_cur_cell.x; if(m_cur_cell.x > m_max_x) m_max_x = m_cur_cell.x; } } //------------------------------------------------------------------------ AGG_INLINE void outline_aa::set_cur_cell(int x, int y) { if(m_cur_cell.packed_coord != (y << 16) + x) { add_cur_cell(); m_cur_cell.set(x, y, 0, 0); } } //------------------------------------------------------------------------ AGG_INLINE void outline_aa::render_hline(int ey, int x1, int y1, int x2, int y2) { int ex1 = x1 >> poly_base_shift; int ex2 = x2 >> poly_base_shift; int fx1 = x1 & poly_base_mask; int fx2 = x2 & poly_base_mask; int delta, p, first, dx; int incr, lift, mod, rem; //trivial case. Happens often if(y1 == y2) { set_cur_cell(ex2, ey); return; } //everything is located in a single cell. That is easy! if(ex1 == ex2) { delta = y2 - y1; m_cur_cell.add_cover(delta, (fx1 + fx2) * delta); return; } //ok, we'll have to render a run of adjacent cells on the same //hline... p = (poly_base_size - fx1) * (y2 - y1); first = poly_base_size; incr = 1; dx = x2 - x1; if(dx < 0) { p = fx1 * (y2 - y1); first = 0; incr = -1; dx = -dx; } delta = p / dx; mod = p % dx; if(mod < 0) { delta--; mod += dx; } m_cur_cell.add_cover(delta, (fx1 + first) * delta); ex1 += incr; set_cur_cell(ex1, ey); y1 += delta; if(ex1 != ex2) { p = poly_base_size * (y2 - y1 + delta); lift = p / dx; rem = p % dx; if (rem < 0) { lift--; rem += dx; } mod -= dx; while (ex1 != ex2) { delta = lift; mod += rem; if(mod >= 0) { mod -= dx; delta++; } m_cur_cell.add_cover(delta, (poly_base_size) * delta); y1 += delta; ex1 += incr; set_cur_cell(ex1, ey); } } delta = y2 - y1; m_cur_cell.add_cover(delta, (fx2 + poly_base_size - first) * delta); } //------------------------------------------------------------------------ void outline_aa::render_line(int x1, int y1, int x2, int y2) { int ey1 = y1 >> poly_base_shift; int ey2 = y2 >> poly_base_shift; int fy1 = y1 & poly_base_mask; int fy2 = y2 & poly_base_mask; int dx, dy, x_from, x_to; int p, rem, mod, lift, delta, first, incr; dx = x2 - x1; dy = y2 - y1; //everything is on a single hline if(ey1 == ey2) { render_hline(ey1, x1, fy1, x2, fy2); return; } //Vertical line - we have to calculate start and end cells, //and then - the common values of the area and coverage for //all cells of the line. We know exactly there's only one //cell, so, we don't have to call render_hline(). incr = 1; if(dx == 0) { int ex = x1 >> poly_base_shift; int two_fx = (x1 - (ex << poly_base_shift)) << 1; int area; first = poly_base_size; if(dy < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -