1.upgrade to latest agg2.4

2.added default PointSymbolizer in load_map.cpp
This commit is contained in:
Artem Pavlenko 2006-11-09 23:44:34 +00:00
parent e7bab0b8c8
commit bf297ec3ca
79 changed files with 4130 additions and 2262 deletions

View file

@ -57,7 +57,7 @@ namespace agg
};
alpha_mask_u8() : m_rbuf(0) {}
alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
@ -70,7 +70,7 @@ namespace agg
{
if(x >= 0 && y >= 0 &&
x < (int)m_rbuf->width() &&
y <= (int)m_rbuf->height())
y < (int)m_rbuf->height())
{
return (cover_type)m_mask_function.calculate(
m_rbuf->row_ptr(y) + x * Step + Offset);
@ -83,7 +83,7 @@ namespace agg
{
if(x >= 0 && y >= 0 &&
x < (int)m_rbuf->width() &&
y <= (int)m_rbuf->height())
y < (int)m_rbuf->height())
{
return (cover_type)((cover_full + val *
m_mask_function.calculate(
@ -361,7 +361,7 @@ namespace agg
};
amask_no_clip_u8() : m_rbuf(0) {}
amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }

View file

@ -109,20 +109,27 @@ namespace agg
typedef T value_type;
typedef pod_array<T> self_type;
~pod_array() { delete [] m_array; }
~pod_array() { pod_allocator<T>::deallocate(m_array, m_size); }
pod_array() : m_array(0), m_size(0) {}
pod_array(unsigned size) : m_array(new T[size]), m_size(size) {}
pod_array(unsigned size) :
m_array(pod_allocator<T>::allocate(size)),
m_size(size)
{}
pod_array(const self_type& v) :
m_array(new T[v.m_size]), m_size(v.m_size)
m_array(pod_allocator<T>::allocate(v.m_size)),
m_size(v.m_size)
{
memcpy(m_array, v.m_array, sizeof(T) * m_size);
}
void resize(unsigned size)
{
if(size != m_size)
{
delete [] m_array;
m_array = new T[m_size = size];
pod_allocator<T>::deallocate(m_array, m_size);
m_array = pod_allocator<T>::allocate(m_size = size);
}
}
const self_type& operator = (const self_type& v)
@ -157,7 +164,7 @@ namespace agg
public:
typedef T value_type;
~pod_vector() { delete [] m_array; }
~pod_vector() { pod_allocator<T>::deallocate(m_array, m_capacity); }
pod_vector() : m_size(0), m_capacity(0), m_array(0) {}
pod_vector(unsigned cap, unsigned extra_tail=0);
@ -215,9 +222,9 @@ namespace agg
m_size = 0;
if(cap > m_capacity)
{
delete [] m_array;
pod_allocator<T>::deallocate(m_array, m_capacity);
m_capacity = cap + extra_tail;
m_array = m_capacity ? new T [m_capacity] : 0;
m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0;
}
}
@ -238,9 +245,9 @@ namespace agg
{
if(new_size > m_capacity)
{
T* data = new T[new_size];
T* data = pod_allocator<T>::allocate(new_size);
memcpy(data, m_array, m_size * sizeof(T));
delete [] m_array;
pod_allocator<T>::deallocate(m_array, m_capacity);
m_array = data;
}
}
@ -252,13 +259,15 @@ namespace agg
//------------------------------------------------------------------------
template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) :
m_size(0), m_capacity(cap + extra_tail), m_array(new T[m_capacity]) {}
m_size(0),
m_capacity(cap + extra_tail),
m_array(pod_allocator<T>::allocate(m_capacity)) {}
//------------------------------------------------------------------------
template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) :
m_size(v.m_size),
m_capacity(v.m_capacity),
m_array(v.m_capacity ? new T [v.m_capacity] : 0)
m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0)
{
memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
}
@ -509,11 +518,11 @@ namespace agg
T** blk = m_blocks + m_num_blocks - 1;
while(m_num_blocks--)
{
delete [] *blk;
pod_allocator<T>::deallocate(*blk, block_size);
--blk;
}
delete [] m_blocks;
}
pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
}
@ -526,7 +535,13 @@ namespace agg
unsigned nb = (size + block_mask) >> block_shift;
while(m_num_blocks > nb)
{
delete [] m_blocks[--m_num_blocks];
pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size);
}
if(m_num_blocks == 0)
{
pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
m_blocks = 0;
m_max_blocks = 0;
}
m_size = size;
}
@ -562,13 +577,15 @@ namespace agg
m_size(v.m_size),
m_num_blocks(v.m_num_blocks),
m_max_blocks(v.m_max_blocks),
m_blocks(v.m_max_blocks ? new T* [v.m_max_blocks] : 0),
m_blocks(v.m_max_blocks ?
pod_allocator<T*>::allocate(v.m_max_blocks) :
0),
m_block_ptr_inc(v.m_block_ptr_inc)
{
unsigned i;
for(i = 0; i < v.m_num_blocks; ++i)
{
m_blocks[i] = new T [block_size];
m_blocks[i] = pod_allocator<T>::allocate(block_size);
memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
}
}
@ -599,7 +616,7 @@ namespace agg
{
if(nb >= m_max_blocks)
{
T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc];
T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc);
if(m_blocks)
{
@ -607,12 +624,12 @@ namespace agg
m_blocks,
m_num_blocks * sizeof(T*));
delete [] m_blocks;
pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
}
m_blocks = new_blocks;
m_max_blocks += m_block_ptr_inc;
}
m_blocks[nb] = new T [block_size];
m_blocks[nb] = pod_allocator<T>::allocate(block_size);
m_num_blocks++;
}
@ -753,7 +770,7 @@ namespace agg
}
//-----------------------------------------------------------pod_allocator
//---------------------------------------------------------block_allocator
// Allocator for arbitrary POD data. Most usable in different cache
// systems for efficient memory allocations.
// Memory is allocated with blocks of fixed size ("block_size" in
@ -761,20 +778,26 @@ namespace agg
// creates a new block of the required size. However, the most efficient
// use is when the average reqired size is much less than the block size.
//------------------------------------------------------------------------
class pod_allocator
class block_allocator
{
struct block_type
{
int8u* data;
unsigned size;
};
public:
void remove_all()
{
if(m_num_blocks)
{
int8u** blk = m_blocks + m_num_blocks - 1;
block_type* blk = m_blocks + m_num_blocks - 1;
while(m_num_blocks--)
{
delete [] *blk;
pod_allocator<int8u>::deallocate(blk->data, blk->size);
--blk;
}
delete [] m_blocks;
pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
}
m_num_blocks = 0;
m_max_blocks = 0;
@ -783,12 +806,12 @@ namespace agg
m_rest = 0;
}
~pod_allocator()
~block_allocator()
{
remove_all();
}
pod_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
m_block_size(block_size),
m_block_ptr_inc(block_ptr_inc),
m_num_blocks(0),
@ -808,7 +831,9 @@ namespace agg
int8u* ptr = m_buf_ptr;
if(alignment > 1)
{
unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment;
unsigned align =
(alignment - unsigned((size_t)ptr) % alignment) % alignment;
size += align;
ptr += align;
if(size <= m_rest)
@ -835,20 +860,25 @@ namespace agg
if(size < m_block_size) size = m_block_size;
if(m_num_blocks >= m_max_blocks)
{
int8u** new_blocks = new int8u* [m_max_blocks + m_block_ptr_inc];
block_type* new_blocks =
pod_allocator<block_type>::allocate(m_max_blocks + m_block_ptr_inc);
if(m_blocks)
{
memcpy(new_blocks,
m_blocks,
m_num_blocks * sizeof(int8u*));
delete [] m_blocks;
m_num_blocks * sizeof(block_type));
pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
}
m_blocks = new_blocks;
m_max_blocks += m_block_ptr_inc;
}
m_blocks[m_num_blocks] = m_buf_ptr = new int8u [size];
m_blocks[m_num_blocks].size = size;
m_blocks[m_num_blocks].data =
m_buf_ptr =
pod_allocator<int8u>::allocate(size);
m_num_blocks++;
m_rest = size;
}
@ -857,7 +887,7 @@ namespace agg
unsigned m_block_ptr_inc;
unsigned m_num_blocks;
unsigned m_max_blocks;
int8u** m_blocks;
block_type* m_blocks;
int8u* m_buf_ptr;
unsigned m_rest;
};
@ -1014,7 +1044,6 @@ namespace agg
return j;
}
//--------------------------------------------------------invert_container
template<class Array> void invert_container(Array& arr)
{
@ -1026,7 +1055,6 @@ namespace agg
}
}
//------------------------------------------------------binary_search_pos
template<class Array, class Value, class Less>
unsigned binary_search_pos(const Array& arr, const Value& val, Less less)
@ -1052,6 +1080,40 @@ namespace agg
return end;
}
//----------------------------------------------------------range_adaptor
template<class Array> class range_adaptor
{
public:
typedef typename Array::value_type value_type;
range_adaptor(Array& array, unsigned start, unsigned size) :
m_array(array), m_start(start), m_size(size)
{}
unsigned size() const { return m_size; }
const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; }
value_type& operator [] (unsigned i) { return m_array[m_start + i]; }
const value_type& at(unsigned i) const { return m_array[m_start + i]; }
value_type& at(unsigned i) { return m_array[m_start + i]; }
value_type value_at(unsigned i) const { return m_array[m_start + i]; }
private:
Array& m_array;
unsigned m_start;
unsigned m_size;
};
//---------------------------------------------------------------int_less
inline bool int_less(int a, int b) { return a < b; }
//------------------------------------------------------------int_greater
inline bool int_greater(int a, int b) { return a > b; }
//----------------------------------------------------------unsigned_less
inline bool unsigned_less(unsigned a, unsigned b) { return a < b; }
//-------------------------------------------------------unsigned_greater
inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; }
}
#endif

View file

@ -19,6 +19,43 @@
#include <math.h>
#include "agg_config.h"
//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
#ifdef AGG_CUSTOM_ALLOCATOR
#include "agg_allocator.h"
#else
namespace agg
{
// The policy of all AGG containers and memory allocation strategy
// in general is that no allocated data requires explicit construction.
// It means that the allocator can be really simple; you can even
// replace new/delete to malloc/free. The constructors and destructors
// won't be called in this case, however everything will remain working.
// The second argument of deallocate() is the size of the allocated
// block. You can use this information if you wish.
//------------------------------------------------------------pod_allocator
template<class T> struct pod_allocator
{
static T* allocate(unsigned num) { return new T [num]; }
static void deallocate(T* ptr, unsigned) { delete [] ptr; }
};
// Single object allocator. It's also can be replaced with your custom
// allocator. The difference is that it can only allocate a single
// object and the constructor and destructor must be called.
// In AGG there is no need to allocate an array of objects with
// calling their constructors (only single ones). So that, if you
// replace these new/delete to malloc/free make sure that the in-place
// new is called and take care of calling the destructor too.
//------------------------------------------------------------obj_allocator
template<class T> struct obj_allocator
{
static T* allocate() { return new T; }
static void deallocate(T* ptr) { delete ptr; }
};
}
#endif
//-------------------------------------------------------- Default basic types
//
// If the compiler has different capacity of the basic types you can redefine
@ -93,15 +130,17 @@ namespace agg
#pragma warning(disable : 4035) //Disable warning "no return value"
AGG_INLINE int iround(double v) //-------iround
{
int t;
__asm fld qword ptr [v]
__asm fistp dword ptr [ebp-8]
__asm mov eax, dword ptr [ebp-8]
__asm fistp dword ptr [t]
__asm mov eax, dword ptr [t]
}
AGG_INLINE unsigned uround(double v) //-------uround
{
unsigned t;
__asm fld qword ptr [v]
__asm fistp dword ptr [ebp-8]
__asm mov eax, dword ptr [ebp-8]
__asm fistp dword ptr [t]
__asm mov eax, dword ptr [t]
}
#pragma warning(pop)
AGG_INLINE unsigned ufloor(double v) //-------ufloor
@ -218,16 +257,19 @@ namespace agg
//----------------------------------------------------------------rect_base
template<class T> struct rect_base
{
typedef T value_type;
typedef rect_base<T> self_type;
T x1;
T y1;
T x2;
T y2;
T x1, y1, x2, y2;
rect_base() {}
rect_base(T x1_, T y1_, T x2_, T y2_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
void init(T x1_, T y1_, T x2_, T y2_)
{
x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
}
const self_type& normalize()
{
T t;
@ -249,6 +291,11 @@ namespace agg
{
return x1 <= x2 && y1 <= y2;
}
bool hit_test(T x, T y) const
{
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
}
};
//-----------------------------------------------------intersect_rectangles
@ -451,6 +498,31 @@ namespace agg
typedef vertex_base<float> vertex_f; //-----vertex_f
typedef vertex_base<double> vertex_d; //-----vertex_d
//----------------------------------------------------------------row_info
template<class T> struct row_info
{
int x1, x2;
T* ptr;
row_info() {}
row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
};
//----------------------------------------------------------const_row_info
template<class T> struct const_row_info
{
int x1, x2;
const T* ptr;
const_row_info() {}
const_row_info(int x1_, int x2_, const T* ptr_) :
x1(x1_), x2(x2_), ptr(ptr_) {}
};
//------------------------------------------------------------is_equal_eps
template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
{
return fabs(v1 - v2) <= double(epsilon);
}
}

View file

@ -20,7 +20,7 @@
#ifndef AGG_BSPLINE_INCLUDED
#define AGG_BSPLINE_INCLUDED
#include "agg_basics.h"
#include "agg_array.h"
namespace agg
{
@ -40,7 +40,6 @@ namespace agg
class bspline
{
public:
~bspline();
bspline();
bspline(int num);
bspline(int num, const double* x, const double* y);
@ -67,7 +66,7 @@ namespace agg
int m_num;
double* m_x;
double* m_y;
double* m_am;
pod_array<double> m_am;
mutable int m_last_idx;
};

View file

@ -148,7 +148,7 @@ namespace agg
return *this;
}
calc_type v_ = (calc_type(v) * base_mask) / a;
v = value_type((v_ > base_mask) ? base_mask : v_);
v = value_type((v_ > base_mask) ? (value_type)base_mask : v_);
return *this;
}
@ -162,6 +162,31 @@ namespace agg
return ret;
}
//--------------------------------------------------------------------
AGG_INLINE void add(const self_type& c, unsigned cover)
{
calc_type cv, ca;
if(cover == cover_mask)
{
if(c.a == base_mask)
{
*this = c;
}
else
{
cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
}
}
else
{
cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
}
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); }
};
@ -324,6 +349,31 @@ namespace agg
return ret;
}
//--------------------------------------------------------------------
AGG_INLINE void add(const self_type& c, unsigned cover)
{
calc_type cv, ca;
if(cover == cover_mask)
{
if(c.a == base_mask)
{
*this = c;
}
else
{
cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
}
}
else
{
cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
}
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); }
};

View file

@ -443,32 +443,43 @@ namespace agg
}
//-----------------------------------------------------------rgb8_packed
//-------------------------------------------------------------rgb8_packed
inline rgba8 rgb8_packed(unsigned v)
{
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
}
//-----------------------------------------------------------bgr8_packed
//-------------------------------------------------------------bgr8_packed
inline rgba8 bgr8_packed(unsigned v)
{
return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
}
//----------------------------------------------------------argb8_packed
//------------------------------------------------------------argb8_packed
inline rgba8 argb8_packed(unsigned v)
{
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
}
//---------------------------------------------------------rgba8_gamma_dir
template<class GammaLUT>
rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma)
{
return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
}
//---------------------------------------------------------rgba8_gamma_inv
template<class GammaLUT>
rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma)
{
return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
}
//=================================================================rgba16
//==================================================================rgba16
struct rgba16
{
typedef int16u value_type;
@ -709,6 +720,22 @@ namespace agg
return rgba16(c,a).premultiply();
}
//------------------------------------------------------rgba16_gamma_dir
template<class GammaLUT>
rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma)
{
return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
}
//------------------------------------------------------rgba16_gamma_inv
template<class GammaLUT>
rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma)
{
return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
}
}

View file

@ -1,7 +1,10 @@
#ifndef AGG_CONFIG_INCLUDED
#define AGG_CONFIG_INCLUDED
// This file can be used to redefine the default basic types such as:
// This file can be used to redefine certain data types.
//---------------------------------------
// 1. Default basic types such as:
//
// AGG_INT8
// AGG_INT8U
@ -23,4 +26,20 @@
// but it won't result any crash and the rest of the library will remain
// fully functional.
//---------------------------------------
// 2. Default rendering_buffer type. Can be:
//
// Provides faster access for massive pixel operations,
// such as blur, image filtering:
// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
//
// Provides cheaper creation and destruction (no mem allocs):
#define AGG_RENDERING_BUFFER row_accessor<int8u>
//
// You can still use both of them simultaneouslyin your applications
// This #define is used only for default rendering_buffer type,
// in short hand typedefs like pixfmt_rgba32.
#endif

View file

@ -45,12 +45,11 @@ namespace agg
};
public:
conv_adaptor_vcgen(VertexSource& source) :
explicit conv_adaptor_vcgen(VertexSource& source) :
m_source(&source),
m_status(initial)
{}
void set_source(VertexSource& source) { m_source = &source; }
void attach(VertexSource& source) { m_source = &source; }
Generator& generator() { return m_generator; }
const Generator& generator() const { return m_generator; }

View file

@ -25,9 +25,8 @@ namespace agg
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
{
public:
conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
void set_source(VertexSource& source) { m_source = &source; }
explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
void attach(VertexSource& source) { m_source = &source; }
VPGen& vpgen() { return m_vpgen; }
const VPGen& vpgen() const { return m_vpgen; }

View file

@ -25,9 +25,8 @@ namespace agg
template<class VertexSource> class conv_close_polygon
{
public:
conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
void set_source(VertexSource& source) { m_source = &source; }
explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);

View file

@ -28,9 +28,8 @@ namespace agg
public:
conv_concat(VS1& source1, VS2& source2) :
m_source1(&source1), m_source2(&source2), m_status(2) {}
void set_source1(VS1& source) { m_source1 = &source; }
void set_source2(VS2& source) { m_source2 = &source; }
void attach1(VS1& source) { m_source1 = &source; }
void attach2(VS2& source) { m_source2 = &source; }
void rewind(unsigned path_id)

View file

@ -60,10 +60,9 @@ namespace agg
typedef Curve4 curve4_type;
typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
conv_curve(VertexSource& source) :
explicit conv_curve(VertexSource& source) :
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
void set_source(VertexSource& source) { m_source = &source; }
void attach(VertexSource& source) { m_source = &source; }
void approximation_method(curve_approximation_method_e v)
{

View file

@ -89,8 +89,8 @@ namespace agg
memset(&m_result, 0, sizeof(m_result));
}
void set_source1(VSA& source) { m_src_a = &source; }
void set_source2(VSB& source) { m_src_b = &source; }
void attach1(VSA& source) { m_src_a = &source; }
void attach2(VSB& source) { m_src_b = &source; }
void operation(gpc_op_e v) { m_operation = v; }
@ -191,10 +191,10 @@ namespace agg
int i;
for(i = 0; i < p.num_contours; i++)
{
delete [] p.contour[i].vertex;
pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex,
p.contour[i].num_vertices);
}
delete [] p.hole;
delete [] p.contour;
pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
memset(&p, 0, sizeof(gpc_polygon));
}
@ -260,7 +260,7 @@ namespace agg
// TO DO: Clarify the "holes"
//if(is_cw(orientation)) h.hole_flag = 1;
h.vertices = new gpc_vertex [h.num_vertices];
h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices);
gpc_vertex* d = h.vertices;
int i;
for(i = 0; i < h.num_vertices; i++)
@ -288,19 +288,14 @@ namespace agg
{
p.num_contours = m_contour_accumulator.size();
// TO DO: Clarify the "holes"
//p.hole = new int[p.num_contours];
p.hole = 0;
p.contour = new gpc_vertex_list[p.num_contours];
p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
int i;
//int* ph = p.hole;
gpc_vertex_list* pv = p.contour;
for(i = 0; i < p.num_contours; i++)
{
const contour_header_type& h = m_contour_accumulator[i];
// *ph++ = h.hole_flag;
pv->num_vertices = h.num_vertices;
pv->vertex = h.vertices;
++pv;

View file

@ -31,8 +31,7 @@ namespace agg
public:
conv_transform(VertexSource& source, const Transformer& tr) :
m_source(&source), m_trans(&tr) {}
void set_source(VertexSource& source) { m_source = &source; }
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id)
{

View file

@ -24,9 +24,8 @@ namespace agg
template<class VertexSource> class conv_unclose_polygon
{
public:
conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
void set_source(VertexSource& source) { m_source = &source; }
explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id)
{

View file

@ -152,7 +152,6 @@ namespace agg
double m_approximation_scale;
double m_distance_tolerance_square;
double m_distance_tolerance_manhattan;
double m_angle_tolerance;
unsigned m_count;
pod_bvector<point_d> m_points;
@ -464,7 +463,6 @@ namespace agg
double m_approximation_scale;
double m_distance_tolerance_square;
double m_distance_tolerance_manhattan;
double m_angle_tolerance;
double m_cusp_limit;
unsigned m_count;

View file

@ -52,9 +52,13 @@ namespace agg
enum block_size_e { block_size = 16384-16 };
//--------------------------------------------------------------------
font_cache(const char* font_signature) :
font_cache() :
m_allocator(block_size),
m_font_signature(0)
{}
//--------------------------------------------------------------------
void signature(const char* font_signature)
{
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
strcpy(m_font_signature, font_signature);
@ -114,7 +118,7 @@ namespace agg
}
private:
pod_allocator m_allocator;
block_allocator m_allocator;
glyph_cache** m_glyphs[256];
char* m_font_signature;
};
@ -135,14 +139,14 @@ namespace agg
unsigned i;
for(i = 0; i < m_num_fonts; ++i)
{
delete m_fonts[i];
obj_allocator<font_cache>::deallocate(m_fonts[i]);
}
delete [] m_fonts;
pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
}
//--------------------------------------------------------------------
font_cache_pool(unsigned max_fonts=32) :
m_fonts(new font_cache* [max_fonts]),
m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)),
m_max_fonts(max_fonts),
m_num_fonts(0),
m_cur_font(0)
@ -157,8 +161,9 @@ namespace agg
{
if(reset_cache)
{
delete m_fonts[idx];
m_fonts[idx] = new font_cache(font_signature);
obj_allocator<font_cache>::deallocate(m_fonts[idx]);
m_fonts[idx] = obj_allocator<font_cache>::allocate();
m_fonts[idx]->signature(font_signature);
}
m_cur_font = m_fonts[idx];
}
@ -166,13 +171,14 @@ namespace agg
{
if(m_num_fonts >= m_max_fonts)
{
delete m_fonts[0];
obj_allocator<font_cache>::deallocate(m_fonts[0]);
memcpy(m_fonts,
m_fonts + 1,
(m_max_fonts - 1) * sizeof(font_cache*));
m_num_fonts = m_max_fonts - 1;
}
m_fonts[m_num_fonts] = new font_cache(font_signature);
m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
m_fonts[m_num_fonts]->signature(font_signature);
m_cur_font = m_fonts[m_num_fonts];
++m_num_fonts;
}
@ -269,6 +275,12 @@ namespace agg
m_last_glyph(0)
{}
//--------------------------------------------------------------------
void reset_last_glyph()
{
m_prev_glyph = m_last_glyph = 0;
}
//--------------------------------------------------------------------
const glyph_cache* glyph(unsigned glyph_code)
{

View file

@ -45,14 +45,14 @@ namespace agg
~gamma_lut()
{
delete [] m_inv_gamma;
delete [] m_dir_gamma;
pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
}
gamma_lut() :
m_gamma(1.0),
m_dir_gamma(new HiResT[gamma_size]),
m_inv_gamma(new LoResT[hi_res_size])
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
{
unsigned i;
for(i = 0; i < gamma_size; i++)
@ -68,8 +68,8 @@ namespace agg
gamma_lut(double g) :
m_gamma(1.0),
m_dir_gamma(new HiResT[gamma_size]),
m_inv_gamma(new LoResT[hi_res_size])
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
{
gamma(g);
}

View file

@ -20,7 +20,7 @@
#ifndef AGG_GSV_TEXT_INCLUDED
#define AGG_GSV_TEXT_INCLUDED
#include "agg_basics.h"
#include "agg_array.h"
#include "agg_conv_stroke.h"
#include "agg_conv_transform.h"
@ -43,7 +43,6 @@ namespace agg
};
public:
~gsv_text();
gsv_text();
void font(const void* font);
@ -55,6 +54,8 @@ namespace agg
void start_point(double x, double y);
void text(const char* text);
double text_width();
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
@ -89,15 +90,13 @@ namespace agg
double m_line_space;
char m_chr[2];
char* m_text;
char* m_text_buf;
unsigned m_buf_size;
pod_array<char> m_text_buf;
char* m_cur_chr;
const void* m_font;
char* m_loaded_font;
pod_array<char> m_loaded_font;
status m_status;
bool m_big_endian;
bool m_flip;
int8u* m_indices;
int8* m_glyphs;
int8* m_bglyph;

View file

@ -32,13 +32,14 @@ namespace agg
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_clip() {}
image_accessor_clip(const pixfmt_type& pixf, const color_type& bk) :
explicit image_accessor_clip(const pixfmt_type& pixf,
const color_type& bk) :
m_pixf(&pixf)
{
pixfmt_type::make_pix(m_bk_buf, bk);
}
void set_source(const pixfmt_type& pixf)
void attach(const pixfmt_type& pixf)
{
m_pixf = &pixf;
}
@ -65,7 +66,7 @@ namespace agg
m_x = m_x0 = x;
m_y = y;
if(y >= 0 && y < (int)m_pixf->height() &&
x >= 0 && x+len <= (int)m_pixf->width())
x >= 0 && x+(int)len <= (int)m_pixf->width())
{
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
@ -114,9 +115,11 @@ namespace agg
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_no_clip() {}
image_accessor_no_clip(const pixfmt_type& pixf) : m_pixf(&pixf) {}
explicit image_accessor_no_clip(const pixfmt_type& pixf) :
m_pixf(&pixf)
{}
void set_source(const pixfmt_type& pixf)
void attach(const pixfmt_type& pixf)
{
m_pixf = &pixf;
}
@ -159,9 +162,11 @@ namespace agg
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_clone() {}
image_accessor_clone(const pixfmt_type& pixf) : m_pixf(&pixf) {}
explicit image_accessor_clone(const pixfmt_type& pixf) :
m_pixf(&pixf)
{}
void set_source(const pixfmt_type& pixf)
void attach(const pixfmt_type& pixf)
{
m_pixf = &pixf;
}
@ -233,13 +238,13 @@ namespace agg
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_wrap() {}
image_accessor_wrap(const pixfmt_type& pixf) :
explicit image_accessor_wrap(const pixfmt_type& pixf) :
m_pixf(&pixf),
m_wrap_x(pixf.width()),
m_wrap_y(pixf.height())
{}
void set_source(const pixfmt_type& pixf)
void attach(const pixfmt_type& pixf)
{
m_pixf = &pixf;
}

View file

@ -20,6 +20,7 @@
#ifndef AGG_IMAGE_FILTERS_INCLUDED
#define AGG_IMAGE_FILTERS_INCLUDED
#include "agg_array.h"
#include "agg_math.h"
namespace agg
@ -46,9 +47,6 @@ namespace agg
class image_filter_lut
{
public:
~image_filter_lut();
image_filter_lut();
template<class FilterF> void calculate(const FilterF& filter,
bool normalization=true)
{
@ -71,10 +69,10 @@ namespace agg
}
}
image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {}
template<class FilterF> image_filter_lut(const FilterF& filter,
bool normalization=true) :
m_weight_array(0),
m_max_size(0)
bool normalization=true)
{
calculate(filter, normalization);
}
@ -82,7 +80,7 @@ namespace agg
double radius() const { return m_radius; }
unsigned diameter() const { return m_diameter; }
int start() const { return m_start; }
const int16* weight_array() const { return m_weight_array; }
const int16* weight_array() const { return &m_weight_array[0]; }
void normalize();
private:
@ -93,8 +91,7 @@ namespace agg
double m_radius;
unsigned m_diameter;
int m_start;
int16* m_weight_array;
unsigned m_max_size;
pod_array<int16> m_weight_array;
};

View file

@ -142,8 +142,8 @@ namespace agg
int octant;
//---------------------------------------------------------------------
static int8u s_orthogonal_quadrant[8];
static int8u s_diagonal_quadrant[8];
static const int8u s_orthogonal_quadrant[8];
static const int8u s_diagonal_quadrant[8];
};

View file

@ -41,7 +41,6 @@ namespace agg
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
}
//--------------------------------------------------------point_in_triangle
AGG_INLINE bool point_in_triangle(double x1, double y1,
double x2, double y2,
@ -54,7 +53,6 @@ namespace agg
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
}
//-----------------------------------------------------------calc_distance
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
{
@ -63,6 +61,13 @@ namespace agg
return sqrt(dx * dx + dy * dy);
}
//--------------------------------------------------------calc_sq_distance
AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
{
double dx = x2-x1;
double dy = y2-y1;
return dx * dx + dy * dy;
}
//------------------------------------------------calc_line_point_distance
AGG_INLINE double calc_line_point_distance(double x1, double y1,
@ -79,6 +84,53 @@ namespace agg
return ((x - x2) * dy - (y - y2) * dx) / d;
}
//-------------------------------------------------------calc_line_point_u
AGG_INLINE double calc_segment_point_u(double x1, double y1,
double x2, double y2,
double x, double y)
{
double dx = x2 - x1;
double dy = y2 - y1;
if(dx == 0 && dy == 0)
{
return 0;
}
double pdx = x - x1;
double pdy = y - y1;
return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
}
//---------------------------------------------calc_line_point_sq_distance
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
double x2, double y2,
double x, double y,
double u)
{
if(u <= 0)
{
return calc_sq_distance(x, y, x1, y1);
}
else
if(u >= 1)
{
return calc_sq_distance(x, y, x2, y2);
}
return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
}
//---------------------------------------------calc_line_point_sq_distance
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
double x2, double y2,
double x, double y)
{
return
calc_segment_point_sq_distance(
x1, y1, x2, y2, x, y,
calc_segment_point_u(x1, y1, x2, y2, x, y));
}
//-------------------------------------------------------calc_intersection
AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
@ -94,7 +146,6 @@ namespace agg
return true;
}
//-----------------------------------------------------intersection_exists
AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
double x3, double y3, double x4, double y4)
@ -122,7 +173,6 @@ namespace agg
//return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
}
//--------------------------------------------------------calc_orthogonal
AGG_INLINE void calc_orthogonal(double thickness,
double x1, double y1,
@ -133,10 +183,9 @@ namespace agg
double dy = y2 - y1;
double d = sqrt(dx*dx + dy*dy);
*x = thickness * dy / d;
*y = thickness * dx / d;
*y = -thickness * dx / d;
}
//--------------------------------------------------------dilate_triangle
AGG_INLINE void dilate_triangle(double x1, double y1,
double x2, double y2,
@ -161,12 +210,12 @@ namespace agg
calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
}
*x++ = x1 + dx1; *y++ = y1 - dy1;
*x++ = x2 + dx1; *y++ = y2 - dy1;
*x++ = x2 + dx2; *y++ = y2 - dy2;
*x++ = x3 + dx2; *y++ = y3 - dy2;
*x++ = x3 + dx3; *y++ = y3 - dy3;
*x++ = x1 + dx3; *y++ = y1 - dy3;
*x++ = x1 + dx1; *y++ = y1 + dy1;
*x++ = x2 + dx1; *y++ = y2 + dy1;
*x++ = x2 + dx2; *y++ = y2 + dy2;
*x++ = x3 + dx2; *y++ = y3 + dy2;
*x++ = x3 + dx3; *y++ = y3 + dy3;
*x++ = x1 + dx3; *y++ = y1 + dy3;
}
//------------------------------------------------------calc_triangle_area
@ -177,7 +226,6 @@ namespace agg
return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
}
//-------------------------------------------------------calc_polygon_area
template<class Storage> double calc_polygon_area(const Storage& st)
{
@ -274,7 +322,7 @@ namespace agg
}
}
//This is calculation sqrt itself.
//This code calculates the sqrt.
bit -= 9;
if(bit > 0)
{

View file

@ -53,75 +53,176 @@ namespace agg
inner_round
};
// Minimal angle to calculate round joins, less than 0.1 degree.
const double stroke_theta = 0.001; //----stroke_theta
//--------------------------------------------------------stroke_calc_arc
template<class VertexConsumer>
void stroke_calc_arc(VertexConsumer& out_vertices,
double x, double y,
double dx1, double dy1,
double dx2, double dy2,
double width,
double approximation_scale)
//------------------------------------------------------------math_stroke
template<class VertexConsumer> class math_stroke
{
public:
typedef typename VertexConsumer::value_type coord_type;
double a1 = atan2(dy1, dx1);
double a2 = atan2(dy2, dx2);
math_stroke();
void line_cap(line_cap_e lc) { m_line_cap = lc; }
void line_join(line_join_e lj) { m_line_join = lj; }
void inner_join(inner_join_e ij) { m_inner_join = ij; }
line_cap_e line_cap() const { return m_line_cap; }
line_join_e line_join() const { return m_line_join; }
inner_join_e inner_join() const { return m_inner_join; }
void width(double w);
void miter_limit(double ml) { m_miter_limit = ml; }
void miter_limit_theta(double t);
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
void approximation_scale(double as) { m_approx_scale = as; }
double width() const { return m_width * 2.0; }
double miter_limit() const { return m_miter_limit; }
double inner_miter_limit() const { return m_inner_miter_limit; }
double approximation_scale() const { return m_approx_scale; }
void calc_cap(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
double len);
void calc_join(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double len1,
double len2);
private:
AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y)
{
vc.add(coord_type(x, y));
}
void calc_arc(VertexConsumer& vc,
double x, double y,
double dx1, double dy1,
double dx2, double dy2);
void calc_miter(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double dx1, double dy1,
double dx2, double dy2,
line_join_e lj,
double mlimit,
double dbevel);
double m_width;
double m_width_abs;
double m_width_eps;
int m_width_sign;
double m_miter_limit;
double m_inner_miter_limit;
double m_approx_scale;
line_cap_e m_line_cap;
line_join_e m_line_join;
inner_join_e m_inner_join;
};
//-----------------------------------------------------------------------
template<class VC> math_stroke<VC>::math_stroke() :
m_width(0.5),
m_width_abs(0.5),
m_width_eps(0.5/1024.0),
m_width_sign(1),
m_miter_limit(4.0),
m_inner_miter_limit(1.01),
m_approx_scale(1.0),
m_line_cap(butt_cap),
m_line_join(miter_join),
m_inner_join(inner_miter)
{
}
//-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::width(double w)
{
m_width = w * 0.5;
if(m_width < 0)
{
m_width_abs = -m_width;
m_width_sign = -1;
}
else
{
m_width_abs = m_width;
m_width_sign = 1;
}
m_width_eps = m_width / 1024.0;
}
//-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::miter_limit_theta(double t)
{
m_miter_limit = 1.0 / sin(t * 0.5) ;
}
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::calc_arc(VC& vc,
double x, double y,
double dx1, double dy1,
double dx2, double dy2)
{
double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign);
double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign);
double da = a1 - a2;
int i, n;
bool ccw = da > 0.0 && da < pi;
da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
if(width < 0) width = -width;
da = acos(width / (width + 0.125 / approximation_scale)) * 2;
out_vertices.add(coord_type(x + dx1, y + dy1));
if(!ccw)
add_vertex(vc, x + dx1, y + dy1);
if(m_width_sign > 0)
{
if(a1 > a2) a2 += 2 * pi;
a2 -= da / 4;
n = int((a2 - a1) / da);
da = (a2 - a1) / (n + 1);
a1 += da;
while(a1 < a2)
for(i = 0; i < n; i++)
{
out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width));
add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
a1 += da;
}
}
else
{
if(a1 < a2) a2 -= 2 * pi;
a2 += da / 4;
n = int((a1 - a2) / da);
da = (a1 - a2) / (n + 1);
a1 -= da;
while(a1 > a2)
for(i = 0; i < n; i++)
{
out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width));
add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
a1 -= da;
}
}
out_vertices.add(coord_type(x + dx2, y + dy2));
add_vertex(vc, x + dx2, y + dy2);
}
//-------------------------------------------------------stroke_calc_miter
template<class VertexConsumer>
void stroke_calc_miter(VertexConsumer& out_vertices,
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::calc_miter(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double dx1, double dy1,
double dx2, double dy2,
double width,
line_join_e line_join,
double miter_limit,
double approximation_scale)
line_join_e lj,
double mlimit,
double dbevel)
{
typedef typename VertexConsumer::value_type coord_type;
double xi = v1.x;
double yi = v1.y;
double di = 1;
double lim = m_width_abs * mlimit;
bool miter_limit_exceeded = true; // Assume the worst
bool intersection_failed = true; // Assume the worst
if(calc_intersection(v0.x + dx1, v0.y - dy1,
v1.x + dx1, v1.y - dy1,
@ -131,15 +232,15 @@ namespace agg
{
// Calculation of the intersection succeeded
//---------------------
double d1 = calc_distance(v1.x, v1.y, xi, yi);
double lim = width * miter_limit;
if(d1 <= lim)
di = calc_distance(v1.x, v1.y, xi, yi);
if(di <= lim)
{
// Inside the miter limit
//---------------------
out_vertices.add(coord_type(xi, yi));
add_vertex(vc, xi, yi);
miter_limit_exceeded = false;
}
intersection_failed = false;
}
else
{
@ -153,13 +254,13 @@ namespace agg
//----------------
double x2 = v1.x + dx1;
double y2 = v1.y - dy1;
if(((x2 - v0.x)*dy1 - (v0.y - y2)*dx1 < 0.0) !=
((x2 - v2.x)*dy1 - (v2.y - y2)*dx1 < 0.0))
if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
(cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
{
// This case means that the next segment continues
// the previous one (straight line)
//-----------------
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
add_vertex(vc, v1.x + dx1, v1.y - dy1);
miter_limit_exceeded = false;
}
}
@ -168,171 +269,177 @@ namespace agg
{
// Miter limit exceeded
//------------------------
switch(line_join)
switch(lj)
{
case miter_join_revert:
// For the compatibility with SVG, PDF, etc,
// we use a simple bevel join instead of
// "smart" bevel
//-------------------
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2);
break;
case miter_join_round:
stroke_calc_arc(out_vertices,
v1.x, v1.y, dx1, -dy1, dx2, -dy2,
width, approximation_scale);
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
break;
default:
// If no miter-revert, calculate new dx1, dy1, dx2, dy2
//----------------
out_vertices.add(coord_type(v1.x + dx1 + dy1 * miter_limit,
v1.y - dy1 + dx1 * miter_limit));
out_vertices.add(coord_type(v1.x + dx2 - dy2 * miter_limit,
v1.y - dy2 - dx2 * miter_limit));
if(intersection_failed)
{
mlimit *= m_width_sign;
add_vertex(vc, v1.x + dx1 + dy1 * mlimit,
v1.y - dy1 + dx1 * mlimit);
add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
v1.y - dy2 - dx2 * mlimit);
}
else
{
double x1 = v1.x + dx1;
double y1 = v1.y - dy1;
double x2 = v1.x + dx2;
double y2 = v1.y - dy2;
di = (lim - dbevel) / (di - dbevel);
add_vertex(vc, x1 + (xi - x1) * di,
y1 + (yi - y1) * di);
add_vertex(vc, x2 + (xi - x2) * di,
y2 + (yi - y2) * di);
}
break;
}
}
}
//--------------------------------------------------------stroke_calc_cap
template<class VertexConsumer>
void stroke_calc_cap(VertexConsumer& out_vertices,
template<class VC>
void math_stroke<VC>::calc_cap(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
double len,
line_cap_e line_cap,
double width,
double approximation_scale)
double len)
{
typedef typename VertexConsumer::value_type coord_type;
out_vertices.remove_all();
vc.remove_all();
double dx1 = (v1.y - v0.y) / len;
double dy1 = (v1.x - v0.x) / len;
double dx2 = 0;
double dy2 = 0;
dx1 *= width;
dy1 *= width;
dx1 *= m_width;
dy1 *= m_width;
if(line_cap != round_cap)
if(m_line_cap != round_cap)
{
if(line_cap == square_cap)
if(m_line_cap == square_cap)
{
dx2 = dy1;
dy2 = dx1;
dx2 = dy1 * m_width_sign;
dy2 = dx1 * m_width_sign;
}
out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2));
out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2));
add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
}
else
{
double a1 = atan2(dy1, -dx1);
double a2 = a1 + pi;
double da = acos(width / (width + 0.125 / approximation_scale)) * 2;
out_vertices.add(coord_type(v0.x - dx1, v0.y + dy1));
a1 += da;
a2 -= da/4;
while(a1 < a2)
double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
double a1;
int i;
int n = int(pi / da);
da = pi / (n + 1);
add_vertex(vc, v0.x - dx1, v0.y + dy1);
if(m_width_sign > 0)
{
out_vertices.add(coord_type(v0.x + cos(a1) * width,
v0.y + sin(a1) * width));
a1 = atan2(dy1, -dx1);
a1 += da;
for(i = 0; i < n; i++)
{
add_vertex(vc, v0.x + cos(a1) * m_width,
v0.y + sin(a1) * m_width);
a1 += da;
}
out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1));
}
else
{
a1 = atan2(-dy1, dx1);
a1 -= da;
for(i = 0; i < n; i++)
{
add_vertex(vc, v0.x + cos(a1) * m_width,
v0.y + sin(a1) * m_width);
a1 -= da;
}
}
add_vertex(vc, v0.x + dx1, v0.y - dy1);
}
}
//-------------------------------------------------------stroke_calc_join
template<class VertexConsumer>
void stroke_calc_join(VertexConsumer& out_vertices,
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::calc_join(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double len1,
double len2,
double width,
line_join_e line_join,
inner_join_e inner_join,
double miter_limit,
double inner_miter_limit,
double approximation_scale)
double len2)
{
typedef typename VertexConsumer::value_type coord_type;
double dx1 = m_width * (v1.y - v0.y) / len1;
double dy1 = m_width * (v1.x - v0.x) / len1;
double dx2 = m_width * (v2.y - v1.y) / len2;
double dy2 = m_width * (v2.x - v1.x) / len2;
double dx1, dy1, dx2, dy2;
double d;
vc.remove_all();
dx1 = width * (v1.y - v0.y) / len1;
dy1 = width * (v1.x - v0.x) / len1;
dx2 = width * (v2.y - v1.y) / len2;
dy2 = width * (v2.x - v1.x) / len2;
out_vertices.remove_all();
if(cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0)
double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
if(cp != 0 && (cp > 0) == (m_width > 0))
{
// Inner join
//---------------
switch(inner_join)
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
if(limit < m_inner_miter_limit)
{
limit = m_inner_miter_limit;
}
switch(m_inner_join)
{
default: // inner_bevel
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2);
break;
case inner_miter:
stroke_calc_miter(out_vertices,
calc_miter(vc,
v0, v1, v2, dx1, dy1, dx2, dy2,
width,
miter_join_revert,
inner_miter_limit,
1.0);
limit, 0);
break;
case inner_jag:
case inner_round:
cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
if(cp < len1 * len1 && cp < len2 * len2)
{
d = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
if(d < len1 * len1 && d < len2 * len2)
{
stroke_calc_miter(out_vertices,
calc_miter(vc,
v0, v1, v2, dx1, dy1, dx2, dy2,
width,
miter_join_revert,
inner_miter_limit,
1.0);
limit, 0);
}
else
{
if(inner_join == inner_jag)
if(m_inner_join == inner_jag)
{
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
out_vertices.add(coord_type(v1.x, v1.y ));
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x, v1.y );
add_vertex(vc, v1.x + dx2, v1.y - dy2);
}
else
{
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
out_vertices.add(coord_type(v1.x, v1.y ));
stroke_calc_arc(out_vertices,
v1.x, v1.y, dx2, -dy2, dx1, -dy1,
width, approximation_scale);
out_vertices.add(coord_type(v1.x, v1.y ));
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
}
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x, v1.y );
calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
add_vertex(vc, v1.x, v1.y );
add_vertex(vc, v1.x + dx2, v1.y - dy2);
}
}
break;
@ -342,10 +449,18 @@ namespace agg
{
// Outer join
//---------------
if(line_join == round_join || line_join == bevel_join)
// Calculate the distance between v1 and
// the central point of the bevel line segment
//---------------
double dx = (dx1 + dx2) / 2;
double dy = (dy1 + dy2) / 2;
double dbevel = sqrt(dx * dx + dy * dy);
if(m_line_join == round_join || m_line_join == bevel_join)
{
// This is an optimization that reduces the number of points
// in cases of almost collonear segments. If there's no
// in cases of almost collinear segments. If there's no
// visible difference between bevel and miter joins we'd rather
// use miter join because it adds only one point instead of two.
//
@ -354,44 +469,50 @@ namespace agg
// At outer joins this distance always less than stroke width,
// because it's actually the height of an isosceles triangle of
// v1 and its two bevel points. If the difference between this
// width and this value is small (no visible bevel) we can switch
// to the miter join.
// width and this value is small (no visible bevel) we can
// add just one point.
//
// The constant in the expression makes the result approximately
// the same as in round joins and caps. One can safely comment
// out this "if".
// the same as in round joins and caps. You can safely comment
// out this entire "if".
//-------------------
double dx = (dx1 + dx2) / 2;
double dy = (dy1 + dy2) / 2;
d = width - sqrt(dx * dx + dy * dy);
if(d < 0.0625 / approximation_scale)
if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
{
line_join = miter_join;
if(calc_intersection(v0.x + dx1, v0.y - dy1,
v1.x + dx1, v1.y - dy1,
v1.x + dx2, v1.y - dy2,
v2.x + dx2, v2.y - dy2,
&dx, &dy))
{
add_vertex(vc, dx, dy);
}
else
{
add_vertex(vc, v1.x + dx1, v1.y - dy1);
}
return;
}
}
switch(line_join)
switch(m_line_join)
{
case miter_join:
case miter_join_revert:
case miter_join_round:
stroke_calc_miter(out_vertices,
calc_miter(vc,
v0, v1, v2, dx1, dy1, dx2, dy2,
width,
line_join,
miter_limit,
approximation_scale);
m_line_join,
m_miter_limit,
dbevel);
break;
case round_join:
stroke_calc_arc(out_vertices,
v1.x, v1.y, dx1, -dy1, dx2, -dy2,
width, approximation_scale);
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
break;
default: // Bevel join
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2);
break;
}
}

View file

@ -90,10 +90,13 @@ namespace agg
T** coord_blk = m_coord_blocks + m_total_blocks - 1;
while(m_total_blocks--)
{
delete [] *coord_blk;
pod_allocator<T>::deallocate(
*coord_blk,
block_size * 2 +
block_size / (sizeof(T) / sizeof(unsigned char)));
--coord_blk;
}
delete [] m_coord_blocks;
pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2);
m_total_blocks = 0;
m_max_blocks = 0;
m_coord_blocks = 0;
@ -298,7 +301,7 @@ namespace agg
if(nb >= m_max_blocks)
{
T** new_coords =
new T* [(m_max_blocks + block_pool) * 2];
pod_allocator<T*>::allocate((m_max_blocks + block_pool) * 2);
unsigned char** new_cmds =
(unsigned char**)(new_coords + m_max_blocks + block_pool);
@ -313,15 +316,15 @@ namespace agg
m_cmd_blocks,
m_max_blocks * sizeof(unsigned char*));
delete [] m_coord_blocks;
pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2);
}
m_coord_blocks = new_coords;
m_cmd_blocks = new_cmds;
m_max_blocks += block_pool;
}
m_coord_blocks[nb] =
new T [block_size * 2 +
block_size / (sizeof(T) / sizeof(unsigned char))];
pod_allocator<T>::allocate(block_size * 2 +
block_size / (sizeof(T) / sizeof(unsigned char)));
m_cmd_blocks[nb] =
(unsigned char*)(m_coord_blocks[nb] + block_size * 2);
@ -766,7 +769,7 @@ namespace agg
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
m_vertices.add_vertex(x, y, is_move_to(cmd) ?
path_cmd_line_to :
unsigned(path_cmd_line_to) :
cmd);
}
}
@ -792,6 +795,46 @@ namespace agg
join_path(poly);
}
//--------------------------------------------------------------------
void translate(double dx, double dy, unsigned path_id=0);
void translate_all_paths(double dx, double dy);
//--------------------------------------------------------------------
template<class Trans>
void transform(const Trans& trans, unsigned path_id=0)
{
unsigned num_ver = m_vertices.total_vertices();
for(; path_id < num_ver; path_id++)
{
double x, y;
unsigned cmd = m_vertices.vertex(path_id, &x, &y);
if(is_stop(cmd)) break;
if(is_vertex(cmd))
{
trans.transform(&x, &y);
m_vertices.modify_vertex(path_id, x, y);
}
}
}
//--------------------------------------------------------------------
template<class Trans>
void transform_all_paths(const Trans& trans)
{
unsigned idx;
unsigned num_ver = m_vertices.total_vertices();
for(idx = 0; idx < num_ver; idx++)
{
double x, y;
if(is_vertex(m_vertices.vertex(idx, &x, &y)))
{
trans.transform(&x, &y);
m_vertices.modify_vertex(idx, x, y);
}
}
}
private:
unsigned perceive_polygon_orientation(unsigned start, unsigned end);
@ -1167,7 +1210,6 @@ namespace agg
return m_vertices.vertex(m_iterator++, x, y);
}
//------------------------------------------------------------------------
template<class VC>
unsigned path_base<VC>::perceive_polygon_orientation(unsigned start,
@ -1188,7 +1230,6 @@ namespace agg
return (area < 0.0) ? path_flags_cw : path_flags_ccw;
}
//------------------------------------------------------------------------
template<class VC>
void path_base<VC>::invert_polygon(unsigned start, unsigned end)
@ -1232,11 +1273,8 @@ namespace agg
while(end < m_vertices.total_vertices() &&
!is_next_poly(m_vertices.command(end))) ++end;
if(end - start > 2)
{
invert_polygon(start, end);
}
}
//------------------------------------------------------------------------
template<class VC>
@ -1276,7 +1314,6 @@ namespace agg
return end;
}
//------------------------------------------------------------------------
template<class VC>
unsigned path_base<VC>::arrange_orientations(unsigned start,
@ -1297,7 +1334,6 @@ namespace agg
return start;
}
//------------------------------------------------------------------------
template<class VC>
void path_base<VC>::arrange_orientations_all_paths(path_flags_e orientation)
@ -1312,7 +1348,6 @@ namespace agg
}
}
//------------------------------------------------------------------------
template<class VC>
void path_base<VC>::flip_x(double x1, double x2)
@ -1329,7 +1364,6 @@ namespace agg
}
}
//------------------------------------------------------------------------
template<class VC>
void path_base<VC>::flip_y(double y1, double y2)
@ -1346,9 +1380,42 @@ namespace agg
}
}
//------------------------------------------------------------------------
template<class VC>
void path_base<VC>::translate(double dx, double dy, unsigned path_id)
{
unsigned num_ver = m_vertices.total_vertices();
for(; path_id < num_ver; path_id++)
{
double x, y;
unsigned cmd = m_vertices.vertex(path_id, &x, &y);
if(is_stop(cmd)) break;
if(is_vertex(cmd))
{
x += dx;
y += dy;
m_vertices.modify_vertex(path_id, x, y);
}
}
}
//------------------------------------------------------------------------
template<class VC>
void path_base<VC>::translate_all_paths(double dx, double dy)
{
unsigned idx;
unsigned num_ver = m_vertices.total_vertices();
for(idx = 0; idx < num_ver; idx++)
{
double x, y;
if(is_vertex(m_vertices.vertex(idx, &x, &y)))
{
x += dx;
y += dy;
m_vertices.modify_vertex(idx, x, y);
}
}
}
//-----------------------------------------------------vertex_stl_storage
template<class Container> class vertex_stl_storage

View file

@ -18,6 +18,7 @@
#include <string.h>
#include "agg_array.h"
#include "agg_rendering_buffer.h"
@ -38,38 +39,40 @@ namespace agg
void realloc_span(unsigned len)
{
if(len > m_max_len)
if(len > m_span.size())
{
delete [] m_span;
m_span = new cover_type[m_max_len = len + span_extra_tail];
m_span.resize(len + span_extra_tail);
}
}
void init_span(unsigned len)
{
realloc_span(len);
// ATTN! May work incorrectly if cover_type is more that one byte
memset(m_span, amask_type::cover_full, len * sizeof(cover_type));
memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
}
void init_span(unsigned len, const cover_type* covers)
{
realloc_span(len);
memcpy(m_span, covers, len * sizeof(cover_type));
memcpy(&m_span[0], covers, len * sizeof(cover_type));
}
public:
~pixfmt_amask_adaptor() { delete [] m_span; }
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0)
m_pixf(&pixf), m_mask(&mask), m_span()
{}
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
//--------------------------------------------------------------------
template<class PixFmt2>
bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
{
return m_pixf->attach(pixf, x1, y1, x2, y2);
}
//--------------------------------------------------------------------
unsigned width() const { return m_pixf->width(); }
unsigned height() const { return m_pixf->height(); }
@ -98,8 +101,8 @@ namespace agg
const color_type& c)
{
realloc_span(len);
m_mask->fill_hspan(x, y, m_span, len);
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
m_mask->fill_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
@ -109,8 +112,8 @@ namespace agg
cover_type cover)
{
init_span(len);
m_mask->combine_hspan(x, y, m_span, len);
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
@ -119,8 +122,8 @@ namespace agg
const color_type& c)
{
realloc_span(len);
m_mask->fill_vspan(x, y, m_span, len);
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
m_mask->fill_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
@ -130,8 +133,8 @@ namespace agg
cover_type cover)
{
init_span(len);
m_mask->combine_vspan(x, y, m_span, len);
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
m_mask->combine_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
@ -151,8 +154,8 @@ namespace agg
const cover_type* covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, m_span, len);
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
@ -163,8 +166,8 @@ namespace agg
const cover_type* covers)
{
init_span(len, covers);
m_mask->combine_vspan(x, y, m_span, len);
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
m_mask->combine_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
@ -172,10 +175,17 @@ namespace agg
void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
{
realloc_span(len);
m_mask->fill_hspan(x, y, m_span, len);
m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover_full);
m_mask->fill_hspan(x, y, &m_span[0], len);
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
{
realloc_span(len);
m_mask->fill_vspan(x, y, &m_span[0], len);
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
@ -187,14 +197,14 @@ namespace agg
if(covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, m_span, len);
m_mask->combine_hspan(x, y, &m_span[0], len);
}
else
{
realloc_span(len);
m_mask->fill_hspan(x, y, m_span, len);
m_mask->fill_hspan(x, y, &m_span[0], len);
}
m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover);
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
}
@ -208,22 +218,20 @@ namespace agg
if(covers)
{
init_span(len, covers);
m_mask->combine_vspan(x, y, m_span, len);
m_mask->combine_vspan(x, y, &m_span[0], len);
}
else
{
realloc_span(len);
m_mask->fill_vspan(x, y, m_span, len);
m_mask->fill_vspan(x, y, &m_span[0], len);
}
m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover);
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
}
private:
pixfmt_type* m_pixf;
const amask_type* m_mask;
cover_type* m_span;
unsigned m_max_len;
pod_array<cover_type> m_span;
};
}

View file

@ -128,7 +128,9 @@ namespace agg
base_shift = color_type::base_shift,
base_scale = color_type::base_scale,
base_mask = color_type::base_mask,
pix_width = sizeof(value_type)
pix_width = sizeof(value_type),
pix_step = Step,
pix_offset = Offset
};
private:
@ -171,30 +173,46 @@ namespace agg
public:
//--------------------------------------------------------------------
pixfmt_alpha_blend_gray(rbuf_type& rb) :
explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
m_rbuf(&rb)
{}
void attach(rbuf_type& rb) { m_rbuf = &rb; }
//--------------------------------------------------------------------
template<class PixFmt>
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
{
rect_i r(x1, y1, x2, y2);
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
{
int stride = pixf.stride();
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
(r.x2 - r.x1) + 1,
(r.y2 - r.y1) + 1,
stride);
return true;
}
return false;
}
//--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
AGG_INLINE int stride() const { return m_rbuf->stride(); }
//--------------------------------------------------------------------
const int8u* row_ptr(int y) const
{
return m_rbuf->row_ptr(y);
}
int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
row_data row(int y) const { return m_rbuf->row(y); }
//--------------------------------------------------------------------
const int8u* pix_ptr(int x, int y) const
{
return m_rbuf->row_ptr(y) + x * pix_width;
return m_rbuf->row_ptr(y) + x * Step + Offset;
}
//--------------------------------------------------------------------
row_data row(int x, int y) const
int8u* pix_ptr(int x, int y)
{
return m_rbuf->row(y);
return m_rbuf->row_ptr(y) + x * Step + Offset;
}
//--------------------------------------------------------------------
@ -206,7 +224,7 @@ namespace agg
//--------------------------------------------------------------------
AGG_INLINE color_type pixel(int x, int y) const
{
value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset;
value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
return color_type(*p);
}
@ -399,13 +417,29 @@ namespace agg
do
{
*p++ = colors->v;
*p = colors->v;
p += Step;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
do
{
value_type* p = (value_type*)
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
*p = colors->v;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
@ -565,6 +599,58 @@ namespace agg
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& from,
const color_type& color,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
value_type* pdst =
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
do
{
copy_or_blend_pix(pdst,
color,
(*psrc * cover + base_mask) >> base_shift);
++psrc;
++pdst;
}
while(--len);
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_lut(const SrcPixelFormatRenderer& from,
const color_type* color_lut,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
value_type* pdst =
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
do
{
copy_or_blend_pix(pdst, color_lut[*psrc], cover);
++psrc;
++pdst;
}
while(--len);
}
}
private:
rbuf_type* m_rbuf;
};

View file

@ -173,8 +173,8 @@ namespace agg
{
public:
typedef RenBuf rbuf_type;
typedef typename rbuf_type::row_data row_data;
typedef Blender blender_type;
typedef typename rbuf_type::row_data row_data;
typedef typename blender_type::color_type color_type;
typedef typename blender_type::order_type order_type;
typedef typename color_type::value_type value_type;
@ -231,9 +231,27 @@ namespace agg
public:
//--------------------------------------------------------------------
pixfmt_alpha_blend_rgb(rbuf_type& rb) :
explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
m_rbuf(&rb)
{}
void attach(rbuf_type& rb) { m_rbuf = &rb; }
//--------------------------------------------------------------------
template<class PixFmt>
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
{
rect_i r(x1, y1, x2, y2);
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
{
int stride = pixf.stride();
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
(r.x2 - r.x1) + 1,
(r.y2 - r.y1) + 1,
stride);
return true;
}
return false;
}
//--------------------------------------------------------------------
Blender& blender() { return m_blender; }
@ -241,23 +259,22 @@ namespace agg
//--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
AGG_INLINE int stride() const { return m_rbuf->stride(); }
//--------------------------------------------------------------------
const int8u* row_ptr(int y) const
{
return m_rbuf->row_ptr(y);
}
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
//--------------------------------------------------------------------
const int8u* pix_ptr(int x, int y) const
AGG_INLINE int8u* pix_ptr(int x, int y)
{
return m_rbuf->row_ptr(y) + x * pix_width;
}
//--------------------------------------------------------------------
row_data row(int x, int y) const
AGG_INLINE const int8u* pix_ptr(int x, int y) const
{
return m_rbuf->row(y);
return m_rbuf->row_ptr(y) + x * pix_width;
}
//--------------------------------------------------------------------
@ -484,6 +501,24 @@ namespace agg
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
do
{
value_type* p = (value_type*)
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
p[order_type::R] = colors->r;
p[order_type::G] = colors->g;
p[order_type::B] = colors->b;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
@ -687,6 +722,74 @@ namespace agg
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& from,
const color_type& color,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
value_type* pdst =
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
do
{
copy_or_blend_pix(pdst,
color,
(*psrc * cover + base_mask) >> base_shift);
++psrc;
pdst += 3;
}
while(--len);
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_lut(const SrcPixelFormatRenderer& from,
const color_type* color_lut,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
value_type* pdst =
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
if(cover == 255)
{
do
{
const color_type& color = color_lut[*psrc];
m_blender.blend_pix(pdst,
color.r, color.g, color.b, color.a);
++psrc;
pdst += 3;
}
while(--len);
}
else
{
do
{
copy_or_blend_pix(pdst, color_lut[*psrc], cover);
++psrc;
pdst += 3;
}
while(--len);
}
}
}
private:
rbuf_type* m_rbuf;
Blender m_blender;

View file

@ -828,29 +828,47 @@ namespace agg
public:
//--------------------------------------------------------------------
pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {}
explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {}
void attach(rbuf_type& rb) { m_rbuf = &rb; }
//--------------------------------------------------------------------
template<class PixFmt>
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
{
rect_i r(x1, y1, x2, y2);
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
{
int stride = pixf.stride();
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
(r.x2 - r.x1) + 1,
(r.y2 - r.y1) + 1,
stride);
return true;
}
return false;
}
Blender& blender() { return m_blender; }
//--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
AGG_INLINE int stride() const { return m_rbuf->stride(); }
//--------------------------------------------------------------------
const int8u* row_ptr(int y) const
{
return m_rbuf->row_ptr(y);
}
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
//--------------------------------------------------------------------
const int8u* pix_ptr(int x, int y) const
AGG_INLINE int8u* pix_ptr(int x, int y)
{
return m_rbuf->row_ptr(y) + x * pix_width;
}
//--------------------------------------------------------------------
row_data row(int x, int y) const
AGG_INLINE const int8u* pix_ptr(int x, int y) const
{
return m_rbuf->row(y);
return m_rbuf->row_ptr(y) + x * pix_width;
}
//--------------------------------------------------------------------
@ -1012,6 +1030,20 @@ namespace agg
while(--len);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
do
{
pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x;
*p = m_blender.make_pix(colors->r, colors->g, colors->b);
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
@ -1102,6 +1134,65 @@ namespace agg
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& from,
const color_type& color,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
pixel_type* pdst =
(pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
do
{
m_blender.blend_pix(pdst,
color.r, color.g, color.b, color.a,
cover);
++psrc;
++pdst;
}
while(--len);
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_lut(const SrcPixelFormatRenderer& from,
const color_type* color_lut,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
pixel_type* pdst =
(pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
do
{
const color_type& color = color_lut[*psrc];
m_blender.blend_pix(pdst,
color.r, color.g, color.b, color.a,
cover);
++psrc;
++pdst;
}
while(--len);
}
}
private:
rbuf_type* m_rbuf;
Blender m_blender;

View file

@ -614,6 +614,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type s1a = base_mask - sa;
calc_type d1a = base_mask - p[Order::A];
p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift);
@ -621,6 +623,7 @@ namespace agg
p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift);
p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1)));
}
}
};
//=========================================================comp_op_rgba_plus
@ -649,14 +652,17 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type dr = p[Order::R] + sr;
calc_type dg = p[Order::G] + sg;
calc_type db = p[Order::B] + sb;
calc_type da = p[Order::A] + sa;
p[Order::R] = (dr > base_mask) ? base_mask : dr;
p[Order::G] = (dg > base_mask) ? base_mask : dg;
p[Order::B] = (db > base_mask) ? base_mask : db;
p[Order::A] = (da > base_mask) ? base_mask : da;
p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr;
p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg;
p[Order::B] = (db > base_mask) ? (value_type)base_mask : db;
p[Order::A] = (da > base_mask) ? (value_type)base_mask : da;
}
}
};
@ -686,13 +692,17 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type dr = p[Order::R] - sr;
calc_type dg = p[Order::G] - sg;
calc_type db = p[Order::B] - sb;
p[Order::R] = (dr > base_mask) ? 0 : dr;
p[Order::G] = (dg > base_mask) ? 0 : dg;
p[Order::B] = (db > base_mask) ? 0 : db;
p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
//p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift));
}
}
};
@ -722,6 +732,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type s1a = base_mask - sa;
calc_type d1a = base_mask - p[Order::A];
calc_type dr = p[Order::R];
@ -732,6 +744,7 @@ namespace agg
p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift);
p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_screen
@ -760,6 +773,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type dr = p[Order::R];
calc_type dg = p[Order::G];
calc_type db = p[Order::B];
@ -769,6 +784,7 @@ namespace agg
p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_overlay
@ -801,6 +817,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R];
@ -811,18 +829,19 @@ namespace agg
p[Order::R] = (value_type)(((2*dr < da) ?
2*sr*dr + sr*d1a + dr*s1a :
sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a) >> base_shift);
sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
p[Order::G] = (value_type)(((2*dg < da) ?
2*sg*dg + sg*d1a + dg*s1a :
sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a) >> base_shift);
sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
p[Order::B] = (value_type)(((2*db < da) ?
2*sb*db + sb*d1a + db*s1a :
sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a) >> base_shift);
sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
@ -855,6 +874,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R];
@ -862,11 +883,12 @@ namespace agg
calc_type db = p[Order::B];
calc_type da = p[Order::A];
p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a) >> base_shift);
p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a) >> base_shift);
p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a) >> base_shift);
p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_lighten
@ -895,6 +917,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R];
@ -902,11 +926,12 @@ namespace agg
calc_type db = p[Order::B];
calc_type da = p[Order::A];
p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a) >> base_shift);
p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a) >> base_shift);
p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a) >> base_shift);
p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_color_dodge
@ -940,6 +965,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R];
@ -955,19 +982,20 @@ namespace agg
long_type sada = sa * da;
p[Order::R] = (value_type)((srda + drsa >= sada) ?
(sada + sr * d1a + dr * s1a) >> base_shift :
drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a) >> base_shift));
(sada + sr * d1a + dr * s1a + base_mask) >> base_shift :
drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift));
p[Order::G] = (value_type)((sgda + dgsa >= sada) ?
(sada + sg * d1a + dg * s1a) >> base_shift :
dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a) >> base_shift));
(sada + sg * d1a + dg * s1a + base_mask) >> base_shift :
dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift));
p[Order::B] = (value_type)((sbda + dbsa >= sada) ?
(sada + sb * d1a + db * s1a) >> base_shift :
dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a) >> base_shift));
(sada + sb * d1a + db * s1a + base_mask) >> base_shift :
dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_color_burn
@ -1001,6 +1029,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R];
@ -1017,18 +1047,19 @@ namespace agg
p[Order::R] = (value_type)(((srda + drsa <= sada) ?
sr * d1a + dr * s1a :
sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a) >> base_shift);
sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift);
p[Order::G] = (value_type)(((sgda + dgsa <= sada) ?
sg * d1a + dg * s1a :
sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a) >> base_shift);
sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift);
p[Order::B] = (value_type)(((sbda + dbsa <= sada) ?
sb * d1a + db * s1a :
sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a) >> base_shift);
sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift);
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_hard_light
@ -1062,6 +1093,8 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R];
@ -1072,18 +1105,19 @@ namespace agg
p[Order::R] = (value_type)(((2*sr < sa) ?
2*sr*dr + sr*d1a + dr*s1a :
sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a) >> base_shift);
sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
p[Order::G] = (value_type)(((2*sg < sa) ?
2*sg*dg + sg*d1a + dg*s1a :
sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a) >> base_shift);
sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
p[Order::B] = (value_type)(((2*sb < sa) ?
2*sb*db + sb*d1a + db*s1a :
sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a) >> base_shift);
sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_soft_light
@ -1117,6 +1151,8 @@ namespace agg
double sg = double(g * cover) / (base_mask * 255);
double sb = double(b * cover) / (base_mask * 255);
double sa = double(a * cover) / (base_mask * 255);
if(sa > 0)
{
double dr = double(p[Order::R]) / base_mask;
double dg = double(p[Order::G]) / base_mask;
double db = double(p[Order::B]) / base_mask;
@ -1143,6 +1179,7 @@ namespace agg
p[Order::B] = (value_type)uround(db * base_mask);
p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_difference
@ -1156,6 +1193,7 @@ namespace agg
enum base_scale_e
{
base_shift = color_type::base_shift,
base_scale = color_type::base_scale,
base_mask = color_type::base_mask
};
@ -1172,15 +1210,18 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type dr = p[Order::R];
calc_type dg = p[Order::G];
calc_type db = p[Order::B];
calc_type da = p[Order::A];
p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa)) >> base_shift));
p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa)) >> base_shift));
p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa)) >> base_shift));
p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift));
p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift));
p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_exclusion
@ -1210,17 +1251,20 @@ namespace agg
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R];
calc_type dg = p[Order::G];
calc_type db = p[Order::B];
calc_type da = p[Order::A];
p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a) >> base_shift);
p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a) >> base_shift);
p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a) >> base_shift);
p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift);
p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift);
p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift);
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=====================================================comp_op_rgba_contrast
@ -1270,11 +1314,83 @@ namespace agg
}
};
//=====================================================comp_op_rgba_invert
template<class ColorT, class Order> struct comp_op_rgba_invert
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
typedef typename color_type::long_type long_type;
enum base_scale_e
{
base_shift = color_type::base_shift,
base_mask = color_type::base_mask
};
// Dca' = (Da - Dca) * Sa + Dca.(1 - Sa)
// Da' = Sa + Da - Sa.Da
static AGG_INLINE void blend_pix(value_type* p,
unsigned sr, unsigned sg, unsigned sb,
unsigned sa, unsigned cover)
{
sa = (sa * cover + 255) >> 8;
if(sa)
{
calc_type da = p[Order::A];
calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift;
calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift;
calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift;
calc_type s1a = base_mask - sa;
p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
//=================================================comp_op_rgba_invert_rgb
template<class ColorT, class Order> struct comp_op_rgba_invert_rgb
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
typedef typename color_type::long_type long_type;
enum base_scale_e
{
base_shift = color_type::base_shift,
base_mask = color_type::base_mask
};
// Dca' = (Da - Dca) * Sca + Dca.(1 - Sa)
// Da' = Sa + Da - Sa.Da
static AGG_INLINE void blend_pix(value_type* p,
unsigned sr, unsigned sg, unsigned sb,
unsigned sa, unsigned cover)
{
if(cover < 255)
{
sr = (sr * cover + 255) >> 8;
sg = (sg * cover + 255) >> 8;
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if(sa)
{
calc_type da = p[Order::A];
calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift;
calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift;
calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift;
calc_type s1a = base_mask - sa;
p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
}
}
};
@ -1324,6 +1440,8 @@ namespace agg
comp_op_rgba_difference <ColorT,Order>::blend_pix,
comp_op_rgba_exclusion <ColorT,Order>::blend_pix,
comp_op_rgba_contrast <ColorT,Order>::blend_pix,
comp_op_rgba_invert <ColorT,Order>::blend_pix,
comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix,
0
};
@ -1357,6 +1475,8 @@ namespace agg
comp_op_difference, //----comp_op_difference
comp_op_exclusion, //----comp_op_exclusion
comp_op_contrast, //----comp_op_contrast
comp_op_invert, //----comp_op_invert
comp_op_invert_rgb, //----comp_op_invert_rgb
end_of_comp_op_e
};
@ -1652,31 +1772,48 @@ namespace agg
//--------------------------------------------------------------------
pixfmt_alpha_blend_rgba() : m_rbuf(0) {}
pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
void attach(rbuf_type& rb) { m_rbuf = &rb; }
//--------------------------------------------------------------------
template<class PixFmt>
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
{
rect_i r(x1, y1, x2, y2);
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
{
int stride = pixf.stride();
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
(r.x2 - r.x1) + 1,
(r.y2 - r.y1) + 1,
stride);
return true;
}
return false;
}
//--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
AGG_INLINE int stride() const { return m_rbuf->stride(); }
//--------------------------------------------------------------------
const int8u* row_ptr(int y) const
{
return m_rbuf->row_ptr(y);
}
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
//--------------------------------------------------------------------
const int8u* pix_ptr(int x, int y) const
AGG_INLINE int8u* pix_ptr(int x, int y)
{
return m_rbuf->row_ptr(y) + x * pix_width;
}
//--------------------------------------------------------------------
row_data row(int y) const
AGG_INLINE const int8u* pix_ptr(int x, int y) const
{
return m_rbuf->row(y);
return m_rbuf->row_ptr(y) + x * pix_width;
}
//--------------------------------------------------------------------
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
{
@ -1938,6 +2075,24 @@ namespace agg
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
do
{
value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
p[order_type::R] = colors->r;
p[order_type::G] = colors->g;
p[order_type::B] = colors->b;
p[order_type::A] = colors->a;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
@ -2170,6 +2325,77 @@ namespace agg
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& from,
const color_type& color,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
value_type* pdst =
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
do
{
cob_type::copy_or_blend_pix(pdst,
color.r, color.g, color.b, color.a,
(*psrc * cover + base_mask) >> base_shift);
++psrc;
pdst += 4;
}
while(--len);
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_lut(const SrcPixelFormatRenderer& from,
const color_type* color_lut,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
value_type* pdst =
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
if(cover == 255)
{
do
{
const color_type& color = color_lut[*psrc];
cob_type::copy_or_blend_pix(pdst,
color.r, color.g, color.b, color.a);
++psrc;
pdst += 4;
}
while(--len);
}
else
{
do
{
const color_type& color = color_lut[*psrc];
cob_type::copy_or_blend_pix(pdst,
color.r, color.g, color.b, color.a,
cover);
++psrc;
pdst += 4;
}
while(--len);
}
}
}
private:
rbuf_type* m_rbuf;
};
@ -2199,37 +2425,53 @@ namespace agg
//--------------------------------------------------------------------
pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {}
pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) :
explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) :
m_rbuf(&rb),
m_comp_op(comp_op)
{}
void attach(rbuf_type& rb) { m_rbuf = &rb; }
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
void comp_op(unsigned op) { m_comp_op = op; }
unsigned comp_op() const { return m_comp_op; }
//--------------------------------------------------------------------
const int8u* row_ptr(int y) const
template<class PixFmt>
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
{
return m_rbuf->row_ptr(y);
rect_i r(x1, y1, x2, y2);
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
{
int stride = pixf.stride();
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
(r.x2 - r.x1) + 1,
(r.y2 - r.y1) + 1,
stride);
return true;
}
return false;
}
//--------------------------------------------------------------------
const int8u* pix_ptr(int x, int y) const
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
AGG_INLINE int stride() const { return m_rbuf->stride(); }
//--------------------------------------------------------------------
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
//--------------------------------------------------------------------
AGG_INLINE int8u* pix_ptr(int x, int y)
{
return m_rbuf->row_ptr(y) + x * pix_width;
}
AGG_INLINE const int8u* pix_ptr(int x, int y) const
{
return m_rbuf->row_ptr(y) + x * pix_width;
}
//--------------------------------------------------------------------
row_data row(int x, int y) const
{
return m_rbuf->row(y);
}
void comp_op(unsigned op) { m_comp_op = op; }
unsigned comp_op() const { return m_comp_op; }
//--------------------------------------------------------------------
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
@ -2373,6 +2615,23 @@ namespace agg
while(--len);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
do
{
value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
p[order_type::R] = colors->r;
p[order_type::G] = colors->g;
p[order_type::B] = colors->b;
p[order_type::A] = colors->a;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
@ -2518,6 +2777,63 @@ namespace agg
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& from,
const color_type& color,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
value_type* pdst =
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
do
{
blender_type::blend_pix(m_comp_op,
pdst,
color.r, color.g, color.b, color.a,
(*psrc * cover + base_mask) >> base_shift);
++psrc;
pdst += 4;
}
while(--len);
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_lut(const SrcPixelFormatRenderer& from,
const color_type* color_lut,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
if(psrc)
{
value_type* pdst =
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
do
{
const color_type& color = color_lut[*psrc];
blender_type::blend_pix(m_comp_op,
pdst,
color.r, color.g, color.b, color.a,
cover);
++psrc;
pdst += 4;
}
while(--len);
}
}
private:
rbuf_type* m_rbuf;
unsigned m_comp_op;

View file

@ -132,10 +132,10 @@ namespace agg
cell_type** ptr = m_cells + m_num_blocks - 1;
while(m_num_blocks--)
{
delete [] *ptr;
pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
ptr--;
}
delete [] m_cells;
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
}
}
@ -188,10 +188,6 @@ namespace agg
}
*m_curr_cell_ptr++ = m_curr_cell;
++m_num_cells;
//if(m_curr_cell.x < m_min_x) m_min_x = m_curr_cell.x;
//if(m_curr_cell.x > m_max_x) m_max_x = m_curr_cell.x;
//if(m_curr_cell.y < m_min_y) m_min_y = m_curr_cell.y;
//if(m_curr_cell.y > m_max_y) m_max_y = m_curr_cell.y;
}
}
@ -474,16 +470,22 @@ namespace agg
{
if(m_num_blocks >= m_max_blocks)
{
cell_type** new_cells = new cell_type* [m_max_blocks + cell_block_pool];
cell_type** new_cells =
pod_allocator<cell_type*>::allocate(m_max_blocks +
cell_block_pool);
if(m_cells)
{
memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*));
delete [] m_cells;
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
}
m_cells = new_cells;
m_max_blocks += cell_block_pool;
}
m_cells[m_num_blocks++] = new cell_type [unsigned(cell_block_size)];
m_cells[m_num_blocks++] =
pod_allocator<cell_type>::allocate(cell_block_size);
}
m_curr_cell_ptr = m_cells[m_curr_block++];
}
@ -642,7 +644,6 @@ namespace agg
// cell = cell; // Breakpoint here
// }
//}
// Allocate the array of cell pointers
m_sorted_cells.allocate(m_num_cells, 16);
@ -721,6 +722,33 @@ namespace agg
m_sorted = true;
}
//------------------------------------------------------scanline_hit_test
class scanline_hit_test
{
public:
scanline_hit_test(int x) : m_x(x), m_hit(false) {}
void reset_spans() {}
void finalize(int) {}
void add_cell(int x, int)
{
if(m_x == x) m_hit = true;
}
void add_span(int x, int len, int)
{
if(m_x >= x && m_x < x+len) m_hit = true;
}
unsigned num_spans() const { return 1; }
bool hit() const { return m_hit; }
private:
int m_x;
bool m_hit;
};
}
#endif

View file

@ -70,6 +70,15 @@ namespace agg
};
//===========================================================layer_order_e
enum layer_order_e
{
layer_unsorted, //------layer_unsorted
layer_direct, //------layer_direct
layer_inverse //------layer_inverse
};
//==================================================rasterizer_compound_aa
template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa
{
@ -88,6 +97,7 @@ namespace agg
public:
typedef Clip clip_type;
typedef typename Clip::conv_type conv_type;
typedef typename Clip::coord_type coord_type;
enum aa_scale_e
{
@ -103,13 +113,20 @@ namespace agg
m_outline(),
m_clipper(),
m_filling_rule(fill_non_zero),
m_layer_order(layer_direct),
m_styles(), // Active Styles
m_ast(), // Active Style Table (unique values)
m_asm(), // Active Style Mask
m_cells(),
m_cover_buf(),
m_master_alpha(),
m_min_style(0x7FFFFFFF),
m_max_style(-0x7FFFFFFF),
m_scan_y(0x7FFFFFFF)
m_start_x(0),
m_start_y(0),
m_scan_y(0x7FFFFFFF),
m_sl_start(0),
m_sl_len(0)
{}
//--------------------------------------------------------------------
@ -117,6 +134,8 @@ namespace agg
void reset_clipping();
void clip_box(double x1, double y1, double x2, double y2);
void filling_rule(filling_rule_e filling_rule);
void layer_order(layer_order_e order);
void master_alpha(int style, double alpha);
//--------------------------------------------------------------------
void styles(int left, int right);
@ -158,10 +177,18 @@ namespace agg
void sort();
bool rewind_scanlines();
unsigned sweep_styles();
int scanline_start() const { return m_sl_start; }
unsigned scanline_length() const { return m_sl_len; }
unsigned style(unsigned style_idx) const;
cover_type* allocate_cover_buffer(unsigned len);
//--------------------------------------------------------------------
AGG_INLINE unsigned calculate_alpha(int area) const
bool navigate_scanline(int y);
bool hit_test(int tx, int ty);
//--------------------------------------------------------------------
AGG_INLINE unsigned calculate_alpha(int area, unsigned master_alpha) const
{
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
if(cover < 0) cover = -cover;
@ -174,7 +201,7 @@ namespace agg
}
}
if(cover > aa_mask) cover = aa_mask;
return cover;
return (cover * master_alpha + aa_mask) >> aa_shift;
}
//--------------------------------------------------------------------
@ -187,8 +214,17 @@ namespace agg
sl.reset_spans();
if(style_idx < 0) style_idx = 0;
else style_idx++;
unsigned master_alpha = aa_mask;
if(style_idx < 0)
{
style_idx = 0;
}
else
{
style_idx++;
master_alpha = m_master_alpha[m_ast[style_idx] + m_min_style - 1];
}
const style_info& st = m_styles[m_ast[style_idx]];
@ -208,14 +244,16 @@ namespace agg
if(area)
{
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area,
master_alpha);
sl.add_cell(x, alpha);
x++;
}
if(num_cells && cell->x > x)
{
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1),
master_alpha);
if(alpha)
{
sl.add_span(x, cell->x - x, alpha);
@ -226,11 +264,11 @@ namespace agg
if(sl.num_spans() == 0) return false;
sl.finalize(scan_y);
return true;
}
private:
void add_style(int style_id);
void allocate_master_alpha();
//--------------------------------------------------------------------
// Disable copying
@ -242,14 +280,21 @@ namespace agg
rasterizer_cells_aa<cell_style_aa> m_outline;
clip_type m_clipper;
filling_rule_e m_filling_rule;
layer_order_e m_layer_order;
pod_vector<style_info> m_styles; // Active Styles
pod_vector<unsigned> m_ast; // Active Style Table (unique values)
pod_vector<int8u> m_asm; // Active Style Mask
pod_vector<cell_info> m_cells;
pod_vector<cover_type> m_cover_buf;
pod_bvector<unsigned> m_master_alpha;
int m_min_style;
int m_max_style;
coord_type m_start_x;
coord_type m_start_y;
int m_scan_y;
int m_sl_start;
unsigned m_sl_len;
};
@ -269,6 +314,8 @@ namespace agg
m_min_style = 0x7FFFFFFF;
m_max_style = -0x7FFFFFFF;
m_scan_y = 0x7FFFFFFF;
m_sl_start = 0;
m_sl_len = 0;
}
//------------------------------------------------------------------------
@ -278,6 +325,13 @@ namespace agg
m_filling_rule = filling_rule;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::layer_order(layer_order_e order)
{
m_layer_order = order;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1,
@ -316,7 +370,8 @@ namespace agg
void rasterizer_compound_aa<Clip>::move_to(int x, int y)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::downscale(x), conv_type::downscale(y));
m_clipper.move_to(m_start_x = conv_type::downscale(x),
m_start_y = conv_type::downscale(y));
}
//------------------------------------------------------------------------
@ -333,7 +388,8 @@ namespace agg
void rasterizer_compound_aa<Clip>::move_to_d(double x, double y)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::upscale(x), conv_type::upscale(y));
m_clipper.move_to(m_start_x = conv_type::upscale(x),
m_start_y = conv_type::upscale(y));
}
//------------------------------------------------------------------------
@ -354,11 +410,14 @@ namespace agg
move_to_d(x, y);
}
else
{
if(is_vertex(cmd))
{
line_to_d(x, y);
}
else
if(is_close(cmd))
{
m_clipper.line_to(m_outline, m_start_x, m_start_y);
}
}
@ -407,6 +466,7 @@ namespace agg
}
m_scan_y = m_outline.min_y();
m_styles.allocate(m_max_style - m_min_style + 2, 128);
allocate_master_alpha();
return true;
}
@ -453,6 +513,8 @@ namespace agg
m_asm.allocate((num_styles + 7) >> 3, 8);
m_asm.zero();
if(num_cells)
{
// Pre-add zero (for no-fill style, that is, -1).
// We need that to ensure that the "-1 style" would go first.
m_asm[0] |= 1;
@ -462,6 +524,8 @@ namespace agg
style->num_cells = 0;
style->last_x = -0x7FFFFFFF;
m_sl_start = cells[0]->x;
m_sl_len = cells[num_cells-1]->x - m_sl_start + 1;
while(num_cells--)
{
curr_cell = *cells++;
@ -526,10 +590,19 @@ namespace agg
style->num_cells++;
}
}
}
if(m_ast.size() > 1) break;
++m_scan_y;
}
++m_scan_y;
if(m_layer_order != layer_unsorted)
{
range_adaptor<pod_vector<unsigned> > ra(m_ast, 1, m_ast.size() - 1);
if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater);
else quick_sort(ra, unsigned_less);
}
return m_ast.size() - 1;
}
@ -542,6 +615,80 @@ namespace agg
return m_ast[style_idx + 1] + m_min_style - 1;
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_compound_aa<Clip>::navigate_scanline(int y)
{
m_outline.sort_cells();
if(m_outline.total_cells() == 0)
{
return false;
}
if(m_max_style < m_min_style)
{
return false;
}
if(y < m_outline.min_y() || y > m_outline.max_y())
{
return false;
}
m_scan_y = y;
m_styles.allocate(m_max_style - m_min_style + 2, 128);
allocate_master_alpha();
return true;
}
//------------------------------------------------------------------------
template<class Clip>
bool rasterizer_compound_aa<Clip>::hit_test(int tx, int ty)
{
if(!navigate_scanline(ty))
{
return false;
}
unsigned num_styles = sweep_styles();
if(num_styles <= 0)
{
return false;
}
scanline_hit_test sl(tx);
sweep_scanline(sl, -1);
return sl.hit();
}
//------------------------------------------------------------------------
template<class Clip>
cover_type* rasterizer_compound_aa<Clip>::allocate_cover_buffer(unsigned len)
{
m_cover_buf.allocate(len, 256);
return &m_cover_buf[0];
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::allocate_master_alpha()
{
while((int)m_master_alpha.size() <= m_max_style)
{
m_master_alpha.add(aa_mask);
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::master_alpha(int style, double alpha)
{
if(style >= 0)
{
while((int)m_master_alpha.size() <= style)
{
m_master_alpha.add(aa_mask);
}
m_master_alpha[style] = uround(alpha * aa_mask);
}
}
}

View file

@ -23,13 +23,14 @@ namespace agg
template<class Renderer> class rasterizer_outline
{
public:
rasterizer_outline(Renderer& ren) :
explicit rasterizer_outline(Renderer& ren) :
m_ren(&ren),
m_start_x(0),
m_start_y(0),
m_vertices(0)
{
}
{}
void attach(Renderer& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
void move_to(int x, int y)

View file

@ -85,21 +85,21 @@ namespace agg
typedef line_aa_vertex vertex_type;
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
rasterizer_outline_aa(Renderer& ren) :
m_ren(ren),
explicit rasterizer_outline_aa(Renderer& ren) :
m_ren(&ren),
m_line_join(ren.accurate_join_only() ?
outline_miter_accurate_join :
outline_round_join),
m_round_cap(false),
m_start_x(0),
m_start_y(0)
{
}
{}
void attach(Renderer& ren) { m_ren = &ren; }
//------------------------------------------------------------------------
void line_join(outline_aa_join_e join)
{
m_line_join = m_ren.accurate_join_only() ?
m_line_join = m_ren->accurate_join_only() ?
outline_miter_accurate_join :
join;
}
@ -187,7 +187,7 @@ namespace agg
{
for(unsigned i = 0; i < num_paths; i++)
{
m_ren.color(colors[i]);
m_ren->color(colors[i]);
add_path(vs, path_id[i]);
}
}
@ -199,7 +199,7 @@ namespace agg
unsigned i;
for(i = 0; i < c.num_paths(); i++)
{
m_ren.color(c.color(i));
m_ren->color(c.color(i));
add_path(c, i);
}
}
@ -209,7 +209,7 @@ namespace agg
const rasterizer_outline_aa<Renderer, Coord>& operator =
(const rasterizer_outline_aa<Renderer, Coord>&);
Renderer& m_ren;
Renderer* m_ren;
vertex_storage_type m_src_vertices;
outline_aa_join_e m_line_join;
bool m_round_cap;
@ -245,15 +245,15 @@ namespace agg
switch(dv.flags)
{
case 0: m_ren.line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
case 1: m_ren.line2(dv.curr, dv.xb2, dv.yb2); break;
case 2: m_ren.line1(dv.curr, dv.xb1, dv.yb1); break;
case 3: m_ren.line0(dv.curr); break;
case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break;
case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break;
case 3: m_ren->line0(dv.curr); break;
}
if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
{
m_ren.pie(dv.curr.x2, dv.curr.y2,
m_ren->pie(dv.curr.x2, dv.curr.y2,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x2 + (dv.next.y2 - dv.next.y1),
@ -406,16 +406,16 @@ namespace agg
line_parameters lp(x1, y1, x2, y2, lprev);
if(m_round_cap)
{
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
m_ren.line3(lp,
m_ren->line3(lp,
x1 + (y2 - y1),
y1 - (x2 - x1),
x2 + (y2 - y1),
y2 - (x2 - x1));
if(m_round_cap)
{
m_ren.semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
}
}
break;
@ -440,32 +440,32 @@ namespace agg
if(m_round_cap)
{
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
if(m_line_join == outline_round_join)
{
m_ren.line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
x2 + (y2 - y1), y2 - (x2 - x1));
m_ren.pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
x2 + (y3 - y2), y2 - (x3 - x2));
m_ren.line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
x3 + (y3 - y2), y3 - (x3 - x2));
}
else
{
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
m_ren.line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
dv.xb1, dv.yb1);
m_ren.line3(lp2, dv.xb1, dv.yb1,
m_ren->line3(lp2, dv.xb1, dv.yb1,
x3 + (y3 - y2), y3 - (x3 - x2));
}
if(m_round_cap)
{
m_ren.semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
}
}
break;
@ -521,15 +521,15 @@ namespace agg
if(m_round_cap)
{
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
if((dv.flags & 1) == 0)
{
if(m_line_join == outline_round_join)
{
m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
x2 + (y2 - y1), y2 - (x2 - x1));
m_ren.pie(prev.x2, prev.y2,
m_ren->pie(prev.x2, prev.y2,
x2 + (y2 - y1), y2 - (x2 - x1),
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
@ -537,13 +537,13 @@ namespace agg
else
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
dv.xb1, dv.yb1);
}
}
else
{
m_ren.line1(prev,
m_ren->line1(prev,
x1 + (y2 - y1),
y1 - (x2 - x1));
}
@ -558,7 +558,7 @@ namespace agg
{
if(m_line_join == outline_round_join)
{
m_ren.line3(dv.curr,
m_ren->line3(dv.curr,
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
@ -566,20 +566,20 @@ namespace agg
}
else
{
m_ren.line3(dv.curr, dv.xb1, dv.yb1,
m_ren->line3(dv.curr, dv.xb1, dv.yb1,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
}
else
{
m_ren.line2(dv.curr,
m_ren->line2(dv.curr,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
if(m_round_cap)
{
m_ren.semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}

View file

@ -357,7 +357,7 @@ namespace agg
template<class Clip>
void rasterizer_scanline_aa<Clip>::close_polygon()
{
if(m_auto_close && m_status == status_line_to)
if(m_status == status_line_to)
{
m_clipper.line_to(m_outline, m_start_x, m_start_y);
m_status = status_closed;
@ -369,7 +369,7 @@ namespace agg
void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
{
if(m_outline.sorted()) reset();
if(m_status == status_line_to) close_polygon();
if(m_auto_close) close_polygon();
m_clipper.move_to(m_start_x = conv_type::downscale(x),
m_start_y = conv_type::downscale(y));
m_status = status_move_to;
@ -390,7 +390,7 @@ namespace agg
void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
{
if(m_outline.sorted()) reset();
if(m_status == status_line_to) close_polygon();
if(m_auto_close) close_polygon();
m_clipper.move_to(m_start_x = conv_type::upscale(x),
m_start_y = conv_type::upscale(y));
m_status = status_move_to;
@ -415,11 +415,14 @@ namespace agg
move_to_d(x, y);
}
else
{
if(is_vertex(cmd))
{
line_to_d(x, y);
}
else
if(is_close(cmd))
{
close_polygon();
}
}
@ -452,6 +455,7 @@ namespace agg
template<class Clip>
void rasterizer_scanline_aa<Clip>::sort()
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
}
@ -459,7 +463,7 @@ namespace agg
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
{
close_polygon();
if(m_auto_close) close_polygon();
m_outline.sort_cells();
if(m_outline.total_cells() == 0)
{
@ -474,7 +478,7 @@ namespace agg
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
{
close_polygon();
if(m_auto_close) close_polygon();
m_outline.sort_cells();
if(m_outline.total_cells() == 0 ||
y < m_outline.min_y() ||
@ -486,31 +490,6 @@ namespace agg
return true;
}
//------------------------------------------------------scanline_hit_test
class scanline_hit_test
{
public:
scanline_hit_test(int x) : m_x(x), m_hit(false) {}
void reset_spans() {}
void finalize(int) {}
void add_cell(int x, int)
{
if(m_x == x) m_hit = true;
}
void add_span(int x, int len, int)
{
if(m_x >= x && m_x < x+len) m_hit = true;
}
unsigned num_spans() const { return 1; }
bool hit() const { return m_hit; }
private:
int m_x;
bool m_hit;
};
//------------------------------------------------------------------------
template<class Clip>
bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)

View file

@ -36,7 +36,7 @@ namespace agg
//--------------------------------------------------------------------
renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {}
renderer_base(pixfmt_type& ren) :
explicit renderer_base(pixfmt_type& ren) :
m_ren(&ren),
m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
{}
@ -327,6 +327,30 @@ namespace agg
m_ren->copy_color_hspan(x, y, len, colors);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y, int len, const color_type* colors)
{
if(x > xmax()) return;
if(x < xmin()) return;
if(y < ymin())
{
int d = ymin() - y;
len -= d;
if(len <= 0) return;
colors += d;
y = ymin();
}
if(y + len > ymax())
{
len = ymax() - y + 1;
if(len <= 0) return;
}
m_ren->copy_color_vspan(x, y, len, colors);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, int len,
const color_type* colors,
@ -539,6 +563,150 @@ namespace agg
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& src,
const color_type& color,
const rect_i* rect_src_ptr = 0,
int dx = 0,
int dy = 0,
cover_type cover = agg::cover_full)
{
rect_i rsrc(0, 0, src.width(), src.height());
if(rect_src_ptr)
{
rsrc.x1 = rect_src_ptr->x1;
rsrc.y1 = rect_src_ptr->y1;
rsrc.x2 = rect_src_ptr->x2 + 1;
rsrc.y2 = rect_src_ptr->y2 + 1;
}
// Version with xdst, ydst (absolute positioning)
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
// Version with dx, dy (relative positioning)
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
if(rc.x2 > 0)
{
int incy = 1;
if(rdst.y1 > rsrc.y1)
{
rsrc.y1 += rc.y2 - 1;
rdst.y1 += rc.y2 - 1;
incy = -1;
}
while(rc.y2 > 0)
{
typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
if(rw.ptr)
{
int x1src = rsrc.x1;
int x1dst = rdst.x1;
int len = rc.x2;
if(rw.x1 > x1src)
{
x1dst += rw.x1 - x1src;
len -= rw.x1 - x1src;
x1src = rw.x1;
}
if(len > 0)
{
if(x1src + len-1 > rw.x2)
{
len -= x1src + len - rw.x2 - 1;
}
if(len > 0)
{
m_ren->blend_from_color(src,
color,
x1dst, rdst.y1,
x1src, rsrc.y1,
len,
cover);
}
}
}
rdst.y1 += incy;
rsrc.y1 += incy;
--rc.y2;
}
}
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from_lut(const SrcPixelFormatRenderer& src,
const color_type* color_lut,
const rect_i* rect_src_ptr = 0,
int dx = 0,
int dy = 0,
cover_type cover = agg::cover_full)
{
rect_i rsrc(0, 0, src.width(), src.height());
if(rect_src_ptr)
{
rsrc.x1 = rect_src_ptr->x1;
rsrc.y1 = rect_src_ptr->y1;
rsrc.x2 = rect_src_ptr->x2 + 1;
rsrc.y2 = rect_src_ptr->y2 + 1;
}
// Version with xdst, ydst (absolute positioning)
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
// Version with dx, dy (relative positioning)
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
if(rc.x2 > 0)
{
int incy = 1;
if(rdst.y1 > rsrc.y1)
{
rsrc.y1 += rc.y2 - 1;
rdst.y1 += rc.y2 - 1;
incy = -1;
}
while(rc.y2 > 0)
{
typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
if(rw.ptr)
{
int x1src = rsrc.x1;
int x1dst = rdst.x1;
int len = rc.x2;
if(rw.x1 > x1src)
{
x1dst += rw.x1 - x1src;
len -= rw.x1 - x1src;
x1src = rw.x1;
}
if(len > 0)
{
if(x1src + len-1 > rw.x2)
{
len -= x1src + len - rw.x2 - 1;
}
if(len > 0)
{
m_ren->blend_from_lut(src,
color_lut,
x1dst, rdst.y1,
x1src, rsrc.y1,
len,
cover);
}
}
}
rdst.y1 += incy;
rsrc.y1 += incy;
--rc.y2;
}
}
}
private:
pixfmt_type* m_ren;
rect_i m_clip_box;

View file

@ -65,8 +65,7 @@ namespace agg
//--------------------------------------------------------------------
renderer_markers(base_ren_type& rbuf) :
base_type(rbuf)
{
}
{}
//--------------------------------------------------------------------
bool visible(int x, int y, int r) const

View file

@ -37,11 +37,15 @@ namespace agg
typedef renderer_base<pixfmt_type> base_ren_type;
//--------------------------------------------------------------------
renderer_mclip(pixfmt_type& ren) :
m_ren(ren),
explicit renderer_mclip(pixfmt_type& pixf) :
m_ren(pixf),
m_curr_cb(0),
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
{}
void attach(pixfmt_type& pixf)
{
m_ren.attach(pixf);
reset_clipping(true);
}
//--------------------------------------------------------------------

View file

@ -15,7 +15,7 @@
#ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED
#define AGG_RENDERER_OUTLINE_AA_INCLUDED
#include "agg_basics.h"
#include "agg_array.h"
#include "agg_math.h"
#include "agg_line_aa_basics.h"
#include "agg_dda_line.h"
@ -1273,13 +1273,8 @@ namespace agg
aa_mask = aa_scale - 1
};
//---------------------------------------------------------------------
~line_profile_aa() { delete [] m_profile; }
//---------------------------------------------------------------------
line_profile_aa() :
m_size(0),
m_profile(0),
m_subpixel_width(0),
m_min_width(1.0),
m_smoother_width(1.0)
@ -1291,8 +1286,6 @@ namespace agg
//---------------------------------------------------------------------
template<class GammaF>
line_profile_aa(double w, const GammaF& gamma_function) :
m_size(0),
m_profile(0),
m_subpixel_width(0),
m_min_width(1.0),
m_smoother_width(1.0)
@ -1318,7 +1311,7 @@ namespace agg
void width(double w);
unsigned profile_size() const { return m_size; }
unsigned profile_size() const { return m_profile.size(); }
int subpixel_width() const { return m_subpixel_width; }
//---------------------------------------------------------------------
@ -1339,8 +1332,7 @@ namespace agg
void set(double center_width, double smoother_width);
//---------------------------------------------------------------------
unsigned m_size;
value_type* m_profile;
pod_array<value_type> m_profile;
value_type m_gamma[aa_scale];
int m_subpixel_width;
double m_min_width;
@ -1363,8 +1355,8 @@ namespace agg
m_profile(&prof),
m_clip_box(0,0,0,0),
m_clipping(false)
{
}
{}
void attach(base_ren_type& ren) { m_ren = &ren; }
//---------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }
@ -1657,7 +1649,7 @@ namespace agg
}
else
{
while(abs(sx - lp.x1) + abs(sy - lp.y1) > 2 * lp2.len)
while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
{
sx = (lp.x1 + sx) >> 1;
sy = (lp.y1 + sy) >> 1;
@ -1724,7 +1716,7 @@ namespace agg
}
else
{
while(abs(ex - lp.x2) + abs(ey - lp.y2) > 2 * lp2.len)
while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
{
ex = (lp.x2 + ex) >> 1;
ey = (lp.y2 + ey) >> 1;
@ -1796,7 +1788,7 @@ namespace agg
}
else
{
while(abs(sx - lp.x1) + abs(sy - lp.y1) > 2 * lp2.len)
while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
{
sx = (lp.x1 + sx) >> 1;
sy = (lp.y1 + sy) >> 1;
@ -1809,7 +1801,7 @@ namespace agg
}
else
{
while(abs(ex - lp.x2) + abs(ey - lp.y2) > 2 * lp2.len)
while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
{
ex = (lp.x2 + ex) >> 1;
ey = (lp.y2 + ey) >> 1;

View file

@ -15,6 +15,7 @@
#ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
#define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
#include "agg_array.h"
#include "agg_math.h"
#include "agg_line_aa_basics.h"
#include "agg_dda_line.h"
@ -69,18 +70,12 @@ namespace agg
typedef Filter filter_type;
typedef typename filter_type::color_type color_type;
//--------------------------------------------------------------------
~line_image_pattern()
{
delete [] m_data;
}
//--------------------------------------------------------------------
line_image_pattern(const Filter& filter) :
m_filter(&filter),
m_dilation(filter.dilation() + 1),
m_dilation_hr(m_dilation << line_subpixel_shift),
m_data(0),
m_data(),
m_width(0),
m_height(0),
m_width_hr(0),
@ -96,7 +91,7 @@ namespace agg
m_filter(&filter),
m_dilation(filter.dilation() + 1),
m_dilation_hr(m_dilation << line_subpixel_shift),
m_data(0),
m_data(),
m_width(0),
m_height(0),
m_width_hr(0),
@ -117,10 +112,9 @@ namespace agg
m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2;
m_half_height_hr += line_subpixel_scale/2;
delete [] m_data;
m_data = new color_type [(m_width + m_dilation * 2) * (m_height + m_dilation * 2)];
m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2));
m_buf.attach(m_data, m_width + m_dilation * 2,
m_buf.attach(&m_data[0], m_width + m_dilation * 2,
m_height + m_dilation * 2,
m_width + m_dilation * 2);
unsigned x, y;
@ -195,7 +189,7 @@ namespace agg
const filter_type* m_filter;
unsigned m_dilation;
int m_dilation_hr;
color_type* m_data;
pod_array<color_type> m_data;
unsigned m_width;
unsigned m_height;
int m_width_hr;
@ -829,8 +823,8 @@ namespace agg
m_scale_x(1.0),
m_clip_box(0,0,0,0),
m_clipping(false)
{
}
{}
void attach(base_ren_type& ren) { m_ren = &ren; }
//---------------------------------------------------------------------
void pattern(const pattern_type& p) { m_pattern = &p; }
@ -924,10 +918,6 @@ namespace agg
fix_degenerate_bisectrix_start(lp, &sx, &sy);
fix_degenerate_bisectrix_end(lp, &ex, &ey);
//sx = lp.x1 + (lp.y2 - lp.y1);
//sy = lp.y1 - (lp.x2 - lp.x1);
//ex = lp.x2 + (lp.y2 - lp.y1);
//ey = lp.y2 - (lp.x2 - lp.x1);
line_interpolator_image<self_type> li(*this, lp,
sx, sy,
ex, ey,

View file

@ -35,14 +35,14 @@ namespace agg
typedef typename base_ren_type::color_type color_type;
//--------------------------------------------------------------------
renderer_primitives(base_ren_type& ren) :
explicit renderer_primitives(base_ren_type& ren) :
m_ren(&ren),
m_fill_color(),
m_line_color(),
m_curr_x(0),
m_curr_y(0)
{
}
{}
void attach(base_ren_type& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
static int coord(double c)

View file

@ -34,8 +34,8 @@ namespace agg
renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) :
m_ren(&ren),
m_glyph(&glyph)
{
}
{}
void attach(ren_type& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }

View file

@ -52,7 +52,6 @@ namespace agg
}
}
//===============================================render_scanlines_aa_solid
template<class Rasterizer, class Scanline,
class BaseRenderer, class ColorT>
@ -103,7 +102,6 @@ namespace agg
}
}
//==============================================renderer_scanline_aa_solid
template<class BaseRenderer> class renderer_scanline_aa_solid
{
@ -113,7 +111,7 @@ namespace agg
//--------------------------------------------------------------------
renderer_scanline_aa_solid() : m_ren(0) {}
renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {}
explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {}
void attach(base_ren_type& ren)
{
m_ren = &ren;
@ -176,8 +174,6 @@ namespace agg
}
}
//=====================================================render_scanlines_aa
template<class Rasterizer, class Scanline, class BaseRenderer,
class SpanAllocator, class SpanGenerator>
@ -195,8 +191,6 @@ namespace agg
}
}
//====================================================renderer_scanline_aa
template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
class renderer_scanline_aa
@ -244,318 +238,6 @@ namespace agg
/*
//===================================================renderer_scanline_bin
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin
{
public:
typedef BaseRenderer base_ren_type;
typedef SpanGenerator span_gen_type;
//--------------------------------------------------------------------
renderer_scanline_bin() : m_ren(0), m_span_gen(0) {}
renderer_scanline_bin(base_ren_type& ren, span_gen_type& span_gen) :
m_ren(&ren),
m_span_gen(&span_gen)
{}
void attach(base_ren_type& ren, span_gen_type& span_gen)
{
m_ren = &ren;
m_span_gen = &span_gen;
}
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
m_span_gen->prepare(max_span_len);
}
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
int y = sl.y();
m_ren->first_clip_box();
do
{
int xmin = m_ren->xmin();
int xmax = m_ren->xmax();
if(y >= m_ren->ymin() && y <= m_ren->ymax())
{
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
for(;;)
{
int x = span->x;
int len = span->len;
if(len < 0) len = -len;
if(x < xmin)
{
len -= xmin - x;
x = xmin;
}
if(len > 0)
{
if(x + len > xmax)
{
len = xmax - x + 1;
}
if(len > 0)
{
m_ren->blend_color_hspan_no_clip(
x, y, len,
m_span_gen->generate(x, y, len),
0);
}
}
if(--num_spans == 0) break;
++span;
}
}
}
while(m_ren->next_clip_box());
}
private:
base_ren_type* m_ren;
SpanGenerator* m_span_gen;
};
//================================================renderer_scanline_direct
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_direct
{
public:
typedef BaseRenderer base_ren_type;
typedef SpanGenerator span_gen_type;
//--------------------------------------------------------------------
renderer_scanline_direct() : m_ren(0), m_span_gen(0) {}
renderer_scanline_direct(base_ren_type& ren, span_gen_type& span_gen) :
m_ren(&ren),
m_span_gen(&span_gen)
{}
void attach(base_ren_type& ren, span_gen_type& span_gen)
{
m_ren = &ren;
m_span_gen = &span_gen;
}
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
m_span_gen->prepare(max_span_len);
}
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
int y = sl.y();
m_ren->first_clip_box();
do
{
int xmin = m_ren->xmin();
int xmax = m_ren->xmax();
if(y >= m_ren->ymin() && y <= m_ren->ymax())
{
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
for(;;)
{
int x = span->x;
int len = span->len;
if(len < 0) len = -len;
if(x < xmin)
{
len -= xmin - x;
x = xmin;
}
if(len > 0)
{
if(x + len > xmax)
{
len = xmax - x + 1;
}
if(len > 0)
{
span_data span = m_ren->span(x, y, len);
if(span.ptr)
{
m_span_gen->generate(span.x, y, span.len, span.ptr);
}
}
}
if(--num_spans == 0) break;
++span;
}
}
}
while(m_ren->next_clip_box());
}
private:
base_ren_type* m_ren;
SpanGenerator* m_span_gen;
};
//===============================================renderer_scanline_bin_copy
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin_copy
{
public:
typedef BaseRenderer base_ren_type;
typedef SpanGenerator span_gen_type;
//--------------------------------------------------------------------
renderer_scanline_bin_copy() : m_ren(0), m_span_gen(0) {}
renderer_scanline_bin_copy(base_ren_type& ren, span_gen_type& span_gen) :
m_ren(&ren),
m_span_gen(&span_gen)
{}
void attach(base_ren_type& ren, span_gen_type& span_gen)
{
m_ren = &ren;
m_span_gen = &span_gen;
}
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
m_span_gen->prepare(max_span_len);
}
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
int y = sl.y();
m_ren->first_clip_box();
do
{
int xmin = m_ren->xmin();
int xmax = m_ren->xmax();
if(y >= m_ren->ymin() && y <= m_ren->ymax())
{
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
for(;;)
{
int x = span->x;
int len = span->len;
if(len < 0) len = -len;
if(x < xmin)
{
len -= xmin - x;
x = xmin;
}
if(len > 0)
{
if(x + len > xmax)
{
len = xmax - x + 1;
}
if(len > 0)
{
m_ren->copy_color_hspan_no_clip(
x, y, len,
m_span_gen->generate(x, y, len));
}
}
if(--num_spans == 0) break;
++span;
}
}
}
while(m_ren->next_clip_box());
}
private:
base_ren_type* m_ren;
SpanGenerator* m_span_gen;
};
//=============================================renderer_scanline_bin_solid
template<class BaseRenderer> class renderer_scanline_bin_solid
{
public:
typedef BaseRenderer base_ren_type;
typedef typename base_ren_type::color_type color_type;
//--------------------------------------------------------------------
renderer_scanline_bin_solid() : m_ren(0) {}
renderer_scanline_bin_solid(base_ren_type& ren) :
m_ren(&ren)
{}
void attach(base_ren_type& ren)
{
m_ren = &ren;
}
//--------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }
const color_type& color() const { return m_color; }
//--------------------------------------------------------------------
void prepare(unsigned) {}
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
for(;;)
{
m_ren->blend_hline(span->x,
sl.y(),
span->x - 1 + ((span->len < 0) ?
-span->len :
span->len),
m_color,
cover_full);
if(--num_spans == 0) break;
++span;
}
}
private:
base_ren_type* m_ren;
color_type m_color;
};
*/
//===============================================render_scanline_bin_solid
template<class Scanline, class BaseRenderer, class ColorT>
void render_scanline_bin_solid(const Scanline& sl,
@ -578,7 +260,6 @@ namespace agg
}
}
//==============================================render_scanlines_bin_solid
template<class Rasterizer, class Scanline,
class BaseRenderer, class ColorT>
@ -621,7 +302,6 @@ namespace agg
}
}
//=============================================renderer_scanline_bin_solid
template<class BaseRenderer> class renderer_scanline_bin_solid
{
@ -631,7 +311,7 @@ namespace agg
//--------------------------------------------------------------------
renderer_scanline_bin_solid() : m_ren(0) {}
renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {}
explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {}
void attach(base_ren_type& ren)
{
m_ren = &ren;
@ -662,6 +342,92 @@ namespace agg
//======================================================render_scanline_bin
template<class Scanline, class BaseRenderer,
class SpanAllocator, class SpanGenerator>
void render_scanline_bin(const Scanline& sl, BaseRenderer& ren,
SpanAllocator& alloc, SpanGenerator& span_gen)
{
int y = sl.y();
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
for(;;)
{
int x = span->x;
int len = span->len;
if(len < 0) len = -len;
typename BaseRenderer::color_type* colors = alloc.allocate(len);
span_gen.generate(colors, x, y, len);
ren.blend_color_hspan(x, y, len, colors, 0, cover_full);
if(--num_spans == 0) break;
++span;
}
}
//=====================================================render_scanlines_bin
template<class Rasterizer, class Scanline, class BaseRenderer,
class SpanAllocator, class SpanGenerator>
void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
SpanAllocator& alloc, SpanGenerator& span_gen)
{
if(ras.rewind_scanlines())
{
sl.reset(ras.min_x(), ras.max_x());
span_gen.prepare();
while(ras.sweep_scanline(sl))
{
render_scanline_bin(sl, ren, alloc, span_gen);
}
}
}
//====================================================renderer_scanline_bin
template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
class renderer_scanline_bin
{
public:
typedef BaseRenderer base_ren_type;
typedef SpanAllocator alloc_type;
typedef SpanGenerator span_gen_type;
//--------------------------------------------------------------------
renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {}
renderer_scanline_bin(base_ren_type& ren,
alloc_type& alloc,
span_gen_type& span_gen) :
m_ren(&ren),
m_alloc(&alloc),
m_span_gen(&span_gen)
{}
void attach(base_ren_type& ren,
alloc_type& alloc,
span_gen_type& span_gen)
{
m_ren = &ren;
m_alloc = &alloc;
m_span_gen = &span_gen;
}
//--------------------------------------------------------------------
void prepare() { m_span_gen->prepare(); }
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen);
}
private:
base_ren_type* m_ren;
alloc_type* m_alloc;
span_gen_type* m_span_gen;
};
@ -682,7 +448,6 @@ namespace agg
}
}
//========================================================render_all_paths
template<class Rasterizer, class Scanline, class Renderer,
class VertexSource, class ColorStorage, class PathId>
@ -707,6 +472,7 @@ namespace agg
//=============================================render_scanlines_compound
template<class Rasterizer,
class ScanlineAA,
@ -820,8 +586,15 @@ namespace agg
colors = mix_buffer + span_aa->x - min_x;
covers = span_aa->covers;
do
{
if(*covers == cover_full)
{
*colors = c;
}
else
{
colors->add(c, *covers);
}
++colors;
++covers;
}
@ -846,8 +619,15 @@ namespace agg
style);
covers = span_aa->covers;
do
{
if(*covers == cover_full)
{
*colors = *cspan;
}
else
{
colors->add(*cspan, *covers);
}
++cspan;
++colors;
++covers;
@ -875,15 +655,196 @@ namespace agg
if(--num_spans == 0) break;
++span_bin;
}
}
}
}
}
} // if(ras.sweep_scanline(sl_bin, -1))
} // if(num_styles == 1) ... else
} // while((num_styles = ras.sweep_styles()) > 0)
} // if(ras.rewind_scanlines())
}
//=======================================render_scanlines_compound_layered
template<class Rasterizer,
class ScanlineAA,
class BaseRenderer,
class SpanAllocator,
class StyleHandler>
void render_scanlines_compound_layered(Rasterizer& ras,
ScanlineAA& sl_aa,
BaseRenderer& ren,
SpanAllocator& alloc,
StyleHandler& sh)
{
if(ras.rewind_scanlines())
{
int min_x = ras.min_x();
int len = ras.max_x() - min_x + 2;
sl_aa.reset(min_x, ras.max_x());
typedef typename BaseRenderer::color_type color_type;
color_type* color_span = alloc.allocate(len * 2);
color_type* mix_buffer = color_span + len;
cover_type* cover_buffer = ras.allocate_cover_buffer(len);
unsigned num_spans;
unsigned num_styles;
unsigned style;
bool solid;
while((num_styles = ras.sweep_styles()) > 0)
{
typename ScanlineAA::const_iterator span_aa;
if(num_styles == 1)
{
// Optimization for a single style. Happens often
//-------------------------
if(ras.sweep_scanline(sl_aa, 0))
{
style = ras.style(0);
if(sh.is_solid(style))
{
// Just solid fill
//-----------------------
render_scanline_aa_solid(sl_aa, ren, sh.color(style));
}
else
{
// Arbitrary span generator
//-----------------------
span_aa = sl_aa.begin();
num_spans = sl_aa.num_spans();
for(;;)
{
len = span_aa->len;
sh.generate_span(color_span,
span_aa->x,
sl_aa.y(),
len,
style);
ren.blend_color_hspan(span_aa->x,
sl_aa.y(),
span_aa->len,
color_span,
span_aa->covers);
if(--num_spans == 0) break;
++span_aa;
}
}
}
}
else
{
int sl_start = ras.scanline_start();
unsigned sl_len = ras.scanline_length();
if(sl_len)
{
memset(mix_buffer + sl_start - min_x,
0,
sl_len * sizeof(color_type));
memset(cover_buffer + sl_start - min_x,
0,
sl_len * sizeof(cover_type));
int sl_y = 0x7FFFFFFF;
unsigned i;
for(i = 0; i < num_styles; i++)
{
style = ras.style(i);
solid = sh.is_solid(style);
if(ras.sweep_scanline(sl_aa, i))
{
unsigned cover;
color_type* colors;
color_type* cspan;
cover_type* src_covers;
cover_type* dst_covers;
span_aa = sl_aa.begin();
num_spans = sl_aa.num_spans();
sl_y = sl_aa.y();
if(solid)
{
// Just solid fill
//-----------------------
for(;;)
{
color_type c = sh.color(style);
len = span_aa->len;
colors = mix_buffer + span_aa->x - min_x;
src_covers = span_aa->covers;
dst_covers = cover_buffer + span_aa->x - min_x;
do
{
cover = *src_covers;
if(*dst_covers + cover > cover_full)
{
cover = cover_full - *dst_covers;
}
if(cover)
{
colors->add(c, cover);
*dst_covers += cover;
}
++colors;
++src_covers;
++dst_covers;
}
while(--len);
if(--num_spans == 0) break;
++span_aa;
}
}
else
{
// Arbitrary span generator
//-----------------------
for(;;)
{
len = span_aa->len;
colors = mix_buffer + span_aa->x - min_x;
cspan = color_span;
sh.generate_span(cspan,
span_aa->x,
sl_aa.y(),
len,
style);
src_covers = span_aa->covers;
dst_covers = cover_buffer + span_aa->x - min_x;
do
{
cover = *src_covers;
if(*dst_covers + cover > cover_full)
{
cover = cover_full - *dst_covers;
}
if(cover)
{
colors->add(*cspan, cover);
*dst_covers += cover;
}
++cspan;
++colors;
++src_covers;
++dst_covers;
}
while(--len);
if(--num_spans == 0) break;
++span_aa;
}
}
}
}
ren.blend_color_hspan(sl_start,
sl_y,
sl_len,
mix_buffer + sl_start - min_x,
0,
cover_full);
} //if(sl_len)
} //if(num_styles == 1) ... else
} //while((num_styles = ras.sweep_styles()) > 0)
} //if(ras.rewind_scanlines())
}
}

View file

@ -20,102 +20,74 @@
#ifndef AGG_RENDERING_BUFFER_INCLUDED
#define AGG_RENDERING_BUFFER_INCLUDED
#include "agg_basics.h"
#include "agg_array.h"
namespace agg
{
//==========================================================row_ptr_cache
template<class T> class row_ptr_cache
//===========================================================row_accessor
template<class T> class row_accessor
{
public:
//--------------------------------------------------------------------
struct row_data
{
int x1, x2;
const int8u* ptr;
row_data() {}
row_data(int x1_, int x2_, const int8u* ptr_) :
x1(x1_), x2(x2_), ptr(ptr_) {}
};
typedef const_row_info<T> row_data;
//-------------------------------------------------------------------
~row_ptr_cache()
{
delete [] m_rows;
}
//-------------------------------------------------------------------
row_ptr_cache() :
row_accessor() :
m_buf(0),
m_rows(0),
m_start(0),
m_width(0),
m_height(0),
m_stride(0),
m_max_height(0)
m_stride(0)
{
}
//--------------------------------------------------------------------
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
row_accessor(T* buf, unsigned width, unsigned height, int stride) :
m_buf(0),
m_rows(0),
m_start(0),
m_width(0),
m_height(0),
m_stride(0),
m_max_height(0)
m_stride(0)
{
attach(buf, width, height, stride);
}
//--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride)
{
m_buf = buf;
m_buf = m_start = buf;
m_width = width;
m_height = height;
m_stride = stride;
if(height > m_max_height)
{
delete [] m_rows;
m_rows = new T* [m_max_height = height];
}
T* row_ptr = m_buf;
if(stride < 0)
{
row_ptr = m_buf - (height - 1) * stride;
}
T** rows = m_rows;
while(height--)
{
*rows++ = row_ptr;
row_ptr += stride;
m_start = m_buf - int(height - 1) * stride;
}
}
//--------------------------------------------------------------------
T* buf() { return m_buf; }
const T* buf() const { return m_buf; }
unsigned width() const { return m_width; }
unsigned height() const { return m_height; }
int stride() const { return m_stride; }
unsigned stride_abs() const
AGG_INLINE T* buf() { return m_buf; }
AGG_INLINE const T* buf() const { return m_buf; }
AGG_INLINE unsigned width() const { return m_width; }
AGG_INLINE unsigned height() const { return m_height; }
AGG_INLINE int stride() const { return m_stride; }
AGG_INLINE unsigned stride_abs() const
{
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
}
//--------------------------------------------------------------------
T* row_ptr(int, int y, unsigned) { return m_rows[y]; }
T* row_ptr(int y) { return m_rows[y]; }
const T* row_ptr(int y) const { return m_rows[y]; }
row_data row (int y) const { return row_data(0, m_width-1, m_rows[y]); }
//--------------------------------------------------------------------
T const* const* rows() const { return m_rows; }
AGG_INLINE T* row_ptr(int, int y, unsigned)
{
return m_start + y * m_stride;
}
AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; }
AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
AGG_INLINE row_data row (int y) const
{
return row_data(0, m_width-1, row_ptr(y));
}
//--------------------------------------------------------------------
template<class RenBuf>
@ -154,27 +126,173 @@ namespace agg
}
}
private:
//--------------------------------------------------------------------
// Prohibit copying
row_ptr_cache(const row_ptr_cache<T>&);
const row_ptr_cache<T>& operator = (const row_ptr_cache<T>&);
private:
//--------------------------------------------------------------------
T* m_buf; // Pointer to renrdering buffer
T** m_rows; // Pointers to each row of the buffer
T* m_start; // Pointer to first pixel depending on stride
unsigned m_width; // Width in pixels
unsigned m_height; // Height in pixels
int m_stride; // Number of bytes per row. Can be < 0
unsigned m_max_height; // The maximal height (currently allocated)
};
//==========================================================row_ptr_cache
template<class T> class row_ptr_cache
{
public:
typedef const_row_info<T> row_data;
//-------------------------------------------------------------------
row_ptr_cache() :
m_buf(0),
m_rows(),
m_width(0),
m_height(0),
m_stride(0)
{
}
//--------------------------------------------------------------------
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
m_buf(0),
m_rows(),
m_width(0),
m_height(0),
m_stride(0)
{
attach(buf, width, height, stride);
}
//--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride)
{
m_buf = buf;
m_width = width;
m_height = height;
m_stride = stride;
if(height > m_rows.size())
{
m_rows.resize(height);
}
T* row_ptr = m_buf;
if(stride < 0)
{
row_ptr = m_buf - int(height - 1) * stride;
}
T** rows = &m_rows[0];
while(height--)
{
*rows++ = row_ptr;
row_ptr += stride;
}
}
//--------------------------------------------------------------------
AGG_INLINE T* buf() { return m_buf; }
AGG_INLINE const T* buf() const { return m_buf; }
AGG_INLINE unsigned width() const { return m_width; }
AGG_INLINE unsigned height() const { return m_height; }
AGG_INLINE int stride() const { return m_stride; }
AGG_INLINE unsigned stride_abs() const
{
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
}
//--------------------------------------------------------------------
AGG_INLINE T* row_ptr(int, int y, unsigned)
{
return m_rows[y];
}
AGG_INLINE T* row_ptr(int y) { return m_rows[y]; }
AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
AGG_INLINE row_data row (int y) const
{
return row_data(0, m_width-1, m_rows[y]);
}
//--------------------------------------------------------------------
T const* const* rows() const { return &m_rows[0]; }
//--------------------------------------------------------------------
template<class RenBuf>
void copy_from(const RenBuf& src)
{
unsigned h = height();
if(src.height() < h) h = src.height();
unsigned l = stride_abs();
if(src.stride_abs() < l) l = src.stride_abs();
l *= sizeof(T);
unsigned y;
unsigned w = width();
for (y = 0; y < h; y++)
{
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
}
}
//--------------------------------------------------------------------
void clear(T value)
{
unsigned y;
unsigned w = width();
unsigned stride = stride_abs();
for(y = 0; y < height(); y++)
{
T* p = row_ptr(0, y, w);
unsigned x;
for(x = 0; x < stride; x++)
{
*p++ = value;
}
}
}
private:
//--------------------------------------------------------------------
T* m_buf; // Pointer to renrdering buffer
pod_array<T*> m_rows; // Pointers to each row of the buffer
unsigned m_width; // Width in pixels
unsigned m_height; // Height in pixels
int m_stride; // Number of bytes per row. Can be < 0
};
//========================================================rendering_buffer
typedef row_ptr_cache<int8u> rendering_buffer;
//
// The definition of the main type for accessing the rows in the frame
// buffer. It provides functionality to navigate to the rows in a
// rectangular matrix, from top to bottom or from bottom to top depending
// on stride.
//
// row_accessor is cheap to create/destroy, but performs one multiplication
// when calling row_ptr().
//
// row_ptr_cache creates an array of pointers to rows, so, the access
// via row_ptr() may be faster. But it requires memory allocation
// when creating. For example, on typical Intel Pentium hardware
// row_ptr_cache speeds span_image_filter_rgb_nn up to 10%
//
// It's used only in short hand typedefs like pixfmt_rgba32 and can be
// redefined in agg_config.h
// In real applications you can use both, depending on your needs
//------------------------------------------------------------------------
#ifdef AGG_RENDERING_BUFFER
typedef AGG_RENDERING_BUFFER rendering_buffer;
#else
// typedef row_ptr_cache<int8u> rendering_buffer;
typedef row_accessor<int8u> rendering_buffer;
#endif
}

View file

@ -20,8 +20,7 @@
#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_array.h"
namespace agg
{
@ -36,12 +35,7 @@ namespace agg
class rendering_buffer_dynarow
{
public:
//----------------------------------------------------------------------
struct row_data
{
int x1, x2;
const int8u* ptr;
};
typedef row_info<int8u> row_data;
//-------------------------------------------------------------------
~rendering_buffer_dynarow()
@ -51,9 +45,10 @@ namespace agg
//-------------------------------------------------------------------
rendering_buffer_dynarow() :
m_rows(0),
m_rows(),
m_width(0),
m_height(0)
m_height(0),
m_byte_width(0)
{
}
@ -61,12 +56,12 @@ namespace agg
//--------------------------------------------------------------------
rendering_buffer_dynarow(unsigned width, unsigned height,
unsigned byte_width) :
m_rows(new row_data[height]),
m_rows(height),
m_width(width),
m_height(height),
m_byte_width(byte_width)
{
memset(m_rows, 0, sizeof(row_data) * height);
memset(&m_rows[0], 0, sizeof(row_data) * height);
}
// Allocate and clear the buffer
@ -74,16 +69,17 @@ namespace agg
void init(unsigned width, unsigned height, unsigned byte_width)
{
unsigned i;
for(i = 0; i < m_height; ++i) delete [] (int8u*)m_rows[i].ptr;
delete [] m_rows;
m_rows = 0;
for(i = 0; i < m_height; ++i)
{
pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
}
if(width && height)
{
m_width = width;
m_height = height;
m_byte_width = byte_width;
m_rows = new row_data[height];
memset(m_rows, 0, sizeof(row_data) * height);
m_rows.resize(height);
memset(&m_rows[0], 0, sizeof(row_data) * height);
}
}
@ -97,7 +93,7 @@ namespace agg
//--------------------------------------------------------------------
int8u* row_ptr(int x, int y, unsigned len)
{
row_data* r = m_rows + y;
row_data* r = &m_rows[y];
int x2 = x + len - 1;
if(r->ptr)
{
@ -106,7 +102,7 @@ namespace agg
}
else
{
int8u* p = new int8u [m_byte_width];
int8u* p = pod_allocator<int8u>::allocate(m_byte_width);
r->ptr = p;
r->x1 = x;
r->x2 = x2;
@ -128,7 +124,7 @@ namespace agg
private:
//--------------------------------------------------------------------
row_data* m_rows; // Pointers to each row of the buffer
pod_array<row_data> m_rows; // Pointers to each row of the buffer
unsigned m_width; // Width in pixels
unsigned m_height; // Height in pixels
unsigned m_byte_width; // Width in bytes

View file

@ -54,15 +54,9 @@ namespace agg
typedef const span* const_iterator;
//--------------------------------------------------------------------
~scanline_bin()
{
delete [] m_spans;
}
scanline_bin() :
m_max_len(0),
m_last_x(0x7FFFFFF0),
m_spans(0),
m_spans(),
m_cur_span(0)
{
}
@ -71,14 +65,12 @@ namespace agg
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 3;
if(max_len > m_max_len)
if(max_len > m_spans.size())
{
delete [] m_spans;
m_spans = new span [max_len];
m_max_len = max_len;
m_spans.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cur_span = m_spans;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
@ -129,22 +121,21 @@ namespace agg
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cur_span = m_spans;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
const_iterator begin() const { return m_spans + 1; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
const_iterator begin() const { return &m_spans[1]; }
private:
scanline_bin(const scanline_bin&);
const scanline_bin operator = (const scanline_bin&);
unsigned m_max_len;
int m_last_x;
int m_y;
span* m_spans;
pod_array<span> m_spans;
span* m_cur_span;
};

View file

@ -57,19 +57,11 @@ namespace agg
typedef span* iterator;
typedef const span* const_iterator;
//--------------------------------------------------------------------
~scanline_p8()
{
delete [] m_spans;
delete [] m_covers;
}
scanline_p8() :
m_max_len(0),
m_last_x(0x7FFFFFF0),
m_covers(0),
m_covers(),
m_cover_ptr(0),
m_spans(0),
m_spans(),
m_cur_span(0)
{
}
@ -78,17 +70,14 @@ namespace agg
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 3;
if(max_len > m_max_len)
if(max_len > m_spans.size())
{
delete [] m_spans;
delete [] m_covers;
m_covers = new cover_type [max_len];
m_spans = new span [max_len];
m_max_len = max_len;
m_spans.resize(max_len);
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = m_covers;
m_cur_span = m_spans;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
}
@ -160,26 +149,25 @@ namespace agg
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cover_ptr = m_covers;
m_cur_span = m_spans;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
const_iterator begin() const { return m_spans + 1; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
const_iterator begin() const { return &m_spans[1]; }
private:
scanline_p8(const self_type&);
const self_type& operator = (const self_type&);
unsigned m_max_len;
int m_last_x;
int m_y;
cover_type* m_covers;
pod_array<cover_type> m_covers;
cover_type* m_cover_ptr;
span* m_spans;
pod_array<span> m_spans;
span* m_cur_span;
};
@ -231,15 +219,10 @@ namespace agg
};
//--------------------------------------------------------------------
~scanline32_p8()
{
delete [] m_covers;
}
scanline32_p8() :
m_max_len(0),
m_last_x(0x7FFFFFF0),
m_covers(0),
m_covers(),
m_cover_ptr(0)
{
}
@ -248,14 +231,12 @@ namespace agg
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 3;
if(max_len > m_max_len)
if(max_len > m_covers.size())
{
delete [] m_covers;
m_covers = new cover_type[max_len];
m_max_len = max_len;
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = m_covers;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
}
@ -319,7 +300,7 @@ namespace agg
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cover_ptr = m_covers;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
}
@ -335,7 +316,7 @@ namespace agg
unsigned m_max_len;
int m_last_x;
int m_y;
cover_type* m_covers;
pod_array<cover_type> m_covers;
cover_type* m_cover_ptr;
span_array_type m_spans;
};

View file

@ -83,7 +83,8 @@ namespace agg
int i;
for(i = m_extra_storage.size()-1; i >= 0; --i)
{
delete [] m_extra_storage[(unsigned)i].ptr;
pod_allocator<T>::deallocate(m_extra_storage[i].ptr,
m_extra_storage[i].len);
}
m_extra_storage.remove_all();
m_cells.remove_all();
@ -101,7 +102,7 @@ namespace agg
}
extra_span s;
s.len = num_cells;
s.ptr = new T [num_cells];
s.ptr = pod_allocator<T>::allocate(num_cells);
memcpy(s.ptr, cells, sizeof(T) * num_cells);
m_extra_storage.add(s);
return -int(m_extra_storage.size());
@ -142,7 +143,7 @@ namespace agg
const extra_span& src = v.m_extra_storage[i];
extra_span dst;
dst.len = src.len;
dst.ptr = new T [dst.len];
dst.ptr = pod_allocator<T>::allocate(dst.len);
memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
m_extra_storage.add(dst);
}

View file

@ -125,18 +125,9 @@ namespace agg
typedef const span* const_iterator;
//--------------------------------------------------------------------
~scanline_u8()
{
delete [] m_spans;
delete [] m_covers;
}
scanline_u8() :
m_min_x(0),
m_max_len(0),
m_last_x(0x7FFFFFF0),
m_covers(0),
m_spans(0),
m_cur_span(0)
{}
@ -144,17 +135,14 @@ namespace agg
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 2;
if(max_len > m_max_len)
if(max_len > m_spans.size())
{
delete [] m_spans;
delete [] m_covers;
m_covers = new cover_type [max_len];
m_spans = new span [max_len];
m_max_len = max_len;
m_spans.resize(max_len);
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_cur_span = m_spans;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
@ -171,7 +159,7 @@ namespace agg
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = 1;
m_cur_span->covers = m_covers + x;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x;
}
@ -180,7 +168,7 @@ namespace agg
void add_cells(int x, unsigned len, const cover_type* covers)
{
x -= m_min_x;
memcpy(m_covers + x, covers, len * sizeof(cover_type));
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
if(x == m_last_x+1)
{
m_cur_span->len += (coord_type)len;
@ -190,7 +178,7 @@ namespace agg
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = (coord_type)len;
m_cur_span->covers = m_covers + x;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x + len - 1;
}
@ -199,7 +187,7 @@ namespace agg
void add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(m_covers + x, cover, len);
memset(&m_covers[x], cover, len);
if(x == m_last_x+1)
{
m_cur_span->len += (coord_type)len;
@ -209,7 +197,7 @@ namespace agg
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = (coord_type)len;
m_cur_span->covers = m_covers + x;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x + len - 1;
}
@ -224,14 +212,14 @@ namespace agg
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cur_span = m_spans;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
const_iterator begin() const { return m_spans + 1; }
iterator begin() { return m_spans + 1; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
const_iterator begin() const { return &m_spans[1]; }
iterator begin() { return &m_spans[1]; }
private:
scanline_u8(const self_type&);
@ -239,11 +227,10 @@ namespace agg
private:
int m_min_x;
unsigned m_max_len;
int m_last_x;
int m_y;
cover_type* m_covers;
span* m_spans;
pod_array<cover_type> m_covers;
pod_array<span> m_spans;
span* m_cur_span;
};
@ -357,27 +344,19 @@ namespace agg
//--------------------------------------------------------------------
~scanline32_u8()
{
delete [] m_covers;
}
scanline32_u8() :
m_min_x(0),
m_max_len(0),
m_last_x(0x7FFFFFF0),
m_covers(0)
m_covers()
{}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 2;
if(max_len > m_max_len)
if(max_len > m_covers.size())
{
delete [] m_covers;
m_covers = new cover_type [max_len];
m_max_len = max_len;
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
@ -395,7 +374,7 @@ namespace agg
}
else
{
m_spans.add(span(coord_type(x + m_min_x), 1, m_covers + x));
m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
}
m_last_x = x;
}
@ -404,14 +383,16 @@ namespace agg
void add_cells(int x, unsigned len, const cover_type* covers)
{
x -= m_min_x;
memcpy(m_covers + x, covers, len * sizeof(cover_type));
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
if(x == m_last_x+1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x + m_min_x), coord_type(len), m_covers + x));
m_spans.add(span(coord_type(x + m_min_x),
coord_type(len),
&m_covers[x]));
}
m_last_x = x + len - 1;
}
@ -420,14 +401,16 @@ namespace agg
void add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(m_covers + x, cover, len);
memset(&m_covers[x], cover, len);
if(x == m_last_x+1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x + m_min_x), coord_type(len), m_covers + x));
m_spans.add(span(coord_type(x + m_min_x),
coord_type(len),
&m_covers[x]));
}
m_last_x = x + len - 1;
}
@ -457,10 +440,9 @@ namespace agg
private:
int m_min_x;
unsigned m_max_len;
int m_last_x;
int m_y;
cover_type* m_covers;
pod_array<cover_type> m_covers;
span_array_type m_spans;
};

View file

@ -16,7 +16,7 @@
#ifndef AGG_SPAN_ALLOCATOR_INCLUDED
#define AGG_SPAN_ALLOCATOR_INCLUDED
#include "agg_basics.h"
#include "agg_array.h"
namespace agg
{
@ -26,45 +26,25 @@ namespace agg
public:
typedef ColorT color_type;
//--------------------------------------------------------------------
~span_allocator()
{
delete [] m_span;
}
//--------------------------------------------------------------------
span_allocator() :
m_max_span_len(0),
m_span(0)
{
}
//--------------------------------------------------------------------
AGG_INLINE color_type* allocate(unsigned span_len)
{
if(span_len > m_max_span_len)
if(span_len > m_span.size())
{
// To reduce the number of reallocs we align the
// span_len to 256 color elements.
// Well, I just like this number and it looks reasonable.
//-----------------------
delete [] m_span;
span_len = ((span_len + 255) >> 8) << 8;
m_span = new color_type[m_max_span_len = span_len];
m_span.resize(((span_len + 255) >> 8) << 8);
}
return m_span;
return &m_span[0];
}
AGG_INLINE color_type* span() { return m_span; }
AGG_INLINE unsigned max_span_len() const { return m_max_span_len; }
AGG_INLINE color_type* span() { return &m_span[0]; }
AGG_INLINE unsigned max_span_len() const { return m_span.size(); }
private:
//--------------------------------------------------------------------
span_allocator(const span_allocator<ColorT>&);
const span_allocator<ColorT>& operator = (const span_allocator<ColorT>&);
unsigned m_max_span_len;
color_type* m_span;
pod_array<color_type> m_span;
};
}

View file

@ -29,6 +29,9 @@ namespace agg
span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) :
m_span_gen(&span_gen), m_span_cnv(&span_cnv) {}
void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; }
void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; }
//--------------------------------------------------------------------
void prepare()
{

View file

@ -146,6 +146,10 @@ namespace agg
};
//==========================================================gradient_circle
class gradient_circle
{
@ -168,7 +172,6 @@ namespace agg
}
};
//========================================================gradient_radial_d
class gradient_radial_d
{
@ -179,25 +182,24 @@ namespace agg
}
};
//====================================================gradient_radial_focus
class gradient_radial_focus
{
public:
//---------------------------------------------------------------------
gradient_radial_focus() :
m_radius(100 * gradient_subpixel_scale),
m_focus_x(0),
m_focus_y(0)
m_r(100 * gradient_subpixel_scale),
m_fx(0),
m_fy(0)
{
update_values();
}
//---------------------------------------------------------------------
gradient_radial_focus(double r, double fx, double fy) :
m_radius (iround(r * gradient_subpixel_scale)),
m_focus_x(iround(fx * gradient_subpixel_scale)),
m_focus_y(iround(fy * gradient_subpixel_scale))
m_r (iround(r * gradient_subpixel_scale)),
m_fx(iround(fx * gradient_subpixel_scale)),
m_fy(iround(fy * gradient_subpixel_scale))
{
update_values();
}
@ -205,111 +207,62 @@ namespace agg
//---------------------------------------------------------------------
void init(double r, double fx, double fy)
{
m_radius = iround(r * gradient_subpixel_scale);
m_focus_x = iround(fx * gradient_subpixel_scale);
m_focus_y = iround(fy * gradient_subpixel_scale);
m_r = iround(r * gradient_subpixel_scale);
m_fx = iround(fx * gradient_subpixel_scale);
m_fy = iround(fy * gradient_subpixel_scale);
update_values();
}
//---------------------------------------------------------------------
double radius() const { return double(m_radius) / gradient_subpixel_scale; }
double focus_x() const { return double(m_focus_x) / gradient_subpixel_scale; }
double focus_y() const { return double(m_focus_y) / gradient_subpixel_scale; }
double radius() const { return double(m_r) / gradient_subpixel_scale; }
double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
//---------------------------------------------------------------------
int calculate(int x, int y, int) const
{
double solution_x;
double solution_y;
// Special case to avoid divide by zero or very near zero
//---------------------------------
if(x == iround(m_focus_x))
{
solution_x = m_focus_x;
solution_y = 0.0;
solution_y += (y > m_focus_y) ? m_trivial : -m_trivial;
}
else
{
// Slope of the focus-current line
//-------------------------------
double slope = double(y - m_focus_y) / double(x - m_focus_x);
// y-intercept of that same line
//--------------------------------
double yint = double(y) - (slope * x);
// Use the classical quadratic formula to calculate
// the intersection point
//--------------------------------
double a = (slope * slope) + 1;
double b = 2 * slope * yint;
double c = yint * yint - m_radius2;
double det = sqrt((b * b) - (4.0 * a * c));
solution_x = -b;
// Choose the positive or negative root depending
// on where the X coord lies with respect to the focus.
solution_x += (x < m_focus_x) ? -det : det;
solution_x /= 2.0 * a;
// Calculating of Y is trivial
solution_y = (slope * solution_x) + yint;
}
// Calculate the percentage (0...1) of the current point along the
// focus-circumference line and return the normalized (0...d) value
//-------------------------------
solution_x -= double(m_focus_x);
solution_y -= double(m_focus_y);
double int_to_focus = solution_x * solution_x + solution_y * solution_y;
double cur_to_focus = double(x - m_focus_x) * double(x - m_focus_x) +
double(y - m_focus_y) * double(y - m_focus_y);
return iround(sqrt(cur_to_focus / int_to_focus) * m_radius);
double dx = x - m_fx;
double dy = y - m_fy;
double d2 = dx * m_fy - dy * m_fx;
double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul);
}
private:
//---------------------------------------------------------------------
void update_values()
{
// For use in the quadratic equation
//-------------------------------
m_radius2 = double(m_radius) * double(m_radius);
double dist = sqrt(double(m_focus_x) * double(m_focus_x) +
double(m_focus_y) * double(m_focus_y));
// Test if distance from focus to center is greater than the radius
// For the sake of assurance factor restrict the point to be
// no further than 99% of the radius.
//-------------------------------
double r = m_radius * 0.99;
if(dist > r)
// Calculate the invariant values. In case the focal center
// lies exactly on the gradient circle the divisor degenerates
// into zero. In this case we just move the focal center by
// one subpixel unit possibly in the direction to the origin (0,0)
// and calculate the values again.
//-------------------------
m_r2 = double(m_r) * double(m_r);
m_fx2 = double(m_fx) * double(m_fx);
m_fy2 = double(m_fy) * double(m_fy);
double d = (m_r2 - (m_fx2 + m_fy2));
if(d == 0)
{
// clamp focus to radius
// x = r cos theta, y = r sin theta
//------------------------
double a = atan2(double(m_focus_y), double(m_focus_x));
m_focus_x = iround(r * cos(a));
m_focus_y = iround(r * sin(a));
if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; }
if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; }
m_fx2 = double(m_fx) * double(m_fx);
m_fy2 = double(m_fy) * double(m_fy);
d = (m_r2 - (m_fx2 + m_fy2));
}
m_mul = m_r / d;
}
// Calculate the solution to be used in the case where x == focus_x
//------------------------------
m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x));
}
int m_radius;
int m_focus_x;
int m_focus_y;
double m_radius2;
double m_trivial;
int m_r;
int m_fx;
int m_fy;
double m_r2;
double m_fx2;
double m_fy2;
double m_mul;
};
//==============================================================gradient_x
class gradient_x
{
@ -325,7 +278,6 @@ namespace agg
static int calculate(int, int y, int) { return y; }
};
//========================================================gradient_diamond
class gradient_diamond
{
@ -338,7 +290,6 @@ namespace agg
}
};
//=============================================================gradient_xy
class gradient_xy
{
@ -349,7 +300,6 @@ namespace agg
}
};
//========================================================gradient_sqrt_xy
class gradient_sqrt_xy
{
@ -360,7 +310,6 @@ namespace agg
}
};
//==========================================================gradient_conic
class gradient_conic
{
@ -371,7 +320,6 @@ namespace agg
}
};
//=================================================gradient_repeat_adaptor
template<class GradientF> class gradient_repeat_adaptor
{
@ -390,7 +338,6 @@ namespace agg
const GradientF* m_gradient;
};
//================================================gradient_reflect_adaptor
template<class GradientF> class gradient_reflect_adaptor
{

View file

@ -46,6 +46,7 @@ namespace agg
m_dx_int(image_subpixel_scale / 2),
m_dy_int(image_subpixel_scale / 2)
{}
void attach(source_type& v) { m_src = &v; }
//--------------------------------------------------------------------
source_type& source() { return *m_src; }
@ -57,7 +58,6 @@ namespace agg
double filter_dy_dbl() const { return m_dy_dbl; }
//--------------------------------------------------------------------
void set_source(source_type& v) { m_src = &v; }
void interpolator(interpolator_type& v) { m_interpolator = &v; }
void filter(const image_filter_lut& v) { m_filter = &v; }
void filter_offset(double dx, double dy)
@ -136,34 +136,30 @@ namespace agg
base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
m_rx = image_subpixel_scale;
m_ry = image_subpixel_scale;
m_rx_inv = image_subpixel_scale;
m_ry_inv = image_subpixel_scale;
scale_x *= m_blur_x;
scale_y *= m_blur_y;
if(scale_x * scale_y > m_scale_limit)
{
scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
}
if(scale_x > 1.0001)
{
if(scale_x < 1) scale_x = 1;
if(scale_y < 1) scale_y = 1;
if(scale_x > m_scale_limit) scale_x = m_scale_limit;
if(scale_y > m_scale_limit) scale_y = m_scale_limit;
scale_x *= m_blur_x;
scale_y *= m_blur_y;
if(scale_x < 1) scale_x = 1;
if(scale_y < 1) scale_y = 1;
m_rx = uround( scale_x * double(image_subpixel_scale));
m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale));
}
if(scale_y > 1.0001)
{
if(scale_y > m_scale_limit) scale_y = m_scale_limit;
m_ry = uround( scale_y * double(image_subpixel_scale));
m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
}
}
protected:
int m_rx;
@ -219,6 +215,24 @@ namespace agg
m_blur_y = uround(v * double(image_subpixel_scale)); }
protected:
AGG_INLINE void adjust_scale(int* rx, int* ry)
{
if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
if(*rx > image_subpixel_scale * m_scale_limit)
{
*rx = image_subpixel_scale * m_scale_limit;
}
if(*ry > image_subpixel_scale * m_scale_limit)
{
*ry = image_subpixel_scale * m_scale_limit;
}
*rx = (*rx * m_blur_x) >> image_subpixel_shift;
*ry = (*ry * m_blur_y) >> image_subpixel_shift;
if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
}
int m_scale_limit;
int m_blur_x;
int m_blur_y;

View file

@ -676,35 +676,10 @@ namespace agg
int ry_inv = image_subpixel_scale;
base_type::interpolator().coordinates(&x, &y);
base_type::interpolator().local_scale(&rx, &ry);
base_type::adjust_scale(&rx, &ry);
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
if(rx < image_subpixel_scale)
{
rx = image_subpixel_scale;
}
else
{
if(rx > image_subpixel_scale * base_type::m_scale_limit)
{
rx = image_subpixel_scale * base_type::m_scale_limit;
}
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
}
if(ry < image_subpixel_scale)
{
ry = image_subpixel_scale;
}
else
{
if(ry > image_subpixel_scale * base_type::m_scale_limit)
{
ry = image_subpixel_scale * base_type::m_scale_limit;
}
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
}
int radius_x = (diameter * rx) >> 1;
int radius_y = (diameter * ry) >> 1;

View file

@ -808,35 +808,10 @@ namespace agg
int ry_inv = image_subpixel_scale;
base_type::interpolator().coordinates(&x, &y);
base_type::interpolator().local_scale(&rx, &ry);
base_type::adjust_scale(&rx, &ry);
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
if(rx < image_subpixel_scale)
{
rx = image_subpixel_scale;
}
else
{
if(rx > image_subpixel_scale * base_type::m_scale_limit)
{
rx = image_subpixel_scale * base_type::m_scale_limit;
}
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
}
if(ry < image_subpixel_scale)
{
ry = image_subpixel_scale;
}
else
{
if(ry > image_subpixel_scale * base_type::m_scale_limit)
{
ry = image_subpixel_scale * base_type::m_scale_limit;
}
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
}
int radius_x = (diameter * rx) >> 1;
int radius_y = (diameter * ry) >> 1;

View file

@ -832,35 +832,10 @@ namespace agg
int ry_inv = image_subpixel_scale;
base_type::interpolator().coordinates(&x, &y);
base_type::interpolator().local_scale(&rx, &ry);
base_type::adjust_scale(&rx, &ry);
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
if(rx < image_subpixel_scale)
{
rx = image_subpixel_scale;
}
else
{
if(rx > image_subpixel_scale * base_type::m_scale_limit)
{
rx = image_subpixel_scale * base_type::m_scale_limit;
}
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
}
if(ry < image_subpixel_scale)
{
ry = image_subpixel_scale;
}
else
{
if(ry > image_subpixel_scale * base_type::m_scale_limit)
{
ry = image_subpixel_scale * base_type::m_scale_limit;
}
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
}
int radius_x = (diameter * rx) >> 1;
int radius_y = (diameter * ry) >> 1;

View file

@ -50,9 +50,9 @@ namespace agg
{}
//--------------------------------------------------------------------
void attach(source_type& v) { m_src = &v; }
source_type& source() { return *m_src; }
const source_type& source() const { return *m_src; }
void set_source(source_type& v) { m_src = &v; }
//--------------------------------------------------------------------
void offset_x(unsigned v) { m_offset_x = v; }

View file

@ -51,9 +51,9 @@ namespace agg
{}
//--------------------------------------------------------------------
void attach(source_type& v) { m_src = &v; }
source_type& source() { return *m_src; }
const source_type& source() const { return *m_src; }
void set_source(source_type& v) { m_src = &v; }
//--------------------------------------------------------------------
void offset_x(unsigned v) { m_offset_x = v; }

View file

@ -50,9 +50,9 @@ namespace agg
{}
//--------------------------------------------------------------------
void attach(source_type& v) { m_src = &v; }
source_type& source() { return *m_src; }
const source_type& source() const { return *m_src; }
void set_source(source_type& v) { m_src = &v; }
//--------------------------------------------------------------------
void offset_x(unsigned v) { m_offset_x = v; }
@ -75,7 +75,7 @@ namespace agg
span->g = p[order_type::G];
span->b = p[order_type::B];
span->a = p[order_type::A];
p = m_src->next_x();
p = (const value_type*)m_src->next_x();
++span;
}
while(--len);

View file

@ -24,7 +24,7 @@
namespace agg
{
const double affine_epsilon = 1e-14; // About of precision of doubles
const double affine_epsilon = 1e-14;
//============================================================trans_affine
//
@ -84,48 +84,58 @@ namespace agg
// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate
// m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)
//----------------------------------------------------------------------
class trans_affine
struct trans_affine
{
public:
double sx, shy, shx, sy, tx, ty;
//------------------------------------------ Construction
// Construct an identity matrix - it does not transform anything
// Identity matrix
trans_affine() :
m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(0.0)
sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0)
{}
// Construct a custom matrix. Usually used in derived classes
trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) :
m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5)
// Custom matrix. Usually used in derived classes
trans_affine(double v0, double v1, double v2,
double v3, double v4, double v5) :
sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5)
{}
// Construct a matrix to transform a parallelogram to another one.
trans_affine(const double* rect, const double* parl)
{
parl_to_parl(rect, parl);
}
// Custom matrix from m[6]
explicit trans_affine(const double* m) :
sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5])
{}
// Construct a matrix to transform a rectangle to a parallelogram.
// Rectangle to a parallelogram.
trans_affine(double x1, double y1, double x2, double y2,
const double* parl)
{
rect_to_parl(x1, y1, x2, y2, parl);
}
// Construct a matrix to transform a parallelogram to a rectangle.
// Parallelogram to a rectangle.
trans_affine(const double* parl,
double x1, double y1, double x2, double y2)
{
parl_to_rect(parl, x1, y1, x2, y2);
}
// Arbitrary parallelogram transformation.
trans_affine(const double* src, const double* dst)
{
parl_to_parl(src, dst);
}
//---------------------------------- Parellelogram transformations
// Calculate a matrix to transform a parallelogram to another one.
// src and dst are pointers to arrays of three points
// (double[6], x,y,...) that identify three corners of the
// parallelograms assuming implicit fourth points.
// There are also transformations rectangtle to parallelogram and
// parellelogram to rectangle
// transform a parallelogram to another one. Src and dst are
// pointers to arrays of three points (double[6], x1,y1,...) that
// identify three corners of the parallelograms assuming implicit
// fourth point. The arguments are arrays of double[6] mapped
// to x1,y1, x2,y2, x3,y3 where the coordinates are:
// *-----------------*
// / (x3,y3)/
// / /
// /(x1,y1) (x2,y2)/
// *-----------------*
const trans_affine& parl_to_parl(const double* src,
const double* dst);
@ -139,9 +149,15 @@ namespace agg
//------------------------------------------ Operations
// Reset - actually load an identity matrix
// Reset - load an identity matrix
const trans_affine& reset();
// Direct transformations operations
const trans_affine& translate(double x, double y);
const trans_affine& rotate(double a);
const trans_affine& scale(double s);
const trans_affine& scale(double x, double y);
// Multiply matrix to another one
const trans_affine& multiply(const trans_affine& m);
@ -169,38 +185,38 @@ namespace agg
// Store matrix to an array [6] of double
void store_to(double* m) const
{
*m++ = m0; *m++ = m1; *m++ = m2; *m++ = m3; *m++ = m4; *m++ = m5;
*m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty;
}
// Load matrix from an array [6] of double
const trans_affine& load_from(const double* m)
{
m0 = *m++; m1 = *m++; m2 = *m++; m3 = *m++; m4 = *m++; m5 = *m++;
sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++;
return *this;
}
//------------------------------------------- Operators
// Multiply current matrix to another one
// Multiply the matrix by another one
const trans_affine& operator *= (const trans_affine& m)
{
return multiply(m);
}
// Multiply current matrix to inverse of another one
// Multiply the matrix by inverse of another one
const trans_affine& operator /= (const trans_affine& m)
{
return multiply_inv(m);
}
// Multiply current matrix to another one and return
// Multiply the matrix by another one and return
// the result in a separete matrix.
trans_affine operator * (const trans_affine& m)
{
return trans_affine(*this).multiply(m);
}
// Multiply current matrix to inverse of another one
// Multiply the matrix by inverse of another one
// and return the result in a separete matrix.
trans_affine operator / (const trans_affine& m)
{
@ -227,22 +243,28 @@ namespace agg
}
//-------------------------------------------- Transformations
// Direct transformation x and y
// Direct transformation of x and y
void transform(double* x, double* y) const;
// Direct transformation x and y, 2x2 matrix only, no translation
// Direct transformation of x and y, 2x2 matrix only, no translation
void transform_2x2(double* x, double* y) const;
// Inverse transformation x and y. It works slower than the
// direct transformation, so if the performance is critical
// it's better to invert() the matrix and then use transform()
// Inverse transformation of x and y. It works slower than the
// direct transformation. For massive operations it's better to
// invert() the matrix and then use direct transformations.
void inverse_transform(double* x, double* y) const;
//-------------------------------------------- Auxiliary
// Calculate the determinant of matrix
double determinant() const
{
return 1.0 / (m0 * m3 - m1 * m2);
return sx * sy - shy * shx;
}
// Calculate the reciprocal of the determinant
double determinant_reciprocal() const
{
return 1.0 / (sx * sy - shy * shx);
}
// Get the average scale (by X and Y).
@ -250,65 +272,109 @@ namespace agg
// decomposinting curves into line segments.
double scale() const;
// Check to see if the matrix is not degenerate
bool is_valid(double epsilon = affine_epsilon) const;
// Check to see if it's an identity matrix
bool is_identity(double epsilon = affine_epsilon) const;
// Check to see if two matrices are equal
bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
// Determine the major parameters. Use carefully considering degenerate matrices
// Determine the major parameters. Use with caution considering
// possible degenerate cases.
double rotation() const;
void translation(double* dx, double* dy) const;
void scaling(double* sx, double* sy) const;
void scaling_abs(double* sx, double* sy) const
{
*sx = sqrt(m0*m0 + m2*m2);
*sy = sqrt(m1*m1 + m3*m3);
}
private:
double m0;
double m1;
double m2;
double m3;
double m4;
double m5;
void scaling(double* x, double* y) const;
void scaling_abs(double* x, double* y) const;
};
//------------------------------------------------------------------------
inline void trans_affine::transform(double* x, double* y) const
{
register double tx = *x;
*x = tx * m0 + *y * m2 + m4;
*y = tx * m1 + *y * m3 + m5;
register double tmp = *x;
*x = tmp * sx + *y * shx + tx;
*y = tmp * shy + *y * sy + ty;
}
//------------------------------------------------------------------------
inline void trans_affine::transform_2x2(double* x, double* y) const
{
register double tx = *x;
*x = tx * m0 + *y * m2;
*y = tx * m1 + *y * m3;
register double tmp = *x;
*x = tmp * sx + *y * shx;
*y = tmp * shy + *y * sy;
}
//------------------------------------------------------------------------
inline void trans_affine::inverse_transform(double* x, double* y) const
{
register double d = determinant();
register double a = (*x - m4) * d;
register double b = (*y - m5) * d;
*x = a * m3 - b * m2;
*y = b * m0 - a * m1;
register double d = determinant_reciprocal();
register double a = (*x - tx) * d;
register double b = (*y - ty) * d;
*x = a * sy - b * shx;
*y = b * sx - a * shy;
}
//------------------------------------------------------------------------
inline double trans_affine::scale() const
{
double x = 0.707106781 * m0 + 0.707106781 * m2;
double y = 0.707106781 * m1 + 0.707106781 * m3;
double x = 0.707106781 * sx + 0.707106781 * shx;
double y = 0.707106781 * shy + 0.707106781 * sy;
return sqrt(x*x + y*y);
}
//------------------------------------------------------------------------
inline const trans_affine& trans_affine::translate(double x, double y)
{
tx += x;
ty += y;
return *this;
}
//------------------------------------------------------------------------
inline const trans_affine& trans_affine::rotate(double a)
{
double ca = cos(a);
double sa = sin(a);
double t0 = sx * ca - shy * sa;
double t2 = shx * ca - sy * sa;
double t4 = tx * ca - ty * sa;
shy = sx * sa + shy * ca;
sy = shx * sa + sy * ca;
ty = tx * sa + ty * ca;
sx = t0;
shx = t2;
tx = t4;
return *this;
}
//------------------------------------------------------------------------
inline const trans_affine& trans_affine::scale(double x, double y)
{
double mm0 = x; // Possible hint for the optimizer
double mm3 = y;
sx *= mm0;
shx *= mm0;
tx *= mm0;
shy *= mm3;
sy *= mm3;
ty *= mm3;
return *this;
}
//------------------------------------------------------------------------
inline const trans_affine& trans_affine::scale(double s)
{
double m = s; // Possible hint for the optimizer
sx *= m;
shx *= m;
tx *= m;
shy *= m;
sy *= m;
ty *= m;
return *this;
}
//------------------------------------------------------------------------
inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
{
@ -321,8 +387,7 @@ namespace agg
{
trans_affine t = m;
t.invert();
multiply(t);
return *this;
return multiply(t);
}
//------------------------------------------------------------------------
@ -333,6 +398,16 @@ namespace agg
return *this = t.multiply(*this);
}
//------------------------------------------------------------------------
inline void trans_affine::scaling_abs(double* x, double* y) const
{
// Used to calculate scaling coefficients in image resampling.
// When there is considerable shear this method gives us much
// better estimation than just sx, sy.
*x = sqrt(sx * sx + shx * shx);
*y = sqrt(shy * shy + sy * sy);
}
//====================================================trans_affine_rotation
// Rotation matrix. sin() and cos() are calculated twice for the same angle.
// There's no harm because the performance of sin()/cos() is very good on all
@ -347,12 +422,12 @@ namespace agg
};
//====================================================trans_affine_scaling
// Scaling matrix. sx, sy - scale coefficients by X and Y respectively
// Scaling matrix. x, y - scale coefficients by X and Y respectively
class trans_affine_scaling : public trans_affine
{
public:
trans_affine_scaling(double sx, double sy) :
trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0)
trans_affine_scaling(double x, double y) :
trans_affine(x, 0.0, 0.0, y, 0.0, 0.0)
{}
trans_affine_scaling(double s) :
@ -365,8 +440,8 @@ namespace agg
class trans_affine_translation : public trans_affine
{
public:
trans_affine_translation(double tx, double ty) :
trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty)
trans_affine_translation(double x, double y) :
trans_affine(1.0, 0.0, 0.0, 1.0, x, y)
{}
};
@ -375,8 +450,8 @@ namespace agg
class trans_affine_skewing : public trans_affine
{
public:
trans_affine_skewing(double sx, double sy) :
trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0)
trans_affine_skewing(double x, double y) :
trans_affine(1.0, tan(y), tan(x), 1.0, 0.0, 0.0)
{}
};
@ -402,6 +477,40 @@ namespace agg
};
//============================================trans_affine_reflection_unit
// Reflection matrix. Reflect coordinates across the line through
// the origin containing the unit vector (ux, uy).
// Contributed by John Horigan
class trans_affine_reflection_unit : public trans_affine
{
public:
trans_affine_reflection_unit(double ux, double uy) :
trans_affine(2.0 * ux * ux - 1.0,
2.0 * ux * uy,
2.0 * ux * uy,
2.0 * uy * uy - 1.0,
0.0, 0.0)
{}
};
//=================================================trans_affine_reflection
// Reflection matrix. Reflect coordinates across the line through
// the origin at the angle a or containing the non-unit vector (x, y).
// Contributed by John Horigan
class trans_affine_reflection : public trans_affine_reflection_unit
{
public:
trans_affine_reflection(double a) :
trans_affine_reflection_unit(cos(a), sin(a))
{}
trans_affine_reflection(double x, double y) :
trans_affine_reflection_unit(x / sqrt(x * x + y * y), y / sqrt(x * x + y * y))
{}
};
}

View file

@ -19,125 +19,212 @@
#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED
#define AGG_TRANS_PERSPECTIVE_INCLUDED
#include "agg_basics.h"
#include "agg_simul_eq.h"
#include "agg_trans_affine.h"
namespace agg
{
//=======================================================trans_perspective
class trans_perspective
struct trans_perspective
{
public:
//--------------------------------------------------------------------
trans_perspective() : m_valid(false) {}
double sx, shy, w0, shx, sy, w1, tx, ty, w2;
//------------------------------------------------------- Construction
// Identity matrix
trans_perspective() :
sx (1), shy(0), w0(0),
shx(0), sy (1), w1(0),
tx (0), ty (0), w2(1) {}
//--------------------------------------------------------------------
// Arbitrary quadrangle transformations
trans_perspective(const double* src, const double* dst)
{
quad_to_quad(src, dst);
}
// Custom matrix
trans_perspective(double v0, double v1, double v2,
double v3, double v4, double v5,
double v6, double v7, double v8) :
sx (v0), shy(v1), w0(v2),
shx(v3), sy (v4), w1(v5),
tx (v6), ty (v7), w2(v8) {}
// Custom matrix from m[9]
explicit trans_perspective(const double* m) :
sx (m[0]), shy(m[1]), w0(m[2]),
shx(m[3]), sy (m[4]), w1(m[5]),
tx (m[6]), ty (m[7]), w2(m[8]) {}
//--------------------------------------------------------------------
// Direct transformations
// From affine
explicit trans_perspective(const trans_affine& a) :
sx (a.sx ), shy(a.shy), w0(0),
shx(a.shx), sy (a.sy ), w1(0),
tx (a.tx ), ty (a.ty ), w2(1) {}
// Rectangle to quadrilateral
trans_perspective(double x1, double y1, double x2, double y2,
const double* quad)
{
rect_to_quad(x1, y1, x2, y2, quad);
}
const double* quad);
//--------------------------------------------------------------------
// Reverse transformations
// Quadrilateral to rectangle
trans_perspective(const double* quad,
double x1, double y1, double x2, double y2)
double x1, double y1, double x2, double y2);
// Arbitrary quadrilateral transformations
trans_perspective(const double* src, const double* dst);
//-------------------------------------- Quadrilateral transformations
// The arguments are double[8] that are mapped to quadrilaterals:
// x1,y1, x2,y2, x3,y3, x4,y4
bool quad_to_quad(const double* qs, const double* qd);
bool rect_to_quad(double x1, double y1,
double x2, double y2,
const double* q);
bool quad_to_rect(const double* q,
double x1, double y1,
double x2, double y2);
// Map square (0,0,1,1) to the quadrilateral and vice versa
bool square_to_quad(const double* q);
bool quad_to_square(const double* q);
//--------------------------------------------------------- Operations
// Reset - load an identity matrix
const trans_perspective& reset();
// Invert matrix. Returns false in degenerate case
bool invert();
// Direct transformations operations
const trans_perspective& translate(double x, double y);
const trans_perspective& rotate(double a);
const trans_perspective& scale(double s);
const trans_perspective& scale(double x, double y);
// Multiply the matrix by another one
const trans_perspective& multiply(const trans_perspective& m);
// Multiply "m" by "this" and assign the result to "this"
const trans_perspective& premultiply(const trans_perspective& m);
// Multiply matrix to inverse of another one
const trans_perspective& multiply_inv(const trans_perspective& m);
// Multiply inverse of "m" by "this" and assign the result to "this"
const trans_perspective& premultiply_inv(const trans_perspective& m);
// Multiply the matrix by another one
const trans_perspective& multiply(const trans_affine& m);
// Multiply "m" by "this" and assign the result to "this"
const trans_perspective& premultiply(const trans_affine& m);
// Multiply the matrix by inverse of another one
const trans_perspective& multiply_inv(const trans_affine& m);
// Multiply inverse of "m" by "this" and assign the result to "this"
const trans_perspective& premultiply_inv(const trans_affine& m);
//--------------------------------------------------------- Load/Store
void store_to(double* m) const;
const trans_perspective& load_from(const double* m);
//---------------------------------------------------------- Operators
// Multiply the matrix by another one
const trans_perspective& operator *= (const trans_perspective& m)
{
quad_to_rect(quad, x1, y1, x2, y2);
return multiply(m);
}
const trans_perspective& operator *= (const trans_affine& m)
{
return multiply(m);
}
//--------------------------------------------------------------------
// Set the transformations using two arbitrary quadrangles.
void quad_to_quad(const double* src, const double* dst)
// Multiply the matrix by inverse of another one
const trans_perspective& operator /= (const trans_perspective& m)
{
double left[8][8];
double right[8][1];
unsigned i;
for (i = 0; i < 4; i++)
{
unsigned ix = i * 2;
unsigned iy = ix + 1;
left[ix][0] = 1.0;
left[ix][1] = src[ix];
left[ix][2] = src[iy];
left[ix][3] = 0.0;
left[ix][4] = 0.0;
left[ix][5] = 0.0;
left[ix][6] = -src[ix] * dst[ix];
left[ix][7] = -src[iy] * dst[ix];
right[ix][0] = dst[ix];
left[iy][0] = 0.0;
left[iy][1] = 0.0;
left[iy][2] = 0.0;
left[iy][3] = 1.0;
left[iy][4] = src[ix];
left[iy][5] = src[iy];
left[iy][6] = -src[ix] * dst[iy];
left[iy][7] = -src[iy] * dst[iy];
right[iy][0] = dst[iy];
return multiply_inv(m);
}
m_valid = simul_eq<8, 1>::solve(left, right, m_mtx);
const trans_perspective& operator /= (const trans_affine& m)
{
return multiply_inv(m);
}
//--------------------------------------------------------------------
// Set the direct transformations, i.e., rectangle -> quadrangle
void rect_to_quad(double x1, double y1, double x2, double y2,
const double* quad)
// Multiply the matrix by another one and return
// the result in a separete matrix.
trans_perspective operator * (const trans_perspective& m)
{
double src[8];
src[0] = src[6] = x1;
src[2] = src[4] = x2;
src[1] = src[3] = y1;
src[5] = src[7] = y2;
quad_to_quad(src, quad);
return trans_perspective(*this).multiply(m);
}
trans_perspective operator * (const trans_affine& m)
{
return trans_perspective(*this).multiply(m);
}
//--------------------------------------------------------------------
// Set the reverse transformations, i.e., quadrangle -> rectangle
void quad_to_rect(const double* quad,
double x1, double y1, double x2, double y2)
// Multiply the matrix by inverse of another one
// and return the result in a separete matrix.
trans_perspective operator / (const trans_perspective& m)
{
double dst[8];
dst[0] = dst[6] = x1;
dst[2] = dst[4] = x2;
dst[1] = dst[3] = y1;
dst[5] = dst[7] = y2;
quad_to_quad(quad, dst);
return trans_perspective(*this).multiply_inv(m);
}
trans_perspective operator / (const trans_affine& m)
{
return trans_perspective(*this).multiply_inv(m);
}
//--------------------------------------------------------------------
// Check if the equations were solved successfully
bool is_valid() const { return m_valid; }
//--------------------------------------------------------------------
// Transform a point (x, y)
void transform(double* x, double* y) const
// Calculate and return the inverse matrix
trans_perspective operator ~ () const
{
double tx = *x;
double ty = *y;
double d = 1.0 / (m_mtx[6][0] * tx + m_mtx[7][0] * ty + 1.0);
*x = (m_mtx[0][0] + m_mtx[1][0] * tx + m_mtx[2][0] * ty) * d;
*y = (m_mtx[3][0] + m_mtx[4][0] * tx + m_mtx[5][0] * ty) * d;
trans_perspective ret = *this;
ret.invert();
return ret;
}
// Equal operator with default epsilon
bool operator == (const trans_perspective& m) const
{
return is_equal(m, affine_epsilon);
}
// Not Equal operator with default epsilon
bool operator != (const trans_perspective& m) const
{
return !is_equal(m, affine_epsilon);
}
//---------------------------------------------------- Transformations
// Direct transformation of x and y
void transform(double* x, double* y) const;
// Direct transformation of x and y, affine part only
void transform_affine(double* x, double* y) const;
// Direct transformation of x and y, 2x2 matrix only, no translation
void transform_2x2(double* x, double* y) const;
// Inverse transformation of x and y. It works slow because
// it explicitly inverts the matrix on every call. For massive
// operations it's better to invert() the matrix and then use
// direct transformations.
void inverse_transform(double* x, double* y) const;
//---------------------------------------------------------- Auxiliary
const trans_perspective& from_affine(const trans_affine& a);
double determinant() const;
double determinant_reciprocal() const;
bool is_valid(double epsilon = affine_epsilon) const;
bool is_identity(double epsilon = affine_epsilon) const;
bool is_equal(const trans_perspective& m,
double epsilon = affine_epsilon) const;
// Determine the major affine parameters. Use with caution
// considering possible degenerate cases.
double scale() const;
double rotation() const;
void translation(double* dx, double* dy) const;
void scaling(double* x, double* y) const;
void scaling_abs(double* x, double* y) const;
//--------------------------------------------------------------------
class iterator_x
{
@ -153,17 +240,16 @@ namespace agg
double y;
iterator_x() {}
iterator_x(double tx, double ty, double step, const double m[8][1]) :
den(m[6][0] * tx + m[7][0] * ty + 1.0),
den_step(m[6][0] * step),
nom_x(m[0][0] + m[1][0] * tx + m[2][0] * ty),
nom_x_step(m[1][0] * step),
nom_y(m[3][0] + m[4][0] * tx + m[5][0] * ty),
nom_y_step(m[4][0] * step),
iterator_x(double px, double py, double step, const trans_perspective& m) :
den(px * m.w0 + py * m.w1 + m.w2),
den_step(m.w0 * step),
nom_x(px * m.sx + py * m.shx + m.tx),
nom_x_step(step * m.sx),
nom_y(px * m.shy + py * m.sy + m.ty),
nom_y_step(step * m.shy),
x(nom_x / den),
y(nom_y / den)
{
}
{}
void operator ++ ()
{
@ -179,14 +265,467 @@ namespace agg
//--------------------------------------------------------------------
iterator_x begin(double x, double y, double step) const
{
return iterator_x(x, y, step, m_mtx);
return iterator_x(x, y, step, *this);
}
};
//------------------------------------------------------------------------
inline bool trans_perspective::square_to_quad(const double* q)
{
double dx = q[0] - q[2] + q[4] - q[6];
double dy = q[1] - q[3] + q[5] - q[7];
if(dx == 0.0 && dy == 0.0)
{
// Affine case (parallelogram)
//---------------
sx = q[2] - q[0];
shy = q[3] - q[1];
w0 = 0.0;
shx = q[4] - q[2];
sy = q[5] - q[3];
w1 = 0.0;
tx = q[0];
ty = q[1];
w2 = 1.0;
}
else
{
double dx1 = q[2] - q[4];
double dy1 = q[3] - q[5];
double dx2 = q[6] - q[4];
double dy2 = q[7] - q[5];
double den = dx1 * dy2 - dx2 * dy1;
if(den == 0.0)
{
// Singular case
//---------------
sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
return false;
}
// General case
//---------------
double u = (dx * dy2 - dy * dx2) / den;
double v = (dy * dx1 - dx * dy1) / den;
sx = q[2] - q[0] + u * q[2];
shy = q[3] - q[1] + u * q[3];
w0 = u;
shx = q[6] - q[0] + v * q[6];
sy = q[7] - q[1] + v * q[7];
w1 = v;
tx = q[0];
ty = q[1];
w2 = 1.0;
}
return true;
}
//------------------------------------------------------------------------
inline bool trans_perspective::invert()
{
double d0 = sy * w2 - w1 * ty;
double d1 = w0 * ty - shy * w2;
double d2 = shy * w1 - w0 * sy;
double d = sx * d0 + shx * d1 + tx * d2;
if(d == 0.0)
{
sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
return false;
}
d = 1.0 / d;
trans_perspective a = *this;
sx = d * d0;
shy = d * d1;
w0 = d * d2;
shx = d * (a.w1 *a.tx - a.shx*a.w2);
sy = d * (a.sx *a.w2 - a.w0 *a.tx);
w1 = d * (a.w0 *a.shx - a.sx *a.w1);
tx = d * (a.shx*a.ty - a.sy *a.tx);
ty = d * (a.shy*a.tx - a.sx *a.ty);
w2 = d * (a.sx *a.sy - a.shy*a.shx);
return true;
}
//------------------------------------------------------------------------
inline bool trans_perspective::quad_to_square(const double* q)
{
if(!square_to_quad(q)) return false;
invert();
return true;
}
//------------------------------------------------------------------------
inline bool trans_perspective::quad_to_quad(const double* qs,
const double* qd)
{
trans_perspective p;
if(! quad_to_square(qs)) return false;
if(!p.square_to_quad(qd)) return false;
multiply(p);
return true;
}
//------------------------------------------------------------------------
inline bool trans_perspective::rect_to_quad(double x1, double y1,
double x2, double y2,
const double* q)
{
double r[8];
r[0] = r[6] = x1;
r[2] = r[4] = x2;
r[1] = r[3] = y1;
r[5] = r[7] = y2;
return quad_to_quad(r, q);
}
//------------------------------------------------------------------------
inline bool trans_perspective::quad_to_rect(const double* q,
double x1, double y1,
double x2, double y2)
{
double r[8];
r[0] = r[6] = x1;
r[2] = r[4] = x2;
r[1] = r[3] = y1;
r[5] = r[7] = y2;
return quad_to_quad(q, r);
}
//------------------------------------------------------------------------
inline trans_perspective::trans_perspective(double x1, double y1,
double x2, double y2,
const double* quad)
{
rect_to_quad(x1, y1, x2, y2, quad);
}
//------------------------------------------------------------------------
inline trans_perspective::trans_perspective(const double* quad,
double x1, double y1,
double x2, double y2)
{
quad_to_rect(quad, x1, y1, x2, y2);
}
//------------------------------------------------------------------------
inline trans_perspective::trans_perspective(const double* src,
const double* dst)
{
quad_to_quad(src, dst);
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::reset()
{
sx = 1; shy = 0; w0 = 0;
shx = 0; sy = 1; w1 = 0;
tx = 0; ty = 0; w2 = 1;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::multiply(const trans_perspective& a)
{
trans_perspective b = *this;
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::multiply(const trans_affine& a)
{
trans_perspective b = *this;
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::premultiply(const trans_perspective& b)
{
trans_perspective a = *this;
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::premultiply(const trans_affine& b)
{
trans_perspective a = *this;
sx = a.sx *b.sx + a.shx*b.shy;
shx = a.sx *b.shx + a.shx*b.sy;
tx = a.sx *b.tx + a.shx*b.ty + a.tx;
shy = a.shy*b.sx + a.sy *b.shy;
sy = a.shy*b.shx + a.sy *b.sy;
ty = a.shy*b.tx + a.sy *b.ty + a.ty;
w0 = a.w0 *b.sx + a.w1 *b.shy;
w1 = a.w0 *b.shx + a.w1 *b.sy;
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2;
return *this;
}
//------------------------------------------------------------------------
const trans_perspective&
trans_perspective::multiply_inv(const trans_perspective& m)
{
trans_perspective t = m;
t.invert();
return multiply(t);
}
//------------------------------------------------------------------------
const trans_perspective&
trans_perspective::multiply_inv(const trans_affine& m)
{
trans_affine t = m;
t.invert();
return multiply(t);
}
//------------------------------------------------------------------------
const trans_perspective&
trans_perspective::premultiply_inv(const trans_perspective& m)
{
trans_perspective t = m;
t.invert();
return *this = t.multiply(*this);
}
//------------------------------------------------------------------------
const trans_perspective&
trans_perspective::premultiply_inv(const trans_affine& m)
{
trans_perspective t(m);
t.invert();
return *this = t.multiply(*this);
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::translate(double x, double y)
{
tx += x;
ty += y;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::rotate(double a)
{
multiply(trans_affine_rotation(a));
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::scale(double s)
{
multiply(trans_affine_scaling(s));
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::scale(double x, double y)
{
multiply(trans_affine_scaling(x, y));
return *this;
}
//------------------------------------------------------------------------
inline void trans_perspective::transform(double* px, double* py) const
{
double x = *px;
double y = *py;
double m = 1.0 / (x*w0 + y*w1 + w2);
*px = m * (x*sx + y*shx + tx);
*py = m * (x*shy + y*sy + ty);
}
//------------------------------------------------------------------------
inline void trans_perspective::transform_affine(double* x, double* y) const
{
double tmp = *x;
*x = tmp * sx + *y * shx + tx;
*y = tmp * shy + *y * sy + ty;
}
//------------------------------------------------------------------------
inline void trans_perspective::transform_2x2(double* x, double* y) const
{
double tmp = *x;
*x = tmp * sx + *y * shx;
*y = tmp * shy + *y * sy;
}
//------------------------------------------------------------------------
inline void trans_perspective::inverse_transform(double* x, double* y) const
{
trans_perspective t(*this);
if(t.invert()) t.transform(x, y);
}
//------------------------------------------------------------------------
inline void trans_perspective::store_to(double* m) const
{
*m++ = sx; *m++ = shy; *m++ = w0;
*m++ = shx; *m++ = sy; *m++ = w1;
*m++ = tx; *m++ = ty; *m++ = w2;
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::load_from(const double* m)
{
sx = *m++; shy = *m++; w0 = *m++;
shx = *m++; sy = *m++; w1 = *m++;
tx = *m++; ty = *m++; w2 = *m++;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::from_affine(const trans_affine& a)
{
sx = a.sx; shy = a.shy; w0 = 0;
shx = a.shx; sy = a.sy; w1 = 0;
tx = a.tx; ty = a.ty; w2 = 1;
return *this;
}
//------------------------------------------------------------------------
inline double trans_perspective::determinant() const
{
return sx * (sy * w2 - ty * w1) +
shx * (ty * w0 - shy * w2) +
tx * (shy * w1 - sy * w0);
}
//------------------------------------------------------------------------
inline double trans_perspective::determinant_reciprocal() const
{
return 1.0 / determinant();
}
//------------------------------------------------------------------------
inline bool trans_perspective::is_valid(double epsilon) const
{
return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon;
}
//------------------------------------------------------------------------
inline bool trans_perspective::is_identity(double epsilon) const
{
return is_equal_eps(sx, 1.0, epsilon) &&
is_equal_eps(shy, 0.0, epsilon) &&
is_equal_eps(w0, 0.0, epsilon) &&
is_equal_eps(shx, 0.0, epsilon) &&
is_equal_eps(sy, 1.0, epsilon) &&
is_equal_eps(w1, 0.0, epsilon) &&
is_equal_eps(tx, 0.0, epsilon) &&
is_equal_eps(ty, 0.0, epsilon) &&
is_equal_eps(w2, 1.0, epsilon);
}
//------------------------------------------------------------------------
inline bool trans_perspective::is_equal(const trans_perspective& m,
double epsilon) const
{
return is_equal_eps(sx, m.sx, epsilon) &&
is_equal_eps(shy, m.shy, epsilon) &&
is_equal_eps(w0, m.w0, epsilon) &&
is_equal_eps(shx, m.shx, epsilon) &&
is_equal_eps(sy, m.sy, epsilon) &&
is_equal_eps(w1, m.w1, epsilon) &&
is_equal_eps(tx, m.tx, epsilon) &&
is_equal_eps(ty, m.ty, epsilon) &&
is_equal_eps(w2, m.w2, epsilon);
}
//------------------------------------------------------------------------
inline double trans_perspective::scale() const
{
double x = 0.707106781 * sx + 0.707106781 * shx;
double y = 0.707106781 * shy + 0.707106781 * sy;
return sqrt(x*x + y*y);
}
//------------------------------------------------------------------------
inline double trans_perspective::rotation() const
{
double x1 = 0.0;
double y1 = 0.0;
double x2 = 1.0;
double y2 = 0.0;
transform(&x1, &y1);
transform(&x2, &y2);
return atan2(y2-y1, x2-x1);
}
//------------------------------------------------------------------------
void trans_perspective::translation(double* dx, double* dy) const
{
*dx = tx;
*dy = ty;
}
//------------------------------------------------------------------------
void trans_perspective::scaling(double* x, double* y) const
{
double x1 = 0.0;
double y1 = 0.0;
double x2 = 1.0;
double y2 = 1.0;
trans_perspective t(*this);
t *= trans_affine_rotation(-rotation());
t.transform(&x1, &y1);
t.transform(&x2, &y2);
*x = x2 - x1;
*y = y2 - y1;
}
//------------------------------------------------------------------------
void trans_perspective::scaling_abs(double* x, double* y) const
{
*x = sqrt(sx * sx + shx * shx);
*y = sqrt(shy * shy + sy * sy);
}
private:
double m_mtx[8][1];
bool m_valid;
};
}
#endif

View file

@ -33,6 +33,11 @@ namespace agg
void magnification(double m) { m_magn = m; }
void radius(double r) { m_radius = r; }
double xc() const { return m_xc; }
double yc() const { return m_yc; }
double magnification() const { return m_magn; }
double radius() const { return m_radius; }
void transform(double* x, double* y) const;
void inverse_transform(double* x, double* y) const;

View file

@ -43,21 +43,26 @@ namespace agg
vcgen_contour();
void line_join(line_join_e lj) { m_line_join = lj; }
void inner_join(inner_join_e ij) { m_inner_join = ij; }
void width(double w) { m_width = w * 0.5; }
void miter_limit(double ml) { m_miter_limit = ml; }
void miter_limit_theta(double t);
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
void approximation_scale(double as) { m_approx_scale = as; }
void auto_detect_orientation(bool v) { m_auto_detect = v; }
void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
void line_join(line_join_e lj) { m_stroker.line_join(lj); }
void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
line_join_e line_join() const { return m_line_join; }
inner_join_e inner_join() const { return m_inner_join; }
double width() const { return m_width * 2.0; }
double miter_limit() const { return m_miter_limit; }
double inner_miter_limit() const { return m_inner_miter_limit; }
double approximation_scale() const { return m_approx_scale; }
line_cap_e line_cap() const { return m_stroker.line_cap(); }
line_join_e line_join() const { return m_stroker.line_join(); }
inner_join_e inner_join() const { return m_stroker.inner_join(); }
void width(double w) { m_stroker.width(m_width = w); }
void miter_limit(double ml) { m_stroker.miter_limit(ml); }
void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
void approximation_scale(double as) { m_stroker.approximation_scale(as); }
double width() const { return m_width; }
double miter_limit() const { return m_stroker.miter_limit(); }
double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
double approximation_scale() const { return m_stroker.approximation_scale(); }
void auto_detect_orientation(bool v) { m_auto_detect = v; }
bool auto_detect_orientation() const { return m_auto_detect; }
// Generator interface
@ -72,16 +77,10 @@ namespace agg
vcgen_contour(const vcgen_contour&);
const vcgen_contour& operator = (const vcgen_contour&);
math_stroke<coord_storage> m_stroker;
double m_width;
vertex_storage m_src_vertices;
coord_storage m_out_vertices;
double m_width;
line_join_e m_line_join;
inner_join_e m_inner_join;
double m_approx_scale;
double m_abs_width;
double m_signed_width;
double m_miter_limit;
double m_inner_miter_limit;
status_e m_status;
unsigned m_src_vertex;
unsigned m_out_vertex;

View file

@ -51,24 +51,24 @@ namespace agg
vcgen_stroke();
void line_cap(line_cap_e lc) { m_line_cap = lc; }
void line_join(line_join_e lj) { m_line_join = lj; }
void inner_join(inner_join_e ij) { m_inner_join = ij; }
void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
void line_join(line_join_e lj) { m_stroker.line_join(lj); }
void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
line_cap_e line_cap() const { return m_line_cap; }
line_join_e line_join() const { return m_line_join; }
inner_join_e inner_join() const { return m_inner_join; }
line_cap_e line_cap() const { return m_stroker.line_cap(); }
line_join_e line_join() const { return m_stroker.line_join(); }
inner_join_e inner_join() const { return m_stroker.inner_join(); }
void width(double w) { m_width = w * 0.5; }
void miter_limit(double ml) { m_miter_limit = ml; }
void miter_limit_theta(double t);
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
void approximation_scale(double as) { m_approx_scale = as; }
void width(double w) { m_stroker.width(w); }
void miter_limit(double ml) { m_stroker.miter_limit(ml); }
void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
void approximation_scale(double as) { m_stroker.approximation_scale(as); }
double width() const { return m_width * 2.0; }
double miter_limit() const { return m_miter_limit; }
double inner_miter_limit() const { return m_inner_miter_limit; }
double approximation_scale() const { return m_approx_scale; }
double width() const { return m_stroker.width(); }
double miter_limit() const { return m_stroker.miter_limit(); }
double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
double approximation_scale() const { return m_stroker.approximation_scale(); }
void shorten(double s) { m_shorten = s; }
double shorten() const { return m_shorten; }
@ -85,16 +85,10 @@ namespace agg
vcgen_stroke(const vcgen_stroke&);
const vcgen_stroke& operator = (const vcgen_stroke&);
math_stroke<coord_storage> m_stroker;
vertex_storage m_src_vertices;
coord_storage m_out_vertices;
double m_width;
double m_miter_limit;
double m_inner_miter_limit;
double m_approx_scale;
double m_shorten;
line_cap_e m_line_cap;
line_join_e m_line_join;
inner_join_e m_inner_join;
unsigned m_closed;
status_e m_status;
status_e m_prev_status;

View file

@ -30,7 +30,7 @@ namespace agg
// Modified agg::pod_bvector. The data is interpreted as a sequence
// of vertices. It means that the type T must expose:
//
// bool operator() (const T& val)
// bool T::operator() (const T& val)
//
// that is called every time new vertex is being added. The main purpose
// of this operator is the possibility to calculate some values during

View file

@ -17,26 +17,16 @@
//
//----------------------------------------------------------------------------
#include "agg_bspline.h"
namespace agg
{
//------------------------------------------------------------------------
bspline::~bspline()
{
delete [] m_am;
}
//------------------------------------------------------------------------
bspline::bspline() :
m_max(0),
m_num(0),
m_x(0),
m_y(0),
m_am(0),
m_last_idx(-1)
{
}
@ -47,7 +37,6 @@ namespace agg
m_num(0),
m_x(0),
m_y(0),
m_am(0),
m_last_idx(-1)
{
init(num);
@ -59,7 +48,6 @@ namespace agg
m_num(0),
m_x(0),
m_y(0),
m_am(0),
m_last_idx(-1)
{
init(num, x, y);
@ -71,11 +59,10 @@ namespace agg
{
if(max > 2 && max > m_max)
{
delete [] m_am;
m_am = new double[max * 3];
m_am.resize(max * 3);
m_max = max;
m_x = m_am + m_max;
m_y = m_am + m_max * 2;
m_x = &m_am[m_max];
m_y = &m_am[m_max * 2];
}
m_num = 0;
m_last_idx = -1;
@ -103,7 +90,6 @@ namespace agg
double* temp;
double* r;
double* s;
double* al;
double h, p, d, f, e;
for(k = 0; k < m_num; k++)
@ -113,8 +99,8 @@ namespace agg
n1 = 3 * m_num;
al = new double[n1];
temp = al;
pod_array<double> al(n1);
temp = &al[0];
for(k = 0; k < n1; k++)
{
@ -155,7 +141,6 @@ namespace agg
al[k] = al[k] * al[k + 1] + s[k];
m_am[k] = al[k];
}
delete [] al;
}
m_last_idx = -1;
}

View file

@ -82,9 +82,6 @@ namespace agg
m_step = m_num_steps;
}
//------------------------------------------------------------------------
void curve3_inc::rewind(unsigned)
{
@ -100,9 +97,6 @@ namespace agg
m_dfy = m_saved_dfy;
}
//------------------------------------------------------------------------
unsigned curve3_inc::vertex(double* x, double* y)
{
@ -131,7 +125,6 @@ namespace agg
return path_cmd_line_to;
}
//------------------------------------------------------------------------
void curve3_div::init(double x1, double y1,
double x2, double y2,
@ -140,12 +133,10 @@ namespace agg
m_points.remove_all();
m_distance_tolerance_square = 0.5 / m_approximation_scale;
m_distance_tolerance_square *= m_distance_tolerance_square;
m_distance_tolerance_manhattan = 4.0 / m_approximation_scale;
bezier(x1, y1, x2, y2, x3, y3);
m_count = 0;
}
//------------------------------------------------------------------------
void curve3_div::recursive_bezier(double x1, double y1,
double x2, double y2,
@ -169,10 +160,11 @@ namespace agg
double dx = x3-x1;
double dy = y3-y1;
double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx));
double da;
if(d > curve_collinearity_epsilon)
{
// Regular care
// Regular case
//-----------------
if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
@ -187,7 +179,7 @@ namespace agg
// Angle & Cusp Condition
//----------------------
double da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
if(da >= pi) da = 2*pi - da;
if(da < m_angle_tolerance)
@ -201,10 +193,29 @@ namespace agg
}
else
{
if(fabs(x1 + x3 - x2 - x2) +
fabs(y1 + y3 - y2 - y2) <= m_distance_tolerance_manhattan)
// Collinear case
//------------------
da = dx*dx + dy*dy;
if(da == 0)
{
m_points.add(point_d(x123, y123));
d = calc_sq_distance(x1, y1, x2, y2);
}
else
{
d = ((x2 - x1)*dx + (y2 - y1)*dy) / da;
if(d > 0 && d < 1)
{
// Simple collinear case, 1---2---3
// We can leave just two endpoints
return;
}
if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1);
else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3);
else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy);
}
if(d < m_distance_tolerance_square)
{
m_points.add(point_d(x2, y2));
return;
}
}
@ -307,9 +318,6 @@ namespace agg
m_step = m_num_steps;
}
//------------------------------------------------------------------------
void curve4_inc::rewind(unsigned)
{
@ -327,10 +335,6 @@ namespace agg
m_ddfy = m_saved_ddfy;
}
//------------------------------------------------------------------------
unsigned curve4_inc::vertex(double* x, double* y)
{
@ -376,12 +380,10 @@ namespace agg
m_points.remove_all();
m_distance_tolerance_square = 0.5 / m_approximation_scale;
m_distance_tolerance_square *= m_distance_tolerance_square;
m_distance_tolerance_manhattan = 4.0 / m_approximation_scale;
bezier(x1, y1, x2, y2, x3, y3, x4, y4);
m_count = 0;
}
//------------------------------------------------------------------------
void curve4_div::recursive_bezier(double x1, double y1,
double x2, double y2,
@ -409,6 +411,7 @@ namespace agg
double x1234 = (x123 + x234) / 2;
double y1234 = (y123 + y234) / 2;
// Try to approximate the full cubic curve by a single straight line
//------------------
double dx = x4-x1;
@ -416,7 +419,7 @@ namespace agg
double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx));
double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx));
double da1, da2;
double da1, da2, k;
switch((int(d2 > curve_collinearity_epsilon) << 1) +
int(d3 > curve_collinearity_epsilon))
@ -424,18 +427,55 @@ namespace agg
case 0:
// All collinear OR p1==p4
//----------------------
if(fabs(x1 + x3 - x2 - x2) +
fabs(y1 + y3 - y2 - y2) +
fabs(x2 + x4 - x3 - x3) +
fabs(y2 + y4 - y3 - y3) <= m_distance_tolerance_manhattan)
k = dx*dx + dy*dy;
if(k == 0)
{
m_points.add(point_d(x1234, y1234));
d2 = calc_sq_distance(x1, y1, x2, y2);
d3 = calc_sq_distance(x4, y4, x3, y3);
}
else
{
k = 1 / k;
da1 = x2 - x1;
da2 = y2 - y1;
d2 = k * (da1*dx + da2*dy);
da1 = x3 - x1;
da2 = y3 - y1;
d3 = k * (da1*dx + da2*dy);
if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
{
// Simple collinear case, 1---2---3---4
// We can leave just two endpoints
return;
}
if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1);
else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4);
else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy);
if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1);
else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4);
else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy);
}
if(d2 > d3)
{
if(d2 < m_distance_tolerance_square)
{
m_points.add(point_d(x2, y2));
return;
}
}
else
{
if(d3 < m_distance_tolerance_square)
{
m_points.add(point_d(x3, y3));
return;
}
}
break;
case 1:
// p1,p2,p4 are collinear, p3 is considerable
// p1,p2,p4 are collinear, p3 is significant
//----------------------
if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
@ -469,7 +509,7 @@ namespace agg
break;
case 2:
// p1,p3,p4 are collinear, p2 is considerable
// p1,p3,p4 are collinear, p2 is significant
//----------------------
if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
@ -503,7 +543,7 @@ namespace agg
break;
case 3:
// Regular care
// Regular case
//-----------------
if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
@ -518,9 +558,9 @@ namespace agg
// Angle & Cusp Condition
//----------------------
double a23 = atan2(y3 - y2, x3 - x2);
da1 = fabs(a23 - atan2(y2 - y1, x2 - x1));
da2 = fabs(atan2(y4 - y3, x4 - x3) - a23);
k = atan2(y3 - y2, x3 - x2);
da1 = fabs(k - atan2(y2 - y1, x2 - x1));
da2 = fabs(atan2(y4 - y3, x4 - x3) - k);
if(da1 >= pi) da1 = 2*pi - da1;
if(da2 >= pi) da2 = 2*pi - da2;

View file

@ -19,6 +19,8 @@
#include <string.h>
#include <stdio.h>
#include "agg_gsv_text.h"
#include "agg_bounding_rect.h"
namespace agg
@ -480,16 +482,6 @@ namespace agg
0xf6,0xfa,0x04,0x06,0x08,0xfa
};
//-------------------------------------------------------------------------
gsv_text::~gsv_text()
{
if(m_loaded_font) delete [] m_loaded_font;
if(m_text_buf) delete [] m_text_buf;
}
//-------------------------------------------------------------------------
gsv_text::gsv_text() :
m_x(0.0),
@ -500,11 +492,10 @@ namespace agg
m_space(0.0),
m_line_space(0.0),
m_text(m_chr),
m_text_buf(0),
m_buf_size(0),
m_text_buf(),
m_cur_chr(m_chr),
m_font(gsv_default_font),
m_loaded_font(0),
m_loaded_font(),
m_status(initial),
m_big_endian(false),
m_flip(false)
@ -515,13 +506,11 @@ namespace agg
if(*(char*)&t == 0) m_big_endian = true;
}
//-------------------------------------------------------------------------
void gsv_text::font(const void* font)
{
m_font = font;
if(m_font == 0) m_font = m_loaded_font;
if(m_font == 0) m_font = &m_loaded_font[0];
}
//-------------------------------------------------------------------------
@ -551,13 +540,10 @@ namespace agg
//if(m_flip) m_y += m_height;
}
//-------------------------------------------------------------------------
void gsv_text::load_font(const char* file)
{
if(m_loaded_font) delete [] m_loaded_font;
m_loaded_font = 0;
m_loaded_font.resize(0);
FILE* fd = fopen(file, "rb");
if(fd)
{
@ -568,15 +554,14 @@ namespace agg
fseek(fd, 0l, SEEK_SET);
if(len > 0)
{
m_loaded_font = new char [len];
fread(m_loaded_font, 1, len, fd);
m_font = m_loaded_font;
m_loaded_font.resize(len);
fread(&m_loaded_font[0], 1, len, fd);
m_font = &m_loaded_font[0];
}
fclose(fd);
}
}
//-------------------------------------------------------------------------
void gsv_text::text(const char* text)
{
@ -587,17 +572,14 @@ namespace agg
return;
}
unsigned new_size = strlen(text) + 1;
if(new_size > m_buf_size)
if(new_size > m_text_buf.size())
{
if(m_text_buf) delete [] m_text_buf;
m_text_buf = new char [m_buf_size = new_size];
m_text_buf.resize(new_size);
}
memcpy(m_text_buf, text, new_size);
m_text = m_text_buf;
memcpy(&m_text_buf[0], text, new_size);
m_text = &m_text_buf[0];
}
//-------------------------------------------------------------------------
void gsv_text::rewind(unsigned)
{
@ -614,7 +596,6 @@ namespace agg
m_cur_chr = m_text;
}
//-------------------------------------------------------------------------
unsigned gsv_text::vertex(double* x, double* y)
{
@ -623,7 +604,6 @@ namespace agg
int dx, dy;
bool quit = false;
while(!quit)
{
switch(m_status)
@ -683,6 +663,13 @@ namespace agg
return path_cmd_stop;
}
//-------------------------------------------------------------------------
double gsv_text::text_width()
{
double x1, y1, x2, y2;
bounding_rect_single(*this, 0, &x1, &y1, &x2, &y2);
return x2 - x1;
}
}

View file

@ -23,20 +23,6 @@
namespace agg
{
//--------------------------------------------------------------------
image_filter_lut::~image_filter_lut()
{
delete [] m_weight_array;
}
//--------------------------------------------------------------------
image_filter_lut::image_filter_lut() :
m_weight_array(0),
m_max_size(0)
{}
//--------------------------------------------------------------------
void image_filter_lut::realloc_lut(double radius)
{
@ -44,11 +30,9 @@ namespace agg
m_diameter = uceil(radius) * 2;
m_start = -int(m_diameter / 2 - 1);
unsigned size = m_diameter << image_subpixel_shift;
if(size > m_max_size)
if(size > m_weight_array.size())
{
delete [] m_weight_array;
m_weight_array = new int16 [size];
m_max_size = size;
m_weight_array.resize(size);
}
}

View file

@ -42,8 +42,8 @@ namespace agg
// [2] | [3]
// <3>
// 0,1,2,3,4,5,6,7
int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 };
int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 };
const int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 };
const int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 };

View file

@ -44,12 +44,11 @@ namespace agg
{
m_subpixel_width = uround(w * subpixel_scale);
unsigned size = m_subpixel_width + subpixel_scale * 6;
if(size > m_size)
if(size > m_profile.size())
{
delete [] m_profile;
m_profile = new value_type[m_size = size];
m_profile.resize(size);
}
return m_profile;
return &m_profile[0];
}

View file

@ -21,7 +21,7 @@
namespace agg
{
int16u g_sqrt_table[1024] =
int16u g_sqrt_table[1024] = //----------g_sqrt_table
{
0,
2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444,
@ -100,7 +100,7 @@ namespace agg
};
int8 g_elder_bit_table[256] =
int8 g_elder_bit_table[256] = //---------g_elder_bit_table
{
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,

View file

@ -27,12 +27,12 @@ namespace agg
const trans_affine& trans_affine::parl_to_parl(const double* src,
const double* dst)
{
m0 = src[2] - src[0];
m1 = src[3] - src[1];
m2 = src[4] - src[0];
m3 = src[5] - src[1];
m4 = src[0];
m5 = src[1];
sx = src[2] - src[0];
shy = src[3] - src[1];
shx = src[4] - src[0];
sy = src[5] - src[1];
tx = src[0];
ty = src[1];
invert();
multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1],
dst[4] - dst[0], dst[5] - dst[1],
@ -69,15 +69,15 @@ namespace agg
//------------------------------------------------------------------------
const trans_affine& trans_affine::multiply(const trans_affine& m)
{
double t0 = m0 * m.m0 + m1 * m.m2;
double t2 = m2 * m.m0 + m3 * m.m2;
double t4 = m4 * m.m0 + m5 * m.m2 + m.m4;
m1 = m0 * m.m1 + m1 * m.m3;
m3 = m2 * m.m1 + m3 * m.m3;
m5 = m4 * m.m1 + m5 * m.m3 + m.m5;
m0 = t0;
m2 = t2;
m4 = t4;
double t0 = sx * m.sx + shy * m.shx;
double t2 = shx * m.sx + sy * m.shx;
double t4 = tx * m.sx + ty * m.shx + m.tx;
shy = sx * m.shy + shy * m.sy;
sy = shx * m.shy + sy * m.sy;
ty = tx * m.shy + ty * m.sy + m.ty;
sx = t0;
shx = t2;
tx = t4;
return *this;
}
@ -85,18 +85,18 @@ namespace agg
//------------------------------------------------------------------------
const trans_affine& trans_affine::invert()
{
double d = determinant();
double d = determinant_reciprocal();
double t0 = m3 * d;
m3 = m0 * d;
m1 = -m1 * d;
m2 = -m2 * d;
double t0 = sy * d;
sy = sx * d;
shy = -shy * d;
shx = -shx * d;
double t4 = -m4 * t0 - m5 * m2;
m5 = -m4 * m1 - m5 * m3;
double t4 = -tx * t0 - ty * shx;
ty = -tx * shy - ty * sy;
m0 = t0;
m4 = t4;
sx = t0;
tx = t4;
return *this;
}
@ -104,55 +104,55 @@ namespace agg
//------------------------------------------------------------------------
const trans_affine& trans_affine::flip_x()
{
m0 = -m0;
m1 = -m1;
m4 = -m4;
sx = -sx;
shy = -shy;
tx = -tx;
return *this;
}
//------------------------------------------------------------------------
const trans_affine& trans_affine::flip_y()
{
m2 = -m2;
m3 = -m3;
m5 = -m5;
shx = -shx;
sy = -sy;
ty = -ty;
return *this;
}
//------------------------------------------------------------------------
const trans_affine& trans_affine::reset()
{
m0 = m3 = 1.0;
m1 = m2 = m4 = m5 = 0.0;
sx = sy = 1.0;
shy = shx = tx = ty = 0.0;
return *this;
}
//------------------------------------------------------------------------
inline bool is_equal_eps(double v1, double v2, double epsilon)
{
return fabs(v1 - v2) < epsilon;
}
//------------------------------------------------------------------------
bool trans_affine::is_identity(double epsilon) const
{
return is_equal_eps(m0, 1.0, epsilon) &&
is_equal_eps(m1, 0.0, epsilon) &&
is_equal_eps(m2, 0.0, epsilon) &&
is_equal_eps(m3, 1.0, epsilon) &&
is_equal_eps(m4, 0.0, epsilon) &&
is_equal_eps(m5, 0.0, epsilon);
return is_equal_eps(sx, 1.0, epsilon) &&
is_equal_eps(shy, 0.0, epsilon) &&
is_equal_eps(shx, 0.0, epsilon) &&
is_equal_eps(sy, 1.0, epsilon) &&
is_equal_eps(tx, 0.0, epsilon) &&
is_equal_eps(ty, 0.0, epsilon);
}
//------------------------------------------------------------------------
bool trans_affine::is_valid(double epsilon) const
{
return fabs(sx) > epsilon && fabs(sy) > epsilon;
}
//------------------------------------------------------------------------
bool trans_affine::is_equal(const trans_affine& m, double epsilon) const
{
return is_equal_eps(m0, m.m0, epsilon) &&
is_equal_eps(m1, m.m1, epsilon) &&
is_equal_eps(m2, m.m2, epsilon) &&
is_equal_eps(m3, m.m3, epsilon) &&
is_equal_eps(m4, m.m4, epsilon) &&
is_equal_eps(m5, m.m5, epsilon);
return is_equal_eps(sx, m.sx, epsilon) &&
is_equal_eps(shy, m.shy, epsilon) &&
is_equal_eps(shx, m.shx, epsilon) &&
is_equal_eps(sy, m.sy, epsilon) &&
is_equal_eps(tx, m.tx, epsilon) &&
is_equal_eps(ty, m.ty, epsilon);
}
//------------------------------------------------------------------------
@ -170,13 +170,12 @@ namespace agg
//------------------------------------------------------------------------
void trans_affine::translation(double* dx, double* dy) const
{
trans_affine t(*this);
t *= trans_affine_rotation(-rotation());
t.transform(dx, dy);
*dx = tx;
*dy = ty;
}
//------------------------------------------------------------------------
void trans_affine::scaling(double* sx, double* sy) const
void trans_affine::scaling(double* x, double* y) const
{
double x1 = 0.0;
double y1 = 0.0;
@ -186,8 +185,8 @@ namespace agg
t *= trans_affine_rotation(-rotation());
t.transform(&x1, &y1);
t.transform(&x2, &y2);
*sx = x2 - x1;
*sy = y2 - y1;
*x = x2 - x1;
*y = y2 - y1;
}

View file

@ -40,10 +40,30 @@ namespace agg
//------------------------------------------------------------------------
void trans_warp_magnifier::inverse_transform(double* x, double* y) const
{
trans_warp_magnifier t(*this);
t.magnification(1.0 / m_magn);
t.radius(m_radius * m_magn);
t.transform(x, y);
// New version by Andrew Skalkin
//-----------------
double dx = *x - m_xc;
double dy = *y - m_yc;
double r = sqrt(dx * dx + dy * dy);
if(r < m_radius * m_magn)
{
*x = m_xc + dx / m_magn;
*y = m_yc + dy / m_magn;
}
else
{
double rnew = r - m_radius * (m_magn - 1.0);
*x = m_xc + rnew * dx / r;
*y = m_yc + rnew * dy / r;
}
// Old version
//-----------------
//trans_warp_magnifier t(*this);
//t.magnification(1.0 / m_magn);
//t.radius(m_radius * m_magn);
//t.transform(x, y);
}

View file

@ -25,16 +25,10 @@ namespace agg
//------------------------------------------------------------------------
vcgen_contour::vcgen_contour() :
m_stroker(),
m_width(1),
m_src_vertices(),
m_out_vertices(),
m_width(1.0),
m_line_join(bevel_join),
m_inner_join(inner_miter),
m_approx_scale(1.0),
m_abs_width(1.0),
m_signed_width(1.0),
m_miter_limit(4.0),
m_inner_miter_limit(1.0 + 1.0/64.0),
m_status(initial),
m_src_vertex(0),
m_closed(0),
@ -43,26 +37,15 @@ namespace agg
{
}
//------------------------------------------------------------------------
void vcgen_contour::remove_all()
{
m_src_vertices.remove_all();
m_closed = 0;
m_orientation = 0;
m_abs_width = fabs(m_width);
m_signed_width = m_width;
m_status = initial;
}
//------------------------------------------------------------------------
void vcgen_contour::miter_limit_theta(double t)
{
m_miter_limit = 1.0 / sin(t * 0.5) ;
}
//------------------------------------------------------------------------
void vcgen_contour::add_vertex(double x, double y, unsigned cmd)
{
@ -91,14 +74,12 @@ namespace agg
}
}
//------------------------------------------------------------------------
void vcgen_contour::rewind(unsigned)
{
if(m_status == initial)
{
m_src_vertices.close(true);
m_signed_width = m_width;
if(m_auto_detect)
{
if(!is_oriented(m_orientation))
@ -110,14 +91,13 @@ namespace agg
}
if(is_oriented(m_orientation))
{
m_signed_width = is_ccw(m_orientation) ? m_width : -m_width;
m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width);
}
}
m_status = ready;
m_src_vertex = 0;
}
//------------------------------------------------------------------------
unsigned vcgen_contour::vertex(double* x, double* y)
{
@ -146,18 +126,12 @@ namespace agg
m_status = end_poly;
break;
}
stroke_calc_join(m_out_vertices,
m_stroker.calc_join(m_out_vertices,
m_src_vertices.prev(m_src_vertex),
m_src_vertices.curr(m_src_vertex),
m_src_vertices.next(m_src_vertex),
m_src_vertices.prev(m_src_vertex).dist,
m_src_vertices.curr(m_src_vertex).dist,
m_signed_width,
m_line_join,
m_inner_join,
m_miter_limit,
m_inner_miter_limit,
m_approx_scale);
m_src_vertices.curr(m_src_vertex).dist);
++m_src_vertex;
m_status = out_vertices;
m_out_vertex = 0;

View file

@ -25,16 +25,10 @@ namespace agg
//------------------------------------------------------------------------
vcgen_stroke::vcgen_stroke() :
m_stroker(),
m_src_vertices(),
m_out_vertices(),
m_width(0.5),
m_miter_limit(4.0),
m_inner_miter_limit(1.01),
m_approx_scale(1.0),
m_shorten(0.0),
m_line_cap(butt_cap),
m_line_join(miter_join),
m_inner_join(inner_miter),
m_closed(0),
m_status(initial),
m_src_vertex(0),
@ -42,14 +36,6 @@ namespace agg
{
}
//------------------------------------------------------------------------
void vcgen_stroke::miter_limit_theta(double t)
{
m_miter_limit = 1.0 / sin(t * 0.5) ;
}
//------------------------------------------------------------------------
void vcgen_stroke::remove_all()
{
@ -80,22 +66,6 @@ namespace agg
}
}
//------------------------------------------------------------------------
static inline void calc_butt_cap(double* cap,
const vertex_dist& v0,
const vertex_dist& v1,
double len,
double width)
{
double dx = (v1.y - v0.y) * width / len;
double dy = (v1.x - v0.x) * width / len;
cap[0] = v0.x - dx;
cap[1] = v0.y + dy;
cap[2] = v0.x + dx;
cap[3] = v0.y - dy;
}
//------------------------------------------------------------------------
void vcgen_stroke::rewind(unsigned)
{
@ -135,13 +105,10 @@ namespace agg
break;
case cap1:
stroke_calc_cap(m_out_vertices,
m_stroker.calc_cap(m_out_vertices,
m_src_vertices[0],
m_src_vertices[1],
m_src_vertices[0].dist,
m_line_cap,
m_width,
m_approx_scale);
m_src_vertices[0].dist);
m_src_vertex = 1;
m_prev_status = outline1;
m_status = out_vertices;
@ -149,13 +116,10 @@ namespace agg
break;
case cap2:
stroke_calc_cap(m_out_vertices,
m_stroker.calc_cap(m_out_vertices,
m_src_vertices[m_src_vertices.size() - 1],
m_src_vertices[m_src_vertices.size() - 2],
m_src_vertices[m_src_vertices.size() - 2].dist,
m_line_cap,
m_width,
m_approx_scale);
m_src_vertices[m_src_vertices.size() - 2].dist);
m_prev_status = outline2;
m_status = out_vertices;
m_out_vertex = 0;
@ -179,18 +143,12 @@ namespace agg
break;
}
}
stroke_calc_join(m_out_vertices,
m_stroker.calc_join(m_out_vertices,
m_src_vertices.prev(m_src_vertex),
m_src_vertices.curr(m_src_vertex),
m_src_vertices.next(m_src_vertex),
m_src_vertices.prev(m_src_vertex).dist,
m_src_vertices.curr(m_src_vertex).dist,
m_width,
m_line_join,
m_inner_join,
m_miter_limit,
m_inner_miter_limit,
m_approx_scale);
m_src_vertices.curr(m_src_vertex).dist);
++m_src_vertex;
m_prev_status = m_status;
m_status = out_vertices;
@ -210,18 +168,12 @@ namespace agg
}
--m_src_vertex;
stroke_calc_join(m_out_vertices,
m_stroker.calc_join(m_out_vertices,
m_src_vertices.next(m_src_vertex),
m_src_vertices.curr(m_src_vertex),
m_src_vertices.prev(m_src_vertex),
m_src_vertices.curr(m_src_vertex).dist,
m_src_vertices.prev(m_src_vertex).dist,
m_width,
m_line_join,
m_inner_join,
m_miter_limit,
m_inner_miter_limit,
m_approx_scale);
m_src_vertices.prev(m_src_vertex).dist);
m_prev_status = m_status;
m_status = out_vertices;

View file

@ -290,7 +290,6 @@ popplaces_text_symbolizer.set_label_placement=label_placement.POINT_PLACEMENT
popplaces_text_symbolizer.halo_fill = Color('white')
popplaces_text_symbolizer.halo_radius = 1
popplaces_rule.symbols.append(popplaces_text_symbolizer)
popplaces_rule.symbols.append(PointSymbolizer("/home/artem/dot.png","png",10,10))
popplaces_style.rules.append(popplaces_rule)

View file

@ -146,7 +146,7 @@ namespace mapnik
unsigned width = pixmap_.width();
unsigned height = pixmap_.height();
path_type path(t_,*geom,prj_trans);
agg::row_ptr_cache<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
agg::pixfmt_rgba32 pixf(buf);
ren_base renb(pixf);
@ -179,7 +179,7 @@ namespace mapnik
if (geom && geom->num_points() > 1)
{
path_type path(t_,*geom,prj_trans);
agg::row_ptr_cache<agg::int8u> buf(pixmap_.raw_data(),
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(),
pixmap_.width(),
pixmap_.height(),
pixmap_.width()*4);
@ -389,7 +389,7 @@ namespace mapnik
unsigned height = pixmap_.height();
ImageData32 const& pat = sym.get_pattern();
path_type path(t_,*geom,prj_trans);
agg::row_ptr_cache<agg::int8u> buf(pixmap_.raw_data(), width, height,width*4);
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(), width, height,width*4);
agg::pixfmt_rgba32 pixf(buf);
renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter;
@ -429,13 +429,13 @@ namespace mapnik
unsigned height = pixmap_.height();
path_type path(t_,*geom,prj_trans);
agg::row_ptr_cache<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
agg::pixfmt_rgba32 pixf(buf);
ren_base renb(pixf);
unsigned w=pattern.width();
unsigned h=pattern.height();
agg::row_ptr_cache<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4);
agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4);
double x0,y0;
path.vertex(&x0,&y0);
@ -445,7 +445,8 @@ namespace mapnik
unsigned offset_y = unsigned(height - y0);
agg::span_allocator<agg::rgba8> sa;
img_source_type img_src(pattern_rbuf);
agg::pixfmt_rgba32 pixf_pattern(pattern_rbuf);
img_source_type img_src(pixf_pattern);
span_gen_type sg(img_src, offset_x, offset_y);
renderer_type rp(renb,sa, sg);

View file

@ -126,16 +126,23 @@ namespace mapnik
if ( sym.first == "PointSymbolizer")
{
std::string file =
sym.second.get<std::string>("<xmlattr>.file");
std::string type =
sym.second.get<std::string>("<xmlattr>.type");
unsigned width =
sym.second.get<unsigned>("<xmlattr>.width");
unsigned height =
sym.second.get<unsigned>("<xmlattr>.height");
boost::optional<std::string> file =
sym.second.get_optional<std::string>("<xmlattr>.file");
boost::optional<std::string> type =
sym.second.get_optional<std::string>("<xmlattr>.type");
boost::optional<unsigned> width =
sym.second.get_optional<unsigned>("<xmlattr>.width");
boost::optional<unsigned> height =
sym.second.get_optional<unsigned>("<xmlattr>.height");
rule.append(point_symbolizer(file,type,width,height));
if (file && type && width && height)
{
rule.append(point_symbolizer(*file,*type,*width,*height));
}
else
{
rule.append(point_symbolizer());
}
}
else if ( sym.first == "LinePatternSymbolizer")
{