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

View file

@ -109,20 +109,27 @@ namespace agg
typedef T value_type; typedef T value_type;
typedef pod_array<T> self_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() : 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) : 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); memcpy(m_array, v.m_array, sizeof(T) * m_size);
} }
void resize(unsigned size) void resize(unsigned size)
{ {
if(size != m_size) if(size != m_size)
{ {
delete [] m_array; pod_allocator<T>::deallocate(m_array, m_size);
m_array = new T[m_size = size]; m_array = pod_allocator<T>::allocate(m_size = size);
} }
} }
const self_type& operator = (const self_type& v) const self_type& operator = (const self_type& v)
@ -157,7 +164,7 @@ namespace agg
public: public:
typedef T value_type; 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() : m_size(0), m_capacity(0), m_array(0) {}
pod_vector(unsigned cap, unsigned extra_tail=0); pod_vector(unsigned cap, unsigned extra_tail=0);
@ -215,9 +222,9 @@ namespace agg
m_size = 0; m_size = 0;
if(cap > m_capacity) if(cap > m_capacity)
{ {
delete [] m_array; pod_allocator<T>::deallocate(m_array, m_capacity);
m_capacity = cap + extra_tail; 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) 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)); memcpy(data, m_array, m_size * sizeof(T));
delete [] m_array; pod_allocator<T>::deallocate(m_array, m_capacity);
m_array = data; m_array = data;
} }
} }
@ -252,13 +259,15 @@ namespace agg
//------------------------------------------------------------------------ //------------------------------------------------------------------------
template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) : 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) : template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) :
m_size(v.m_size), m_size(v.m_size),
m_capacity(v.m_capacity), 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); 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; T** blk = m_blocks + m_num_blocks - 1;
while(m_num_blocks--) while(m_num_blocks--)
{ {
delete [] *blk; pod_allocator<T>::deallocate(*blk, block_size);
--blk; --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; unsigned nb = (size + block_mask) >> block_shift;
while(m_num_blocks > nb) 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; m_size = size;
} }
@ -562,13 +577,15 @@ namespace agg
m_size(v.m_size), m_size(v.m_size),
m_num_blocks(v.m_num_blocks), m_num_blocks(v.m_num_blocks),
m_max_blocks(v.m_max_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) m_block_ptr_inc(v.m_block_ptr_inc)
{ {
unsigned i; unsigned i;
for(i = 0; i < v.m_num_blocks; ++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)); memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
} }
} }
@ -599,7 +616,7 @@ namespace agg
{ {
if(nb >= m_max_blocks) 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) if(m_blocks)
{ {
@ -607,12 +624,12 @@ namespace agg
m_blocks, m_blocks,
m_num_blocks * sizeof(T*)); m_num_blocks * sizeof(T*));
delete [] m_blocks; pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
} }
m_blocks = new_blocks; m_blocks = new_blocks;
m_max_blocks += m_block_ptr_inc; 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++; m_num_blocks++;
} }
@ -753,7 +770,7 @@ namespace agg
} }
//-----------------------------------------------------------pod_allocator //---------------------------------------------------------block_allocator
// Allocator for arbitrary POD data. Most usable in different cache // Allocator for arbitrary POD data. Most usable in different cache
// systems for efficient memory allocations. // systems for efficient memory allocations.
// Memory is allocated with blocks of fixed size ("block_size" in // 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 // 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. // 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: public:
void remove_all() void remove_all()
{ {
if(m_num_blocks) 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--) while(m_num_blocks--)
{ {
delete [] *blk; pod_allocator<int8u>::deallocate(blk->data, blk->size);
--blk; --blk;
} }
delete [] m_blocks; pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
} }
m_num_blocks = 0; m_num_blocks = 0;
m_max_blocks = 0; m_max_blocks = 0;
@ -783,12 +806,12 @@ namespace agg
m_rest = 0; m_rest = 0;
} }
~pod_allocator() ~block_allocator()
{ {
remove_all(); 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_size(block_size),
m_block_ptr_inc(block_ptr_inc), m_block_ptr_inc(block_ptr_inc),
m_num_blocks(0), m_num_blocks(0),
@ -808,7 +831,9 @@ namespace agg
int8u* ptr = m_buf_ptr; int8u* ptr = m_buf_ptr;
if(alignment > 1) if(alignment > 1)
{ {
unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment; unsigned align =
(alignment - unsigned((size_t)ptr) % alignment) % alignment;
size += align; size += align;
ptr += align; ptr += align;
if(size <= m_rest) if(size <= m_rest)
@ -835,20 +860,25 @@ namespace agg
if(size < m_block_size) size = m_block_size; if(size < m_block_size) size = m_block_size;
if(m_num_blocks >= m_max_blocks) 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) if(m_blocks)
{ {
memcpy(new_blocks, memcpy(new_blocks,
m_blocks, m_blocks,
m_num_blocks * sizeof(int8u*)); m_num_blocks * sizeof(block_type));
pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
delete [] m_blocks;
} }
m_blocks = new_blocks; m_blocks = new_blocks;
m_max_blocks += m_block_ptr_inc; 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_num_blocks++;
m_rest = size; m_rest = size;
} }
@ -857,7 +887,7 @@ namespace agg
unsigned m_block_ptr_inc; unsigned m_block_ptr_inc;
unsigned m_num_blocks; unsigned m_num_blocks;
unsigned m_max_blocks; unsigned m_max_blocks;
int8u** m_blocks; block_type* m_blocks;
int8u* m_buf_ptr; int8u* m_buf_ptr;
unsigned m_rest; unsigned m_rest;
}; };
@ -1014,7 +1044,6 @@ namespace agg
return j; return j;
} }
//--------------------------------------------------------invert_container //--------------------------------------------------------invert_container
template<class Array> void invert_container(Array& arr) template<class Array> void invert_container(Array& arr)
{ {
@ -1026,7 +1055,6 @@ namespace agg
} }
} }
//------------------------------------------------------binary_search_pos //------------------------------------------------------binary_search_pos
template<class Array, class Value, class Less> template<class Array, class Value, class Less>
unsigned binary_search_pos(const Array& arr, const Value& val, Less less) unsigned binary_search_pos(const Array& arr, const Value& val, Less less)
@ -1052,6 +1080,40 @@ namespace agg
return end; 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 #endif

View file

@ -19,6 +19,43 @@
#include <math.h> #include <math.h>
#include "agg_config.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 //-------------------------------------------------------- Default basic types
// //
// If the compiler has different capacity of the basic types you can redefine // 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" #pragma warning(disable : 4035) //Disable warning "no return value"
AGG_INLINE int iround(double v) //-------iround AGG_INLINE int iround(double v) //-------iround
{ {
int t;
__asm fld qword ptr [v] __asm fld qword ptr [v]
__asm fistp dword ptr [ebp-8] __asm fistp dword ptr [t]
__asm mov eax, dword ptr [ebp-8] __asm mov eax, dword ptr [t]
} }
AGG_INLINE unsigned uround(double v) //-------uround AGG_INLINE unsigned uround(double v) //-------uround
{ {
unsigned t;
__asm fld qword ptr [v] __asm fld qword ptr [v]
__asm fistp dword ptr [ebp-8] __asm fistp dword ptr [t]
__asm mov eax, dword ptr [ebp-8] __asm mov eax, dword ptr [t]
} }
#pragma warning(pop) #pragma warning(pop)
AGG_INLINE unsigned ufloor(double v) //-------ufloor AGG_INLINE unsigned ufloor(double v) //-------ufloor
@ -218,16 +257,19 @@ namespace agg
//----------------------------------------------------------------rect_base //----------------------------------------------------------------rect_base
template<class T> struct rect_base template<class T> struct rect_base
{ {
typedef T value_type;
typedef rect_base<T> self_type; typedef rect_base<T> self_type;
T x1; T x1, y1, x2, y2;
T y1;
T x2;
T y2;
rect_base() {} rect_base() {}
rect_base(T x1_, T y1_, T x2_, T y2_) : rect_base(T x1_, T y1_, T x2_, T y2_) :
x1(x1_), y1(y1_), x2(x2_), y2(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() const self_type& normalize()
{ {
T t; T t;
@ -249,6 +291,11 @@ namespace agg
{ {
return x1 <= x2 && y1 <= y2; return x1 <= x2 && y1 <= y2;
} }
bool hit_test(T x, T y) const
{
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
}
}; };
//-----------------------------------------------------intersect_rectangles //-----------------------------------------------------intersect_rectangles
@ -451,6 +498,31 @@ namespace agg
typedef vertex_base<float> vertex_f; //-----vertex_f typedef vertex_base<float> vertex_f; //-----vertex_f
typedef vertex_base<double> vertex_d; //-----vertex_d 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 #ifndef AGG_BSPLINE_INCLUDED
#define AGG_BSPLINE_INCLUDED #define AGG_BSPLINE_INCLUDED
#include "agg_basics.h" #include "agg_array.h"
namespace agg namespace agg
{ {
@ -40,7 +40,6 @@ namespace agg
class bspline class bspline
{ {
public: public:
~bspline();
bspline(); bspline();
bspline(int num); bspline(int num);
bspline(int num, const double* x, const double* y); bspline(int num, const double* x, const double* y);
@ -67,7 +66,7 @@ namespace agg
int m_num; int m_num;
double* m_x; double* m_x;
double* m_y; double* m_y;
double* m_am; pod_array<double> m_am;
mutable int m_last_idx; mutable int m_last_idx;
}; };

View file

@ -148,7 +148,7 @@ namespace agg
return *this; return *this;
} }
calc_type v_ = (calc_type(v) * base_mask) / a; 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; return *this;
} }
@ -162,6 +162,31 @@ namespace agg
return ret; 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); } static self_type no_color() { return self_type(0,0); }
}; };
@ -324,6 +349,31 @@ namespace agg
return ret; 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); } 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) inline rgba8 rgb8_packed(unsigned v)
{ {
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
} }
//-----------------------------------------------------------bgr8_packed //-------------------------------------------------------------bgr8_packed
inline rgba8 bgr8_packed(unsigned v) inline rgba8 bgr8_packed(unsigned v)
{ {
return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
} }
//----------------------------------------------------------argb8_packed //------------------------------------------------------------argb8_packed
inline rgba8 argb8_packed(unsigned v) inline rgba8 argb8_packed(unsigned v)
{ {
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); 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 struct rgba16
{ {
typedef int16u value_type; typedef int16u value_type;
@ -709,6 +720,22 @@ namespace agg
return rgba16(c,a).premultiply(); 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 #ifndef AGG_CONFIG_INCLUDED
#define 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_INT8
// AGG_INT8U // AGG_INT8U
@ -23,4 +26,20 @@
// but it won't result any crash and the rest of the library will remain // but it won't result any crash and the rest of the library will remain
// fully functional. // 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 #endif

View file

@ -45,12 +45,11 @@ namespace agg
}; };
public: public:
conv_adaptor_vcgen(VertexSource& source) : explicit conv_adaptor_vcgen(VertexSource& source) :
m_source(&source), m_source(&source),
m_status(initial) m_status(initial)
{} {}
void attach(VertexSource& source) { m_source = &source; }
void set_source(VertexSource& source) { m_source = &source; }
Generator& generator() { return m_generator; } Generator& generator() { return m_generator; }
const Generator& generator() const { 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 template<class VertexSource, class VPGen> class conv_adaptor_vpgen
{ {
public: public:
conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
void attach(VertexSource& source) { m_source = &source; }
void set_source(VertexSource& source) { m_source = &source; }
VPGen& vpgen() { return m_vpgen; } VPGen& vpgen() { return m_vpgen; }
const VPGen& vpgen() const { 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 template<class VertexSource> class conv_close_polygon
{ {
public: public:
conv_close_polygon(VertexSource& vs) : m_source(&vs) {} explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
void attach(VertexSource& source) { m_source = &source; }
void set_source(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id); void rewind(unsigned path_id);
unsigned vertex(double* x, double* y); unsigned vertex(double* x, double* y);

View file

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

View file

@ -60,10 +60,9 @@ namespace agg
typedef Curve4 curve4_type; typedef Curve4 curve4_type;
typedef conv_curve<VertexSource, Curve3, Curve4> self_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) {} m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
void attach(VertexSource& source) { m_source = &source; }
void set_source(VertexSource& source) { m_source = &source; }
void approximation_method(curve_approximation_method_e v) void approximation_method(curve_approximation_method_e v)
{ {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -142,8 +142,8 @@ namespace agg
int octant; int octant;
//--------------------------------------------------------------------- //---------------------------------------------------------------------
static int8u s_orthogonal_quadrant[8]; static const int8u s_orthogonal_quadrant[8];
static int8u s_diagonal_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); return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
} }
//--------------------------------------------------------point_in_triangle //--------------------------------------------------------point_in_triangle
AGG_INLINE bool point_in_triangle(double x1, double y1, AGG_INLINE bool point_in_triangle(double x1, double y1,
double x2, double y2, double x2, double y2,
@ -54,7 +53,6 @@ namespace agg
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
} }
//-----------------------------------------------------------calc_distance //-----------------------------------------------------------calc_distance
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) 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); 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 //------------------------------------------------calc_line_point_distance
AGG_INLINE double calc_line_point_distance(double x1, double y1, 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; 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 //-------------------------------------------------------calc_intersection
AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by, AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
@ -94,7 +146,6 @@ namespace agg
return true; return true;
} }
//-----------------------------------------------------intersection_exists //-----------------------------------------------------intersection_exists
AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2, AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
double x3, double y3, double x4, double y4) 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; //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
} }
//--------------------------------------------------------calc_orthogonal //--------------------------------------------------------calc_orthogonal
AGG_INLINE void calc_orthogonal(double thickness, AGG_INLINE void calc_orthogonal(double thickness,
double x1, double y1, double x1, double y1,
@ -133,10 +183,9 @@ namespace agg
double dy = y2 - y1; double dy = y2 - y1;
double d = sqrt(dx*dx + dy*dy); double d = sqrt(dx*dx + dy*dy);
*x = thickness * dy / d; *x = thickness * dy / d;
*y = thickness * dx / d; *y = -thickness * dx / d;
} }
//--------------------------------------------------------dilate_triangle //--------------------------------------------------------dilate_triangle
AGG_INLINE void dilate_triangle(double x1, double y1, AGG_INLINE void dilate_triangle(double x1, double y1,
double x2, double y2, double x2, double y2,
@ -161,12 +210,12 @@ namespace agg
calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2); calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3); calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
} }
*x++ = x1 + dx1; *y++ = y1 - dy1; *x++ = x1 + dx1; *y++ = y1 + dy1;
*x++ = x2 + dx1; *y++ = y2 - dy1; *x++ = x2 + dx1; *y++ = y2 + dy1;
*x++ = x2 + dx2; *y++ = y2 - dy2; *x++ = x2 + dx2; *y++ = y2 + dy2;
*x++ = x3 + dx2; *y++ = y3 - dy2; *x++ = x3 + dx2; *y++ = y3 + dy2;
*x++ = x3 + dx3; *y++ = y3 - dy3; *x++ = x3 + dx3; *y++ = y3 + dy3;
*x++ = x1 + dx3; *y++ = y1 - dy3; *x++ = x1 + dx3; *y++ = y1 + dy3;
} }
//------------------------------------------------------calc_triangle_area //------------------------------------------------------calc_triangle_area
@ -177,7 +226,6 @@ namespace agg
return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5; return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
} }
//-------------------------------------------------------calc_polygon_area //-------------------------------------------------------calc_polygon_area
template<class Storage> double calc_polygon_area(const Storage& st) 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; bit -= 9;
if(bit > 0) if(bit > 0)
{ {

View file

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

View file

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

View file

@ -18,6 +18,7 @@
#include <string.h> #include <string.h>
#include "agg_array.h"
#include "agg_rendering_buffer.h" #include "agg_rendering_buffer.h"
@ -38,38 +39,40 @@ namespace agg
void realloc_span(unsigned len) void realloc_span(unsigned len)
{ {
if(len > m_max_len) if(len > m_span.size())
{ {
delete [] m_span; m_span.resize(len + span_extra_tail);
m_span = new cover_type[m_max_len = len + span_extra_tail];
} }
} }
void init_span(unsigned len) void init_span(unsigned len)
{ {
realloc_span(len); realloc_span(len);
memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
// ATTN! May work incorrectly if cover_type is more that one byte
memset(m_span, amask_type::cover_full, len * sizeof(cover_type));
} }
void init_span(unsigned len, const cover_type* covers) void init_span(unsigned len, const cover_type* covers)
{ {
realloc_span(len); realloc_span(len);
memcpy(m_span, covers, len * sizeof(cover_type)); memcpy(&m_span[0], covers, len * sizeof(cover_type));
} }
public: public:
~pixfmt_amask_adaptor() { delete [] m_span; }
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) : 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_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; } 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 width() const { return m_pixf->width(); }
unsigned height() const { return m_pixf->height(); } unsigned height() const { return m_pixf->height(); }
@ -98,8 +101,8 @@ namespace agg
const color_type& c) const color_type& c)
{ {
realloc_span(len); 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_solid_hspan(x, y, len, c, m_span); m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -109,8 +112,8 @@ namespace agg
cover_type cover) cover_type cover)
{ {
init_span(len); init_span(len);
m_mask->combine_hspan(x, y, m_span, len); m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, m_span); m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -119,8 +122,8 @@ namespace agg
const color_type& c) const color_type& c)
{ {
realloc_span(len); 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_solid_vspan(x, y, len, c, m_span); m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -130,8 +133,8 @@ namespace agg
cover_type cover) cover_type cover)
{ {
init_span(len); init_span(len);
m_mask->combine_vspan(x, y, m_span, len); m_mask->combine_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, m_span); m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -151,8 +154,8 @@ namespace agg
const cover_type* covers) const cover_type* covers)
{ {
init_span(len, covers); init_span(len, covers);
m_mask->combine_hspan(x, y, m_span, len); m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, m_span); m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
} }
@ -163,8 +166,8 @@ namespace agg
const cover_type* covers) const cover_type* covers)
{ {
init_span(len, covers); init_span(len, covers);
m_mask->combine_vspan(x, y, m_span, len); m_mask->combine_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, m_span); 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) void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
{ {
realloc_span(len); 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_full); 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, void blend_color_hspan(int x, int y,
@ -187,14 +197,14 @@ namespace agg
if(covers) if(covers)
{ {
init_span(len, 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 else
{ {
realloc_span(len); 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) if(covers)
{ {
init_span(len, 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 else
{ {
realloc_span(len); 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: private:
pixfmt_type* m_pixf; pixfmt_type* m_pixf;
const amask_type* m_mask; const amask_type* m_mask;
pod_array<cover_type> m_span;
cover_type* m_span;
unsigned m_max_len;
}; };
} }

View file

@ -128,7 +128,9 @@ namespace agg
base_shift = color_type::base_shift, base_shift = color_type::base_shift,
base_scale = color_type::base_scale, base_scale = color_type::base_scale,
base_mask = color_type::base_mask, base_mask = color_type::base_mask,
pix_width = sizeof(value_type) pix_width = sizeof(value_type),
pix_step = Step,
pix_offset = Offset
}; };
private: private:
@ -171,30 +173,46 @@ namespace agg
public: public:
//-------------------------------------------------------------------- //--------------------------------------------------------------------
pixfmt_alpha_blend_gray(rbuf_type& rb) : explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
m_rbuf(&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 width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); } 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 int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
{ const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
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 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;
} }
//-------------------------------------------------------------------- int8u* pix_ptr(int x, int y)
row_data row(int x, int y) const
{ {
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 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); return color_type(*p);
} }
@ -399,13 +417,29 @@ namespace agg
do do
{ {
*p++ = colors->v; *p = colors->v;
p += Step;
++colors; ++colors;
} }
while(--len); 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, 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: private:
rbuf_type* m_rbuf; rbuf_type* m_rbuf;
}; };

View file

@ -173,8 +173,8 @@ namespace agg
{ {
public: public:
typedef RenBuf rbuf_type; typedef RenBuf rbuf_type;
typedef typename rbuf_type::row_data row_data;
typedef Blender blender_type; typedef Blender blender_type;
typedef typename rbuf_type::row_data row_data;
typedef typename blender_type::color_type color_type; typedef typename blender_type::color_type color_type;
typedef typename blender_type::order_type order_type; typedef typename blender_type::order_type order_type;
typedef typename color_type::value_type value_type; typedef typename color_type::value_type value_type;
@ -231,9 +231,27 @@ namespace agg
public: public:
//-------------------------------------------------------------------- //--------------------------------------------------------------------
pixfmt_alpha_blend_rgb(rbuf_type& rb) : explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
m_rbuf(&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; } Blender& blender() { return m_blender; }
@ -241,23 +259,22 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_rbuf->width(); } AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); } 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 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); }
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; return m_rbuf->row_ptr(y) + x * pix_width;
} }
//-------------------------------------------------------------------- AGG_INLINE const int8u* pix_ptr(int x, int y) const
row_data row(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, void blend_color_hspan(int x, int y,
unsigned len, 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: private:
rbuf_type* m_rbuf; rbuf_type* m_rbuf;
Blender m_blender; Blender m_blender;

View file

@ -828,29 +828,47 @@ namespace agg
public: 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; } Blender& blender() { return m_blender; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_rbuf->width(); } AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); } 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 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); }
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; return m_rbuf->row_ptr(y) + x * pix_width;
} }
//-------------------------------------------------------------------- AGG_INLINE const int8u* pix_ptr(int x, int y) const
row_data row(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); 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, void blend_color_hspan(int x, int y,
unsigned len, 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: private:
rbuf_type* m_rbuf; rbuf_type* m_rbuf;
Blender m_blender; Blender m_blender;

View file

@ -614,6 +614,8 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); 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::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))); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1)));
} }
}
}; };
//=========================================================comp_op_rgba_plus //=========================================================comp_op_rgba_plus
@ -649,14 +652,17 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type dr = p[Order::R] + sr; calc_type dr = p[Order::R] + sr;
calc_type dg = p[Order::G] + sg; calc_type dg = p[Order::G] + sg;
calc_type db = p[Order::B] + sb; calc_type db = p[Order::B] + sb;
calc_type da = p[Order::A] + sa; calc_type da = p[Order::A] + sa;
p[Order::R] = (dr > base_mask) ? base_mask : dr; p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr;
p[Order::G] = (dg > base_mask) ? base_mask : dg; p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg;
p[Order::B] = (db > base_mask) ? base_mask : db; p[Order::B] = (db > base_mask) ? (value_type)base_mask : db;
p[Order::A] = (da > base_mask) ? base_mask : da; p[Order::A] = (da > base_mask) ? (value_type)base_mask : da;
}
} }
}; };
@ -686,13 +692,17 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type dr = p[Order::R] - sr; calc_type dr = p[Order::R] - sr;
calc_type dg = p[Order::G] - sg; calc_type dg = p[Order::G] - sg;
calc_type db = p[Order::B] - sb; calc_type db = p[Order::B] - sb;
p[Order::R] = (dr > base_mask) ? 0 : dr; p[Order::R] = (dr > base_mask) ? 0 : dr;
p[Order::G] = (dg > base_mask) ? 0 : dg; p[Order::G] = (dg > base_mask) ? 0 : dg;
p[Order::B] = (db > base_mask) ? 0 : db; 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; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
calc_type dr = p[Order::R]; 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::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)); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_screen //=====================================================comp_op_rgba_screen
@ -760,6 +773,8 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
calc_type dg = p[Order::G]; calc_type dg = p[Order::G];
calc_type db = p[Order::B]; 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::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_overlay //=====================================================comp_op_rgba_overlay
@ -801,6 +817,8 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
@ -811,18 +829,19 @@ namespace agg
p[Order::R] = (value_type)(((2*dr < da) ? p[Order::R] = (value_type)(((2*dr < da) ?
2*sr*dr + sr*d1a + dr*s1a : 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) ? p[Order::G] = (value_type)(((2*dg < da) ?
2*sg*dg + sg*d1a + dg*s1a : 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) ? p[Order::B] = (value_type)(((2*db < da) ?
2*sb*db + sb*d1a + db*s1a : 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)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
@ -855,6 +874,8 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
@ -862,11 +883,12 @@ namespace agg
calc_type db = p[Order::B]; calc_type db = p[Order::B];
calc_type da = p[Order::A]; 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::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_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_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)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_lighten //=====================================================comp_op_rgba_lighten
@ -895,6 +917,8 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
@ -902,11 +926,12 @@ namespace agg
calc_type db = p[Order::B]; calc_type db = p[Order::B];
calc_type da = p[Order::A]; 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::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_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_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)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_color_dodge //=====================================================comp_op_rgba_color_dodge
@ -940,6 +965,8 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
@ -955,19 +982,20 @@ namespace agg
long_type sada = sa * da; long_type sada = sa * da;
p[Order::R] = (value_type)((srda + drsa >= sada) ? p[Order::R] = (value_type)((srda + drsa >= sada) ?
(sada + 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_shift)); drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift));
p[Order::G] = (value_type)((sgda + dgsa >= sada) ? p[Order::G] = (value_type)((sgda + dgsa >= sada) ?
(sada + 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_shift)); dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift));
p[Order::B] = (value_type)((sbda + dbsa >= sada) ? p[Order::B] = (value_type)((sbda + dbsa >= sada) ?
(sada + 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_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)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_color_burn //=====================================================comp_op_rgba_color_burn
@ -1001,6 +1029,8 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
@ -1017,18 +1047,19 @@ namespace agg
p[Order::R] = (value_type)(((srda + drsa <= sada) ? p[Order::R] = (value_type)(((srda + drsa <= sada) ?
sr * d1a + dr * s1a : 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) ? p[Order::G] = (value_type)(((sgda + dgsa <= sada) ?
sg * d1a + dg * s1a : 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) ? p[Order::B] = (value_type)(((sbda + dbsa <= sada) ?
sb * d1a + db * s1a : 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)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_hard_light //=====================================================comp_op_rgba_hard_light
@ -1062,6 +1093,8 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
@ -1072,18 +1105,19 @@ namespace agg
p[Order::R] = (value_type)(((2*sr < sa) ? p[Order::R] = (value_type)(((2*sr < sa) ?
2*sr*dr + sr*d1a + dr*s1a : 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) ? p[Order::G] = (value_type)(((2*sg < sa) ?
2*sg*dg + sg*d1a + dg*s1a : 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) ? p[Order::B] = (value_type)(((2*sb < sa) ?
2*sb*db + sb*d1a + db*s1a : 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)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_soft_light //=====================================================comp_op_rgba_soft_light
@ -1117,6 +1151,8 @@ namespace agg
double sg = double(g * cover) / (base_mask * 255); double sg = double(g * cover) / (base_mask * 255);
double sb = double(b * cover) / (base_mask * 255); double sb = double(b * cover) / (base_mask * 255);
double sa = double(a * cover) / (base_mask * 255); double sa = double(a * cover) / (base_mask * 255);
if(sa > 0)
{
double dr = double(p[Order::R]) / base_mask; double dr = double(p[Order::R]) / base_mask;
double dg = double(p[Order::G]) / base_mask; double dg = double(p[Order::G]) / base_mask;
double db = double(p[Order::B]) / 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::B] = (value_type)uround(db * base_mask);
p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_difference //=====================================================comp_op_rgba_difference
@ -1156,6 +1193,7 @@ namespace agg
enum base_scale_e enum base_scale_e
{ {
base_shift = color_type::base_shift, base_shift = color_type::base_shift,
base_scale = color_type::base_scale,
base_mask = color_type::base_mask base_mask = color_type::base_mask
}; };
@ -1172,15 +1210,18 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
calc_type dg = p[Order::G]; calc_type dg = p[Order::G];
calc_type db = p[Order::B]; calc_type db = p[Order::B];
calc_type da = p[Order::A]; calc_type da = p[Order::A];
p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*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_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_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)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_exclusion //=====================================================comp_op_rgba_exclusion
@ -1210,17 +1251,20 @@ namespace agg
sb = (sb * cover + 255) >> 8; sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8; sa = (sa * cover + 255) >> 8;
} }
if(sa)
{
calc_type d1a = base_mask - p[Order::A]; calc_type d1a = base_mask - p[Order::A];
calc_type s1a = base_mask - sa; calc_type s1a = base_mask - sa;
calc_type dr = p[Order::R]; calc_type dr = p[Order::R];
calc_type dg = p[Order::G]; calc_type dg = p[Order::G];
calc_type db = p[Order::B]; calc_type db = p[Order::B];
calc_type da = p[Order::A]; 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::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_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_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)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
} }
}
}; };
//=====================================================comp_op_rgba_contrast //=====================================================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_difference <ColorT,Order>::blend_pix,
comp_op_rgba_exclusion <ColorT,Order>::blend_pix, comp_op_rgba_exclusion <ColorT,Order>::blend_pix,
comp_op_rgba_contrast <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 0
}; };
@ -1357,6 +1475,8 @@ namespace agg
comp_op_difference, //----comp_op_difference comp_op_difference, //----comp_op_difference
comp_op_exclusion, //----comp_op_exclusion comp_op_exclusion, //----comp_op_exclusion
comp_op_contrast, //----comp_op_contrast 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 end_of_comp_op_e
}; };
@ -1652,31 +1772,48 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
pixfmt_alpha_blend_rgba() : m_rbuf(0) {} 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; } 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 width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); } 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 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); }
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; return m_rbuf->row_ptr(y) + x * pix_width;
} }
//-------------------------------------------------------------------- AGG_INLINE const int8u* pix_ptr(int x, int y) const
row_data row(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) 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, void blend_color_hspan(int x, int y,
unsigned len, 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: private:
rbuf_type* m_rbuf; 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() : 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_rbuf(&rb),
m_comp_op(comp_op) m_comp_op(comp_op)
{} {}
void attach(rbuf_type& rb) { m_rbuf = &rb; } void attach(rbuf_type& rb) { m_rbuf = &rb; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); } template<class PixFmt>
unsigned height() const { return m_rbuf->height(); } bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
//--------------------------------------------------------------------
void comp_op(unsigned op) { m_comp_op = op; }
unsigned comp_op() const { return m_comp_op; }
//--------------------------------------------------------------------
const int8u* row_ptr(int y) const
{ {
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; return m_rbuf->row_ptr(y) + x * pix_width;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
row_data row(int x, int y) const void comp_op(unsigned op) { m_comp_op = op; }
{ unsigned comp_op() const { return m_comp_op; }
return m_rbuf->row(y);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE static void make_pix(int8u* p, const color_type& c) AGG_INLINE static void make_pix(int8u* p, const color_type& c)
@ -2373,6 +2615,23 @@ namespace agg
while(--len); 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, void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors, 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: private:
rbuf_type* m_rbuf; rbuf_type* m_rbuf;
unsigned m_comp_op; unsigned m_comp_op;

View file

@ -132,10 +132,10 @@ namespace agg
cell_type** ptr = m_cells + m_num_blocks - 1; cell_type** ptr = m_cells + m_num_blocks - 1;
while(m_num_blocks--) while(m_num_blocks--)
{ {
delete [] *ptr; pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
ptr--; 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_curr_cell_ptr++ = m_curr_cell;
++m_num_cells; ++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) 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) if(m_cells)
{ {
memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*)); 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_cells = new_cells;
m_max_blocks += cell_block_pool; 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++]; m_curr_cell_ptr = m_cells[m_curr_block++];
} }
@ -642,7 +644,6 @@ namespace agg
// cell = cell; // Breakpoint here // cell = cell; // Breakpoint here
// } // }
//} //}
// Allocate the array of cell pointers // Allocate the array of cell pointers
m_sorted_cells.allocate(m_num_cells, 16); m_sorted_cells.allocate(m_num_cells, 16);
@ -721,6 +722,33 @@ namespace agg
m_sorted = true; 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 #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 //==================================================rasterizer_compound_aa
template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa
{ {
@ -88,6 +97,7 @@ namespace agg
public: public:
typedef Clip clip_type; typedef Clip clip_type;
typedef typename Clip::conv_type conv_type; typedef typename Clip::conv_type conv_type;
typedef typename Clip::coord_type coord_type;
enum aa_scale_e enum aa_scale_e
{ {
@ -103,13 +113,20 @@ namespace agg
m_outline(), m_outline(),
m_clipper(), m_clipper(),
m_filling_rule(fill_non_zero), m_filling_rule(fill_non_zero),
m_layer_order(layer_direct),
m_styles(), // Active Styles m_styles(), // Active Styles
m_ast(), // Active Style Table (unique values) m_ast(), // Active Style Table (unique values)
m_asm(), // Active Style Mask m_asm(), // Active Style Mask
m_cells(), m_cells(),
m_cover_buf(),
m_master_alpha(),
m_min_style(0x7FFFFFFF), m_min_style(0x7FFFFFFF),
m_max_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 reset_clipping();
void clip_box(double x1, double y1, double x2, double y2); void clip_box(double x1, double y1, double x2, double y2);
void filling_rule(filling_rule_e filling_rule); 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); void styles(int left, int right);
@ -158,10 +177,18 @@ namespace agg
void sort(); void sort();
bool rewind_scanlines(); bool rewind_scanlines();
unsigned sweep_styles(); 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; 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); int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
if(cover < 0) cover = -cover; if(cover < 0) cover = -cover;
@ -174,7 +201,7 @@ namespace agg
} }
} }
if(cover > aa_mask) cover = aa_mask; 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(); sl.reset_spans();
if(style_idx < 0) style_idx = 0; unsigned master_alpha = aa_mask;
else style_idx++;
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]]; const style_info& st = m_styles[m_ast[style_idx]];
@ -208,14 +244,16 @@ namespace agg
if(area) 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); sl.add_cell(x, alpha);
x++; x++;
} }
if(num_cells && cell->x > 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) if(alpha)
{ {
sl.add_span(x, cell->x - x, alpha); sl.add_span(x, cell->x - x, alpha);
@ -226,11 +264,11 @@ namespace agg
if(sl.num_spans() == 0) return false; if(sl.num_spans() == 0) return false;
sl.finalize(scan_y); sl.finalize(scan_y);
return true; return true;
} }
private: private:
void add_style(int style_id); void add_style(int style_id);
void allocate_master_alpha();
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Disable copying // Disable copying
@ -242,14 +280,21 @@ namespace agg
rasterizer_cells_aa<cell_style_aa> m_outline; rasterizer_cells_aa<cell_style_aa> m_outline;
clip_type m_clipper; clip_type m_clipper;
filling_rule_e m_filling_rule; filling_rule_e m_filling_rule;
layer_order_e m_layer_order;
pod_vector<style_info> m_styles; // Active Styles pod_vector<style_info> m_styles; // Active Styles
pod_vector<unsigned> m_ast; // Active Style Table (unique values) pod_vector<unsigned> m_ast; // Active Style Table (unique values)
pod_vector<int8u> m_asm; // Active Style Mask pod_vector<int8u> m_asm; // Active Style Mask
pod_vector<cell_info> m_cells; 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_min_style;
int m_max_style; int m_max_style;
coord_type m_start_x;
coord_type m_start_y;
int m_scan_y; int m_scan_y;
int m_sl_start;
unsigned m_sl_len;
}; };
@ -269,6 +314,8 @@ namespace agg
m_min_style = 0x7FFFFFFF; m_min_style = 0x7FFFFFFF;
m_max_style = -0x7FFFFFFF; m_max_style = -0x7FFFFFFF;
m_scan_y = 0x7FFFFFFF; m_scan_y = 0x7FFFFFFF;
m_sl_start = 0;
m_sl_len = 0;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@ -278,6 +325,13 @@ namespace agg
m_filling_rule = filling_rule; 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> template<class Clip>
void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1, 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) void rasterizer_compound_aa<Clip>::move_to(int x, int y)
{ {
if(m_outline.sorted()) reset(); 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) void rasterizer_compound_aa<Clip>::move_to_d(double x, double y)
{ {
if(m_outline.sorted()) reset(); 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); move_to_d(x, y);
} }
else else
{
if(is_vertex(cmd)) if(is_vertex(cmd))
{ {
line_to_d(x, y); 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_scan_y = m_outline.min_y();
m_styles.allocate(m_max_style - m_min_style + 2, 128); m_styles.allocate(m_max_style - m_min_style + 2, 128);
allocate_master_alpha();
return true; return true;
} }
@ -453,6 +513,8 @@ namespace agg
m_asm.allocate((num_styles + 7) >> 3, 8); m_asm.allocate((num_styles + 7) >> 3, 8);
m_asm.zero(); m_asm.zero();
if(num_cells)
{
// Pre-add zero (for no-fill style, that is, -1). // Pre-add zero (for no-fill style, that is, -1).
// We need that to ensure that the "-1 style" would go first. // We need that to ensure that the "-1 style" would go first.
m_asm[0] |= 1; m_asm[0] |= 1;
@ -462,6 +524,8 @@ namespace agg
style->num_cells = 0; style->num_cells = 0;
style->last_x = -0x7FFFFFFF; 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--) while(num_cells--)
{ {
curr_cell = *cells++; curr_cell = *cells++;
@ -526,10 +590,19 @@ namespace agg
style->num_cells++; style->num_cells++;
} }
} }
}
if(m_ast.size() > 1) break; if(m_ast.size() > 1) break;
++m_scan_y; ++m_scan_y;
} }
++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; return m_ast.size() - 1;
} }
@ -542,6 +615,80 @@ namespace agg
return m_ast[style_idx + 1] + m_min_style - 1; 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 template<class Renderer> class rasterizer_outline
{ {
public: public:
rasterizer_outline(Renderer& ren) : explicit rasterizer_outline(Renderer& ren) :
m_ren(&ren), m_ren(&ren),
m_start_x(0), m_start_x(0),
m_start_y(0), m_start_y(0),
m_vertices(0) m_vertices(0)
{ {}
} void attach(Renderer& ren) { m_ren = &ren; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void move_to(int x, int y) void move_to(int x, int y)

View file

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

View file

@ -357,7 +357,7 @@ namespace agg
template<class Clip> template<class Clip>
void rasterizer_scanline_aa<Clip>::close_polygon() 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_clipper.line_to(m_outline, m_start_x, m_start_y);
m_status = status_closed; m_status = status_closed;
@ -369,7 +369,7 @@ namespace agg
void rasterizer_scanline_aa<Clip>::move_to(int x, int y) void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
{ {
if(m_outline.sorted()) reset(); 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_clipper.move_to(m_start_x = conv_type::downscale(x),
m_start_y = conv_type::downscale(y)); m_start_y = conv_type::downscale(y));
m_status = status_move_to; m_status = status_move_to;
@ -390,7 +390,7 @@ namespace agg
void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y) void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
{ {
if(m_outline.sorted()) reset(); 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_clipper.move_to(m_start_x = conv_type::upscale(x),
m_start_y = conv_type::upscale(y)); m_start_y = conv_type::upscale(y));
m_status = status_move_to; m_status = status_move_to;
@ -415,11 +415,14 @@ namespace agg
move_to_d(x, y); move_to_d(x, y);
} }
else else
{
if(is_vertex(cmd)) if(is_vertex(cmd))
{ {
line_to_d(x, y); line_to_d(x, y);
} }
else
if(is_close(cmd))
{
close_polygon();
} }
} }
@ -452,6 +455,7 @@ namespace agg
template<class Clip> template<class Clip>
void rasterizer_scanline_aa<Clip>::sort() void rasterizer_scanline_aa<Clip>::sort()
{ {
if(m_auto_close) close_polygon();
m_outline.sort_cells(); m_outline.sort_cells();
} }
@ -459,7 +463,7 @@ namespace agg
template<class Clip> template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines() AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
{ {
close_polygon(); if(m_auto_close) close_polygon();
m_outline.sort_cells(); m_outline.sort_cells();
if(m_outline.total_cells() == 0) if(m_outline.total_cells() == 0)
{ {
@ -474,7 +478,7 @@ namespace agg
template<class Clip> template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y) AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
{ {
close_polygon(); if(m_auto_close) close_polygon();
m_outline.sort_cells(); m_outline.sort_cells();
if(m_outline.total_cells() == 0 || if(m_outline.total_cells() == 0 ||
y < m_outline.min_y() || y < m_outline.min_y() ||
@ -486,31 +490,6 @@ namespace agg
return true; 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> template<class Clip>
bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty) 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() : 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_ren(&ren),
m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) 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); 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, void blend_color_hspan(int x, int y, int len,
const color_type* colors, 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: private:
pixfmt_type* m_ren; pixfmt_type* m_ren;
rect_i m_clip_box; rect_i m_clip_box;

View file

@ -65,8 +65,7 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
renderer_markers(base_ren_type& rbuf) : renderer_markers(base_ren_type& rbuf) :
base_type(rbuf) base_type(rbuf)
{ {}
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
bool visible(int x, int y, int r) const 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; typedef renderer_base<pixfmt_type> base_ren_type;
//-------------------------------------------------------------------- //--------------------------------------------------------------------
renderer_mclip(pixfmt_type& ren) : explicit renderer_mclip(pixfmt_type& pixf) :
m_ren(ren), m_ren(pixf),
m_curr_cb(0), m_curr_cb(0),
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) 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 #ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED
#define 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_math.h"
#include "agg_line_aa_basics.h" #include "agg_line_aa_basics.h"
#include "agg_dda_line.h" #include "agg_dda_line.h"
@ -1273,13 +1273,8 @@ namespace agg
aa_mask = aa_scale - 1 aa_mask = aa_scale - 1
}; };
//---------------------------------------------------------------------
~line_profile_aa() { delete [] m_profile; }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
line_profile_aa() : line_profile_aa() :
m_size(0),
m_profile(0),
m_subpixel_width(0), m_subpixel_width(0),
m_min_width(1.0), m_min_width(1.0),
m_smoother_width(1.0) m_smoother_width(1.0)
@ -1291,8 +1286,6 @@ namespace agg
//--------------------------------------------------------------------- //---------------------------------------------------------------------
template<class GammaF> template<class GammaF>
line_profile_aa(double w, const GammaF& gamma_function) : line_profile_aa(double w, const GammaF& gamma_function) :
m_size(0),
m_profile(0),
m_subpixel_width(0), m_subpixel_width(0),
m_min_width(1.0), m_min_width(1.0),
m_smoother_width(1.0) m_smoother_width(1.0)
@ -1318,7 +1311,7 @@ namespace agg
void width(double w); 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; } int subpixel_width() const { return m_subpixel_width; }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
@ -1339,8 +1332,7 @@ namespace agg
void set(double center_width, double smoother_width); void set(double center_width, double smoother_width);
//--------------------------------------------------------------------- //---------------------------------------------------------------------
unsigned m_size; pod_array<value_type> m_profile;
value_type* m_profile;
value_type m_gamma[aa_scale]; value_type m_gamma[aa_scale];
int m_subpixel_width; int m_subpixel_width;
double m_min_width; double m_min_width;
@ -1363,8 +1355,8 @@ namespace agg
m_profile(&prof), m_profile(&prof),
m_clip_box(0,0,0,0), m_clip_box(0,0,0,0),
m_clipping(false) m_clipping(false)
{ {}
} void attach(base_ren_type& ren) { m_ren = &ren; }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
void color(const color_type& c) { m_color = c; } void color(const color_type& c) { m_color = c; }
@ -1657,7 +1649,7 @@ namespace agg
} }
else 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; sx = (lp.x1 + sx) >> 1;
sy = (lp.y1 + sy) >> 1; sy = (lp.y1 + sy) >> 1;
@ -1724,7 +1716,7 @@ namespace agg
} }
else 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; ex = (lp.x2 + ex) >> 1;
ey = (lp.y2 + ey) >> 1; ey = (lp.y2 + ey) >> 1;
@ -1796,7 +1788,7 @@ namespace agg
} }
else 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; sx = (lp.x1 + sx) >> 1;
sy = (lp.y1 + sy) >> 1; sy = (lp.y1 + sy) >> 1;
@ -1809,7 +1801,7 @@ namespace agg
} }
else 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; ex = (lp.x2 + ex) >> 1;
ey = (lp.y2 + ey) >> 1; ey = (lp.y2 + ey) >> 1;

View file

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

View file

@ -35,14 +35,14 @@ namespace agg
typedef typename base_ren_type::color_type color_type; 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_ren(&ren),
m_fill_color(), m_fill_color(),
m_line_color(), m_line_color(),
m_curr_x(0), m_curr_x(0),
m_curr_y(0) m_curr_y(0)
{ {}
} void attach(base_ren_type& ren) { m_ren = &ren; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static int coord(double c) static int coord(double c)

View file

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

View file

@ -52,7 +52,6 @@ namespace agg
} }
} }
//===============================================render_scanlines_aa_solid //===============================================render_scanlines_aa_solid
template<class Rasterizer, class Scanline, template<class Rasterizer, class Scanline,
class BaseRenderer, class ColorT> class BaseRenderer, class ColorT>
@ -103,7 +102,6 @@ namespace agg
} }
} }
//==============================================renderer_scanline_aa_solid //==============================================renderer_scanline_aa_solid
template<class BaseRenderer> class 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() : 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) void attach(base_ren_type& ren)
{ {
m_ren = &ren; m_ren = &ren;
@ -176,8 +174,6 @@ namespace agg
} }
} }
//=====================================================render_scanlines_aa //=====================================================render_scanlines_aa
template<class Rasterizer, class Scanline, class BaseRenderer, template<class Rasterizer, class Scanline, class BaseRenderer,
class SpanAllocator, class SpanGenerator> class SpanAllocator, class SpanGenerator>
@ -195,8 +191,6 @@ namespace agg
} }
} }
//====================================================renderer_scanline_aa //====================================================renderer_scanline_aa
template<class BaseRenderer, class SpanAllocator, class SpanGenerator> template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
class renderer_scanline_aa 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 //===============================================render_scanline_bin_solid
template<class Scanline, class BaseRenderer, class ColorT> template<class Scanline, class BaseRenderer, class ColorT>
void render_scanline_bin_solid(const Scanline& sl, void render_scanline_bin_solid(const Scanline& sl,
@ -578,7 +260,6 @@ namespace agg
} }
} }
//==============================================render_scanlines_bin_solid //==============================================render_scanlines_bin_solid
template<class Rasterizer, class Scanline, template<class Rasterizer, class Scanline,
class BaseRenderer, class ColorT> class BaseRenderer, class ColorT>
@ -621,7 +302,6 @@ namespace agg
} }
} }
//=============================================renderer_scanline_bin_solid //=============================================renderer_scanline_bin_solid
template<class BaseRenderer> class 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() : 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) void attach(base_ren_type& ren)
{ {
m_ren = &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 //========================================================render_all_paths
template<class Rasterizer, class Scanline, class Renderer, template<class Rasterizer, class Scanline, class Renderer,
class VertexSource, class ColorStorage, class PathId> class VertexSource, class ColorStorage, class PathId>
@ -707,6 +472,7 @@ namespace agg
//=============================================render_scanlines_compound //=============================================render_scanlines_compound
template<class Rasterizer, template<class Rasterizer,
class ScanlineAA, class ScanlineAA,
@ -820,8 +586,15 @@ namespace agg
colors = mix_buffer + span_aa->x - min_x; colors = mix_buffer + span_aa->x - min_x;
covers = span_aa->covers; covers = span_aa->covers;
do do
{
if(*covers == cover_full)
{
*colors = c;
}
else
{ {
colors->add(c, *covers); colors->add(c, *covers);
}
++colors; ++colors;
++covers; ++covers;
} }
@ -846,8 +619,15 @@ namespace agg
style); style);
covers = span_aa->covers; covers = span_aa->covers;
do do
{
if(*covers == cover_full)
{
*colors = *cspan;
}
else
{ {
colors->add(*cspan, *covers); colors->add(*cspan, *covers);
}
++cspan; ++cspan;
++colors; ++colors;
++covers; ++covers;
@ -875,15 +655,196 @@ namespace agg
if(--num_spans == 0) break; if(--num_spans == 0) break;
++span_bin; ++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 #ifndef AGG_RENDERING_BUFFER_INCLUDED
#define AGG_RENDERING_BUFFER_INCLUDED #define AGG_RENDERING_BUFFER_INCLUDED
#include "agg_basics.h" #include "agg_array.h"
namespace agg namespace agg
{ {
//==========================================================row_ptr_cache //===========================================================row_accessor
template<class T> class row_ptr_cache template<class T> class row_accessor
{ {
public: public:
//-------------------------------------------------------------------- typedef const_row_info<T> row_data;
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_) {}
};
//------------------------------------------------------------------- //-------------------------------------------------------------------
~row_ptr_cache() row_accessor() :
{
delete [] m_rows;
}
//-------------------------------------------------------------------
row_ptr_cache() :
m_buf(0), m_buf(0),
m_rows(0), m_start(0),
m_width(0), m_width(0),
m_height(0), m_height(0),
m_stride(0), m_stride(0)
m_max_height(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_buf(0),
m_rows(0), m_start(0),
m_width(0), m_width(0),
m_height(0), m_height(0),
m_stride(0), m_stride(0)
m_max_height(0)
{ {
attach(buf, width, height, stride); attach(buf, width, height, stride);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride) void attach(T* buf, unsigned width, unsigned height, int stride)
{ {
m_buf = buf; m_buf = m_start = buf;
m_width = width; m_width = width;
m_height = height; m_height = height;
m_stride = stride; 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) if(stride < 0)
{ {
row_ptr = m_buf - (height - 1) * stride; m_start = m_buf - int(height - 1) * stride;
}
T** rows = m_rows;
while(height--)
{
*rows++ = row_ptr;
row_ptr += stride;
} }
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
T* buf() { return m_buf; } AGG_INLINE T* buf() { return m_buf; }
const T* buf() const { return m_buf; } AGG_INLINE const T* buf() const { return m_buf; }
unsigned width() const { return m_width; } AGG_INLINE unsigned width() const { return m_width; }
unsigned height() const { return m_height; } AGG_INLINE unsigned height() const { return m_height; }
int stride() const { return m_stride; } AGG_INLINE int stride() const { return m_stride; }
unsigned stride_abs() const AGG_INLINE unsigned stride_abs() const
{ {
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
T* row_ptr(int, int y, unsigned) { return m_rows[y]; } AGG_INLINE T* row_ptr(int, int y, unsigned)
T* row_ptr(int y) { return m_rows[y]; } {
const T* row_ptr(int y) const { return m_rows[y]; } return m_start + y * m_stride;
row_data row (int y) const { return row_data(0, m_width-1, m_rows[y]); } }
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; }
T const* const* rows() const { return m_rows; } AGG_INLINE row_data row (int y) const
{
return row_data(0, m_width-1, row_ptr(y));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class RenBuf> 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: private:
//-------------------------------------------------------------------- //--------------------------------------------------------------------
T* m_buf; // Pointer to renrdering buffer 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_width; // Width in pixels
unsigned m_height; // Height in pixels unsigned m_height; // Height in pixels
int m_stride; // Number of bytes per row. Can be < 0 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 //========================================================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 #ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED #define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
#include <string.h> #include "agg_array.h"
#include "agg_basics.h"
namespace agg namespace agg
{ {
@ -36,12 +35,7 @@ namespace agg
class rendering_buffer_dynarow class rendering_buffer_dynarow
{ {
public: public:
//---------------------------------------------------------------------- typedef row_info<int8u> row_data;
struct row_data
{
int x1, x2;
const int8u* ptr;
};
//------------------------------------------------------------------- //-------------------------------------------------------------------
~rendering_buffer_dynarow() ~rendering_buffer_dynarow()
@ -51,9 +45,10 @@ namespace agg
//------------------------------------------------------------------- //-------------------------------------------------------------------
rendering_buffer_dynarow() : rendering_buffer_dynarow() :
m_rows(0), m_rows(),
m_width(0), 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, rendering_buffer_dynarow(unsigned width, unsigned height,
unsigned byte_width) : unsigned byte_width) :
m_rows(new row_data[height]), m_rows(height),
m_width(width), m_width(width),
m_height(height), m_height(height),
m_byte_width(byte_width) 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 // Allocate and clear the buffer
@ -74,16 +69,17 @@ namespace agg
void init(unsigned width, unsigned height, unsigned byte_width) void init(unsigned width, unsigned height, unsigned byte_width)
{ {
unsigned i; unsigned i;
for(i = 0; i < m_height; ++i) delete [] (int8u*)m_rows[i].ptr; for(i = 0; i < m_height; ++i)
delete [] m_rows; {
m_rows = 0; pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
}
if(width && height) if(width && height)
{ {
m_width = width; m_width = width;
m_height = height; m_height = height;
m_byte_width = byte_width; m_byte_width = byte_width;
m_rows = new row_data[height]; m_rows.resize(height);
memset(m_rows, 0, sizeof(row_data) * 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) 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; int x2 = x + len - 1;
if(r->ptr) if(r->ptr)
{ {
@ -106,7 +102,7 @@ namespace agg
} }
else else
{ {
int8u* p = new int8u [m_byte_width]; int8u* p = pod_allocator<int8u>::allocate(m_byte_width);
r->ptr = p; r->ptr = p;
r->x1 = x; r->x1 = x;
r->x2 = x2; r->x2 = x2;
@ -128,7 +124,7 @@ namespace agg
private: 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_width; // Width in pixels
unsigned m_height; // Height in pixels unsigned m_height; // Height in pixels
unsigned m_byte_width; // Width in bytes unsigned m_byte_width; // Width in bytes

View file

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

View file

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

View file

@ -83,7 +83,8 @@ namespace agg
int i; int i;
for(i = m_extra_storage.size()-1; i >= 0; --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_extra_storage.remove_all();
m_cells.remove_all(); m_cells.remove_all();
@ -101,7 +102,7 @@ namespace agg
} }
extra_span s; extra_span s;
s.len = num_cells; 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); memcpy(s.ptr, cells, sizeof(T) * num_cells);
m_extra_storage.add(s); m_extra_storage.add(s);
return -int(m_extra_storage.size()); return -int(m_extra_storage.size());
@ -142,7 +143,7 @@ namespace agg
const extra_span& src = v.m_extra_storage[i]; const extra_span& src = v.m_extra_storage[i];
extra_span dst; extra_span dst;
dst.len = src.len; 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)); memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
m_extra_storage.add(dst); m_extra_storage.add(dst);
} }

View file

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

View file

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

View file

@ -29,6 +29,9 @@ namespace agg
span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) : span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) :
m_span_gen(&span_gen), m_span_cnv(&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() void prepare()
{ {

View file

@ -146,6 +146,10 @@ namespace agg
}; };
//==========================================================gradient_circle //==========================================================gradient_circle
class gradient_circle class gradient_circle
{ {
@ -168,7 +172,6 @@ namespace agg
} }
}; };
//========================================================gradient_radial_d //========================================================gradient_radial_d
class gradient_radial_d class gradient_radial_d
{ {
@ -179,25 +182,24 @@ namespace agg
} }
}; };
//====================================================gradient_radial_focus //====================================================gradient_radial_focus
class gradient_radial_focus class gradient_radial_focus
{ {
public: public:
//--------------------------------------------------------------------- //---------------------------------------------------------------------
gradient_radial_focus() : gradient_radial_focus() :
m_radius(100 * gradient_subpixel_scale), m_r(100 * gradient_subpixel_scale),
m_focus_x(0), m_fx(0),
m_focus_y(0) m_fy(0)
{ {
update_values(); update_values();
} }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
gradient_radial_focus(double r, double fx, double fy) : gradient_radial_focus(double r, double fx, double fy) :
m_radius (iround(r * gradient_subpixel_scale)), m_r (iround(r * gradient_subpixel_scale)),
m_focus_x(iround(fx * gradient_subpixel_scale)), m_fx(iround(fx * gradient_subpixel_scale)),
m_focus_y(iround(fy * gradient_subpixel_scale)) m_fy(iround(fy * gradient_subpixel_scale))
{ {
update_values(); update_values();
} }
@ -205,111 +207,62 @@ namespace agg
//--------------------------------------------------------------------- //---------------------------------------------------------------------
void init(double r, double fx, double fy) void init(double r, double fx, double fy)
{ {
m_radius = iround(r * gradient_subpixel_scale); m_r = iround(r * gradient_subpixel_scale);
m_focus_x = iround(fx * gradient_subpixel_scale); m_fx = iround(fx * gradient_subpixel_scale);
m_focus_y = iround(fy * gradient_subpixel_scale); m_fy = iround(fy * gradient_subpixel_scale);
update_values(); update_values();
} }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
double radius() const { return double(m_radius) / gradient_subpixel_scale; } double radius() const { return double(m_r) / gradient_subpixel_scale; }
double focus_x() const { return double(m_focus_x) / gradient_subpixel_scale; } double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
double focus_y() const { return double(m_focus_y) / gradient_subpixel_scale; } double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
int calculate(int x, int y, int) const int calculate(int x, int y, int) const
{ {
double solution_x; double dx = x - m_fx;
double solution_y; double dy = y - m_fy;
double d2 = dx * m_fy - dy * m_fx;
// Special case to avoid divide by zero or very near zero double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
//--------------------------------- return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul);
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);
} }
private: private:
//--------------------------------------------------------------------- //---------------------------------------------------------------------
void update_values() void update_values()
{ {
// For use in the quadratic equation // Calculate the invariant values. In case the focal center
//------------------------------- // lies exactly on the gradient circle the divisor degenerates
m_radius2 = double(m_radius) * double(m_radius); // into zero. In this case we just move the focal center by
// one subpixel unit possibly in the direction to the origin (0,0)
double dist = sqrt(double(m_focus_x) * double(m_focus_x) + // and calculate the values again.
double(m_focus_y) * double(m_focus_y)); //-------------------------
m_r2 = double(m_r) * double(m_r);
// Test if distance from focus to center is greater than the radius m_fx2 = double(m_fx) * double(m_fx);
// For the sake of assurance factor restrict the point to be m_fy2 = double(m_fy) * double(m_fy);
// no further than 99% of the radius. double d = (m_r2 - (m_fx2 + m_fy2));
//------------------------------- if(d == 0)
double r = m_radius * 0.99;
if(dist > r)
{ {
// clamp focus to radius if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; }
// x = r cos theta, y = r sin theta if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; }
//------------------------ m_fx2 = double(m_fx) * double(m_fx);
double a = atan2(double(m_focus_y), double(m_focus_x)); m_fy2 = double(m_fy) * double(m_fy);
m_focus_x = iround(r * cos(a)); d = (m_r2 - (m_fx2 + m_fy2));
m_focus_y = iround(r * sin(a)); }
m_mul = m_r / d;
} }
// Calculate the solution to be used in the case where x == focus_x int m_r;
//------------------------------ int m_fx;
m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x)); int m_fy;
} double m_r2;
double m_fx2;
int m_radius; double m_fy2;
int m_focus_x; double m_mul;
int m_focus_y;
double m_radius2;
double m_trivial;
}; };
//==============================================================gradient_x //==============================================================gradient_x
class gradient_x class gradient_x
{ {
@ -325,7 +278,6 @@ namespace agg
static int calculate(int, int y, int) { return y; } static int calculate(int, int y, int) { return y; }
}; };
//========================================================gradient_diamond //========================================================gradient_diamond
class gradient_diamond class gradient_diamond
{ {
@ -338,7 +290,6 @@ namespace agg
} }
}; };
//=============================================================gradient_xy //=============================================================gradient_xy
class gradient_xy class gradient_xy
{ {
@ -349,7 +300,6 @@ namespace agg
} }
}; };
//========================================================gradient_sqrt_xy //========================================================gradient_sqrt_xy
class gradient_sqrt_xy class gradient_sqrt_xy
{ {
@ -360,7 +310,6 @@ namespace agg
} }
}; };
//==========================================================gradient_conic //==========================================================gradient_conic
class gradient_conic class gradient_conic
{ {
@ -371,7 +320,6 @@ namespace agg
} }
}; };
//=================================================gradient_repeat_adaptor //=================================================gradient_repeat_adaptor
template<class GradientF> class gradient_repeat_adaptor template<class GradientF> class gradient_repeat_adaptor
{ {
@ -390,7 +338,6 @@ namespace agg
const GradientF* m_gradient; const GradientF* m_gradient;
}; };
//================================================gradient_reflect_adaptor //================================================gradient_reflect_adaptor
template<class GradientF> class 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_dx_int(image_subpixel_scale / 2),
m_dy_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; } source_type& source() { return *m_src; }
@ -57,7 +58,6 @@ namespace agg
double filter_dy_dbl() const { return m_dy_dbl; } 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 interpolator(interpolator_type& v) { m_interpolator = &v; }
void filter(const image_filter_lut& v) { m_filter = &v; } void filter(const image_filter_lut& v) { m_filter = &v; }
void filter_offset(double dx, double dy) void filter_offset(double dx, double dy)
@ -136,34 +136,30 @@ namespace agg
base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y); 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) if(scale_x * scale_y > m_scale_limit)
{ {
scale_x = scale_x * m_scale_limit / (scale_x * scale_y); scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
scale_y = scale_y * 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_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 = uround( scale_x * double(image_subpixel_scale));
m_rx_inv = uround(1.0/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 = uround( scale_y * double(image_subpixel_scale));
m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
} }
}
protected: protected:
int m_rx; int m_rx;
@ -219,6 +215,24 @@ namespace agg
m_blur_y = uround(v * double(image_subpixel_scale)); } m_blur_y = uround(v * double(image_subpixel_scale)); }
protected: 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_scale_limit;
int m_blur_x; int m_blur_x;
int m_blur_y; int m_blur_y;

View file

@ -676,35 +676,10 @@ namespace agg
int ry_inv = image_subpixel_scale; int ry_inv = image_subpixel_scale;
base_type::interpolator().coordinates(&x, &y); base_type::interpolator().coordinates(&x, &y);
base_type::interpolator().local_scale(&rx, &ry); 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; 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; ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
}
int radius_x = (diameter * rx) >> 1; int radius_x = (diameter * rx) >> 1;
int radius_y = (diameter * ry) >> 1; int radius_y = (diameter * ry) >> 1;

View file

@ -808,35 +808,10 @@ namespace agg
int ry_inv = image_subpixel_scale; int ry_inv = image_subpixel_scale;
base_type::interpolator().coordinates(&x, &y); base_type::interpolator().coordinates(&x, &y);
base_type::interpolator().local_scale(&rx, &ry); 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; 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; ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
}
int radius_x = (diameter * rx) >> 1; int radius_x = (diameter * rx) >> 1;
int radius_y = (diameter * ry) >> 1; int radius_y = (diameter * ry) >> 1;

View file

@ -832,35 +832,10 @@ namespace agg
int ry_inv = image_subpixel_scale; int ry_inv = image_subpixel_scale;
base_type::interpolator().coordinates(&x, &y); base_type::interpolator().coordinates(&x, &y);
base_type::interpolator().local_scale(&rx, &ry); 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; 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; ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
}
int radius_x = (diameter * rx) >> 1; int radius_x = (diameter * rx) >> 1;
int radius_y = (diameter * ry) >> 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; } source_type& source() { return *m_src; }
const source_type& source() const { 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; } 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; } source_type& source() { return *m_src; }
const source_type& source() const { 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; } 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; } source_type& source() { return *m_src; }
const source_type& source() const { 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; } void offset_x(unsigned v) { m_offset_x = v; }
@ -75,7 +75,7 @@ namespace agg
span->g = p[order_type::G]; span->g = p[order_type::G];
span->b = p[order_type::B]; span->b = p[order_type::B];
span->a = p[order_type::A]; span->a = p[order_type::A];
p = m_src->next_x(); p = (const value_type*)m_src->next_x();
++span; ++span;
} }
while(--len); while(--len);

View file

@ -24,7 +24,7 @@
namespace agg namespace agg
{ {
const double affine_epsilon = 1e-14; // About of precision of doubles const double affine_epsilon = 1e-14;
//============================================================trans_affine //============================================================trans_affine
// //
@ -84,48 +84,58 @@ namespace agg
// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate // 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) // 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 //------------------------------------------ Construction
// Construct an identity matrix - it does not transform anything // Identity matrix
trans_affine() : 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 // Custom matrix. Usually used in derived classes
trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) : trans_affine(double v0, double v1, double v2,
m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5) 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. // Custom matrix from m[6]
trans_affine(const double* rect, const double* parl) explicit trans_affine(const double* m) :
{ sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5])
parl_to_parl(rect, parl); {}
}
// Construct a matrix to transform a rectangle to a parallelogram. // Rectangle to a parallelogram.
trans_affine(double x1, double y1, double x2, double y2, trans_affine(double x1, double y1, double x2, double y2,
const double* parl) const double* parl)
{ {
rect_to_parl(x1, y1, x2, y2, 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, trans_affine(const double* parl,
double x1, double y1, double x2, double y2) double x1, double y1, double x2, double y2)
{ {
parl_to_rect(parl, x1, y1, x2, 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 //---------------------------------- Parellelogram transformations
// Calculate a matrix to transform a parallelogram to another one. // transform a parallelogram to another one. Src and dst are
// src and dst are pointers to arrays of three points // pointers to arrays of three points (double[6], x1,y1,...) that
// (double[6], x,y,...) that identify three corners of the // identify three corners of the parallelograms assuming implicit
// parallelograms assuming implicit fourth points. // fourth point. The arguments are arrays of double[6] mapped
// There are also transformations rectangtle to parallelogram and // to x1,y1, x2,y2, x3,y3 where the coordinates are:
// parellelogram to rectangle // *-----------------*
// / (x3,y3)/
// / /
// /(x1,y1) (x2,y2)/
// *-----------------*
const trans_affine& parl_to_parl(const double* src, const trans_affine& parl_to_parl(const double* src,
const double* dst); const double* dst);
@ -139,9 +149,15 @@ namespace agg
//------------------------------------------ Operations //------------------------------------------ Operations
// Reset - actually load an identity matrix // Reset - load an identity matrix
const trans_affine& reset(); 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 // Multiply matrix to another one
const trans_affine& multiply(const trans_affine& m); const trans_affine& multiply(const trans_affine& m);
@ -169,38 +185,38 @@ namespace agg
// Store matrix to an array [6] of double // Store matrix to an array [6] of double
void store_to(double* m) const 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 // Load matrix from an array [6] of double
const trans_affine& load_from(const double* m) 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; return *this;
} }
//------------------------------------------- Operators //------------------------------------------- Operators
// Multiply current matrix to another one // Multiply the matrix by another one
const trans_affine& operator *= (const trans_affine& m) const trans_affine& operator *= (const trans_affine& m)
{ {
return multiply(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) const trans_affine& operator /= (const trans_affine& m)
{ {
return multiply_inv(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. // the result in a separete matrix.
trans_affine operator * (const trans_affine& m) trans_affine operator * (const trans_affine& m)
{ {
return trans_affine(*this).multiply(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. // and return the result in a separete matrix.
trans_affine operator / (const trans_affine& m) trans_affine operator / (const trans_affine& m)
{ {
@ -227,22 +243,28 @@ namespace agg
} }
//-------------------------------------------- Transformations //-------------------------------------------- Transformations
// Direct transformation x and y // Direct transformation of x and y
void transform(double* x, double* y) const; 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; void transform_2x2(double* x, double* y) const;
// Inverse transformation x and y. It works slower than the // Inverse transformation of x and y. It works slower than the
// direct transformation, so if the performance is critical // direct transformation. For massive operations it's better to
// it's better to invert() the matrix and then use transform() // invert() the matrix and then use direct transformations.
void inverse_transform(double* x, double* y) const; void inverse_transform(double* x, double* y) const;
//-------------------------------------------- Auxiliary //-------------------------------------------- Auxiliary
// Calculate the determinant of matrix // Calculate the determinant of matrix
double determinant() const 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). // Get the average scale (by X and Y).
@ -250,65 +272,109 @@ namespace agg
// decomposinting curves into line segments. // decomposinting curves into line segments.
double scale() const; 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 // Check to see if it's an identity matrix
bool is_identity(double epsilon = affine_epsilon) const; bool is_identity(double epsilon = affine_epsilon) const;
// Check to see if two matrices are equal // Check to see if two matrices are equal
bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const; 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; double rotation() const;
void translation(double* dx, double* dy) const; void translation(double* dx, double* dy) const;
void scaling(double* sx, double* sy) const; void scaling(double* x, double* y) const;
void scaling_abs(double* sx, double* sy) const void scaling_abs(double* x, double* y) 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;
}; };
//------------------------------------------------------------------------ //------------------------------------------------------------------------
inline void trans_affine::transform(double* x, double* y) const inline void trans_affine::transform(double* x, double* y) const
{ {
register double tx = *x; register double tmp = *x;
*x = tx * m0 + *y * m2 + m4; *x = tmp * sx + *y * shx + tx;
*y = tx * m1 + *y * m3 + m5; *y = tmp * shy + *y * sy + ty;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
inline void trans_affine::transform_2x2(double* x, double* y) const inline void trans_affine::transform_2x2(double* x, double* y) const
{ {
register double tx = *x; register double tmp = *x;
*x = tx * m0 + *y * m2; *x = tmp * sx + *y * shx;
*y = tx * m1 + *y * m3; *y = tmp * shy + *y * sy;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
inline void trans_affine::inverse_transform(double* x, double* y) const inline void trans_affine::inverse_transform(double* x, double* y) const
{ {
register double d = determinant(); register double d = determinant_reciprocal();
register double a = (*x - m4) * d; register double a = (*x - tx) * d;
register double b = (*y - m5) * d; register double b = (*y - ty) * d;
*x = a * m3 - b * m2; *x = a * sy - b * shx;
*y = b * m0 - a * m1; *y = b * sx - a * shy;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
inline double trans_affine::scale() const inline double trans_affine::scale() const
{ {
double x = 0.707106781 * m0 + 0.707106781 * m2; double x = 0.707106781 * sx + 0.707106781 * shx;
double y = 0.707106781 * m1 + 0.707106781 * m3; double y = 0.707106781 * shy + 0.707106781 * sy;
return sqrt(x*x + y*y); 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) inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
{ {
@ -321,8 +387,7 @@ namespace agg
{ {
trans_affine t = m; trans_affine t = m;
t.invert(); t.invert();
multiply(t); return multiply(t);
return *this;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@ -333,6 +398,16 @@ namespace agg
return *this = t.multiply(*this); 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 //====================================================trans_affine_rotation
// Rotation matrix. sin() and cos() are calculated twice for the same angle. // 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 // There's no harm because the performance of sin()/cos() is very good on all
@ -347,12 +422,12 @@ namespace agg
}; };
//====================================================trans_affine_scaling //====================================================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 class trans_affine_scaling : public trans_affine
{ {
public: public:
trans_affine_scaling(double sx, double sy) : trans_affine_scaling(double x, double y) :
trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0) trans_affine(x, 0.0, 0.0, y, 0.0, 0.0)
{} {}
trans_affine_scaling(double s) : trans_affine_scaling(double s) :
@ -365,8 +440,8 @@ namespace agg
class trans_affine_translation : public trans_affine class trans_affine_translation : public trans_affine
{ {
public: public:
trans_affine_translation(double tx, double ty) : trans_affine_translation(double x, double y) :
trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty) 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 class trans_affine_skewing : public trans_affine
{ {
public: public:
trans_affine_skewing(double sx, double sy) : trans_affine_skewing(double x, double y) :
trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0) 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 #ifndef AGG_TRANS_PERSPECTIVE_INCLUDED
#define AGG_TRANS_PERSPECTIVE_INCLUDED #define AGG_TRANS_PERSPECTIVE_INCLUDED
#include "agg_basics.h" #include "agg_trans_affine.h"
#include "agg_simul_eq.h"
namespace agg namespace agg
{ {
//=======================================================trans_perspective //=======================================================trans_perspective
class trans_perspective struct trans_perspective
{ {
public: double sx, shy, w0, shx, sy, w1, tx, ty, w2;
//--------------------------------------------------------------------
trans_perspective() : m_valid(false) {}
//------------------------------------------------------- Construction
// Identity matrix
trans_perspective() :
sx (1), shy(0), w0(0),
shx(0), sy (1), w1(0),
tx (0), ty (0), w2(1) {}
//-------------------------------------------------------------------- // Custom matrix
// Arbitrary quadrangle transformations trans_perspective(double v0, double v1, double v2,
trans_perspective(const double* src, const double* dst) double v3, double v4, double v5,
{ double v6, double v7, double v8) :
quad_to_quad(src, dst); 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]) {}
//-------------------------------------------------------------------- // From affine
// Direct transformations 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, trans_perspective(double x1, double y1, double x2, double y2,
const double* quad) const double* quad);
{
rect_to_quad(x1, y1, x2, y2, quad);
}
// Quadrilateral to rectangle
//--------------------------------------------------------------------
// Reverse transformations
trans_perspective(const double* quad, 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);
} }
// Multiply the matrix by inverse of another one
//-------------------------------------------------------------------- const trans_perspective& operator /= (const trans_perspective& m)
// Set the transformations using two arbitrary quadrangles.
void quad_to_quad(const double* src, const double* dst)
{ {
return multiply_inv(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];
} }
m_valid = simul_eq<8, 1>::solve(left, right, m_mtx); const trans_perspective& operator /= (const trans_affine& m)
{
return multiply_inv(m);
} }
// Multiply the matrix by another one and return
//-------------------------------------------------------------------- // the result in a separete matrix.
// Set the direct transformations, i.e., rectangle -> quadrangle trans_perspective operator * (const trans_perspective& m)
void rect_to_quad(double x1, double y1, double x2, double y2,
const double* quad)
{ {
double src[8]; return trans_perspective(*this).multiply(m);
src[0] = src[6] = x1; }
src[2] = src[4] = x2; trans_perspective operator * (const trans_affine& m)
src[1] = src[3] = y1; {
src[5] = src[7] = y2; return trans_perspective(*this).multiply(m);
quad_to_quad(src, quad);
} }
// Multiply the matrix by inverse of another one
//-------------------------------------------------------------------- // and return the result in a separete matrix.
// Set the reverse transformations, i.e., quadrangle -> rectangle trans_perspective operator / (const trans_perspective& m)
void quad_to_rect(const double* quad,
double x1, double y1, double x2, double y2)
{ {
double dst[8]; return trans_perspective(*this).multiply_inv(m);
dst[0] = dst[6] = x1; }
dst[2] = dst[4] = x2; trans_perspective operator / (const trans_affine& m)
dst[1] = dst[3] = y1; {
dst[5] = dst[7] = y2; return trans_perspective(*this).multiply_inv(m);
quad_to_quad(quad, dst);
} }
//-------------------------------------------------------------------- // Calculate and return the inverse matrix
// Check if the equations were solved successfully trans_perspective operator ~ () const
bool is_valid() const { return m_valid; }
//--------------------------------------------------------------------
// Transform a point (x, y)
void transform(double* x, double* y) const
{ {
double tx = *x; trans_perspective ret = *this;
double ty = *y; ret.invert();
double d = 1.0 / (m_mtx[6][0] * tx + m_mtx[7][0] * ty + 1.0); return ret;
*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;
} }
// 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 class iterator_x
{ {
@ -153,17 +240,16 @@ namespace agg
double y; double y;
iterator_x() {} iterator_x() {}
iterator_x(double tx, double ty, double step, const double m[8][1]) : iterator_x(double px, double py, double step, const trans_perspective& m) :
den(m[6][0] * tx + m[7][0] * ty + 1.0), den(px * m.w0 + py * m.w1 + m.w2),
den_step(m[6][0] * step), den_step(m.w0 * step),
nom_x(m[0][0] + m[1][0] * tx + m[2][0] * ty), nom_x(px * m.sx + py * m.shx + m.tx),
nom_x_step(m[1][0] * step), nom_x_step(step * m.sx),
nom_y(m[3][0] + m[4][0] * tx + m[5][0] * ty), nom_y(px * m.shy + py * m.sy + m.ty),
nom_y_step(m[4][0] * step), nom_y_step(step * m.shy),
x(nom_x / den), x(nom_x / den),
y(nom_y / den) y(nom_y / den)
{ {}
}
void operator ++ () void operator ++ ()
{ {
@ -179,14 +265,467 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
iterator_x begin(double x, double y, double step) const 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 #endif

View file

@ -33,6 +33,11 @@ namespace agg
void magnification(double m) { m_magn = m; } void magnification(double m) { m_magn = m; }
void radius(double r) { m_radius = r; } 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 transform(double* x, double* y) const;
void inverse_transform(double* x, double* y) const; void inverse_transform(double* x, double* y) const;

View file

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

View file

@ -51,24 +51,24 @@ namespace agg
vcgen_stroke(); vcgen_stroke();
void line_cap(line_cap_e lc) { m_line_cap = lc; } void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
void line_join(line_join_e lj) { m_line_join = lj; } void line_join(line_join_e lj) { m_stroker.line_join(lj); }
void inner_join(inner_join_e ij) { m_inner_join = ij; } void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
line_cap_e line_cap() const { return m_line_cap; } line_cap_e line_cap() const { return m_stroker.line_cap(); }
line_join_e line_join() const { return m_line_join; } line_join_e line_join() const { return m_stroker.line_join(); }
inner_join_e inner_join() const { return m_inner_join; } inner_join_e inner_join() const { return m_stroker.inner_join(); }
void width(double w) { m_width = w * 0.5; } void width(double w) { m_stroker.width(w); }
void miter_limit(double ml) { m_miter_limit = ml; } void miter_limit(double ml) { m_stroker.miter_limit(ml); }
void miter_limit_theta(double t); void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
void approximation_scale(double as) { m_approx_scale = as; } void approximation_scale(double as) { m_stroker.approximation_scale(as); }
double width() const { return m_width * 2.0; } double width() const { return m_stroker.width(); }
double miter_limit() const { return m_miter_limit; } double miter_limit() const { return m_stroker.miter_limit(); }
double inner_miter_limit() const { return m_inner_miter_limit; } double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
double approximation_scale() const { return m_approx_scale; } double approximation_scale() const { return m_stroker.approximation_scale(); }
void shorten(double s) { m_shorten = s; } void shorten(double s) { m_shorten = s; }
double shorten() const { return m_shorten; } double shorten() const { return m_shorten; }
@ -85,16 +85,10 @@ namespace agg
vcgen_stroke(const vcgen_stroke&); vcgen_stroke(const vcgen_stroke&);
const vcgen_stroke& operator = (const vcgen_stroke&); const vcgen_stroke& operator = (const vcgen_stroke&);
math_stroke<coord_storage> m_stroker;
vertex_storage m_src_vertices; vertex_storage m_src_vertices;
coord_storage m_out_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; double m_shorten;
line_cap_e m_line_cap;
line_join_e m_line_join;
inner_join_e m_inner_join;
unsigned m_closed; unsigned m_closed;
status_e m_status; status_e m_status;
status_e m_prev_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 // Modified agg::pod_bvector. The data is interpreted as a sequence
// of vertices. It means that the type T must expose: // 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 // that is called every time new vertex is being added. The main purpose
// of this operator is the possibility to calculate some values during // of this operator is the possibility to calculate some values during

View file

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

View file

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

View file

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

View file

@ -42,8 +42,8 @@ namespace agg
// [2] | [3] // [2] | [3]
// <3> // <3>
// 0,1,2,3,4,5,6,7 // 0,1,2,3,4,5,6,7
int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 }; const 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_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); m_subpixel_width = uround(w * subpixel_scale);
unsigned size = m_subpixel_width + subpixel_scale * 6; unsigned size = m_subpixel_width + subpixel_scale * 6;
if(size > m_size) if(size > m_profile.size())
{ {
delete [] m_profile; m_profile.resize(size);
m_profile = new value_type[m_size = size];
} }
return m_profile; return &m_profile[0];
} }

View file

@ -21,7 +21,7 @@
namespace agg namespace agg
{ {
int16u g_sqrt_table[1024] = int16u g_sqrt_table[1024] = //----------g_sqrt_table
{ {
0, 0,
2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444, 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, 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, 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 trans_affine& trans_affine::parl_to_parl(const double* src,
const double* dst) const double* dst)
{ {
m0 = src[2] - src[0]; sx = src[2] - src[0];
m1 = src[3] - src[1]; shy = src[3] - src[1];
m2 = src[4] - src[0]; shx = src[4] - src[0];
m3 = src[5] - src[1]; sy = src[5] - src[1];
m4 = src[0]; tx = src[0];
m5 = src[1]; ty = src[1];
invert(); invert();
multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1], multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1],
dst[4] - dst[0], dst[5] - 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) const trans_affine& trans_affine::multiply(const trans_affine& m)
{ {
double t0 = m0 * m.m0 + m1 * m.m2; double t0 = sx * m.sx + shy * m.shx;
double t2 = m2 * m.m0 + m3 * m.m2; double t2 = shx * m.sx + sy * m.shx;
double t4 = m4 * m.m0 + m5 * m.m2 + m.m4; double t4 = tx * m.sx + ty * m.shx + m.tx;
m1 = m0 * m.m1 + m1 * m.m3; shy = sx * m.shy + shy * m.sy;
m3 = m2 * m.m1 + m3 * m.m3; sy = shx * m.shy + sy * m.sy;
m5 = m4 * m.m1 + m5 * m.m3 + m.m5; ty = tx * m.shy + ty * m.sy + m.ty;
m0 = t0; sx = t0;
m2 = t2; shx = t2;
m4 = t4; tx = t4;
return *this; return *this;
} }
@ -85,18 +85,18 @@ namespace agg
//------------------------------------------------------------------------ //------------------------------------------------------------------------
const trans_affine& trans_affine::invert() const trans_affine& trans_affine::invert()
{ {
double d = determinant(); double d = determinant_reciprocal();
double t0 = m3 * d; double t0 = sy * d;
m3 = m0 * d; sy = sx * d;
m1 = -m1 * d; shy = -shy * d;
m2 = -m2 * d; shx = -shx * d;
double t4 = -m4 * t0 - m5 * m2; double t4 = -tx * t0 - ty * shx;
m5 = -m4 * m1 - m5 * m3; ty = -tx * shy - ty * sy;
m0 = t0; sx = t0;
m4 = t4; tx = t4;
return *this; return *this;
} }
@ -104,55 +104,55 @@ namespace agg
//------------------------------------------------------------------------ //------------------------------------------------------------------------
const trans_affine& trans_affine::flip_x() const trans_affine& trans_affine::flip_x()
{ {
m0 = -m0; sx = -sx;
m1 = -m1; shy = -shy;
m4 = -m4; tx = -tx;
return *this; return *this;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
const trans_affine& trans_affine::flip_y() const trans_affine& trans_affine::flip_y()
{ {
m2 = -m2; shx = -shx;
m3 = -m3; sy = -sy;
m5 = -m5; ty = -ty;
return *this; return *this;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
const trans_affine& trans_affine::reset() const trans_affine& trans_affine::reset()
{ {
m0 = m3 = 1.0; sx = sy = 1.0;
m1 = m2 = m4 = m5 = 0.0; shy = shx = tx = ty = 0.0;
return *this; 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 bool trans_affine::is_identity(double epsilon) const
{ {
return is_equal_eps(m0, 1.0, epsilon) && return is_equal_eps(sx, 1.0, epsilon) &&
is_equal_eps(m1, 0.0, epsilon) && is_equal_eps(shy, 0.0, epsilon) &&
is_equal_eps(m2, 0.0, epsilon) && is_equal_eps(shx, 0.0, epsilon) &&
is_equal_eps(m3, 1.0, epsilon) && is_equal_eps(sy, 1.0, epsilon) &&
is_equal_eps(m4, 0.0, epsilon) && is_equal_eps(tx, 0.0, epsilon) &&
is_equal_eps(m5, 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 bool trans_affine::is_equal(const trans_affine& m, double epsilon) const
{ {
return is_equal_eps(m0, m.m0, epsilon) && return is_equal_eps(sx, m.sx, epsilon) &&
is_equal_eps(m1, m.m1, epsilon) && is_equal_eps(shy, m.shy, epsilon) &&
is_equal_eps(m2, m.m2, epsilon) && is_equal_eps(shx, m.shx, epsilon) &&
is_equal_eps(m3, m.m3, epsilon) && is_equal_eps(sy, m.sy, epsilon) &&
is_equal_eps(m4, m.m4, epsilon) && is_equal_eps(tx, m.tx, epsilon) &&
is_equal_eps(m5, m.m5, epsilon); is_equal_eps(ty, m.ty, epsilon);
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@ -170,13 +170,12 @@ namespace agg
//------------------------------------------------------------------------ //------------------------------------------------------------------------
void trans_affine::translation(double* dx, double* dy) const void trans_affine::translation(double* dx, double* dy) const
{ {
trans_affine t(*this); *dx = tx;
t *= trans_affine_rotation(-rotation()); *dy = ty;
t.transform(dx, dy);
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
void trans_affine::scaling(double* sx, double* sy) const void trans_affine::scaling(double* x, double* y) const
{ {
double x1 = 0.0; double x1 = 0.0;
double y1 = 0.0; double y1 = 0.0;
@ -186,8 +185,8 @@ namespace agg
t *= trans_affine_rotation(-rotation()); t *= trans_affine_rotation(-rotation());
t.transform(&x1, &y1); t.transform(&x1, &y1);
t.transform(&x2, &y2); t.transform(&x2, &y2);
*sx = x2 - x1; *x = x2 - x1;
*sy = y2 - y1; *y = y2 - y1;
} }

View file

@ -40,10 +40,30 @@ namespace agg
//------------------------------------------------------------------------ //------------------------------------------------------------------------
void trans_warp_magnifier::inverse_transform(double* x, double* y) const void trans_warp_magnifier::inverse_transform(double* x, double* y) const
{ {
trans_warp_magnifier t(*this); // New version by Andrew Skalkin
t.magnification(1.0 / m_magn); //-----------------
t.radius(m_radius * m_magn); double dx = *x - m_xc;
t.transform(x, y); 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() : vcgen_contour::vcgen_contour() :
m_stroker(),
m_width(1),
m_src_vertices(), m_src_vertices(),
m_out_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_status(initial),
m_src_vertex(0), m_src_vertex(0),
m_closed(0), m_closed(0),
@ -43,26 +37,15 @@ namespace agg
{ {
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
void vcgen_contour::remove_all() void vcgen_contour::remove_all()
{ {
m_src_vertices.remove_all(); m_src_vertices.remove_all();
m_closed = 0; m_closed = 0;
m_orientation = 0; m_orientation = 0;
m_abs_width = fabs(m_width);
m_signed_width = m_width;
m_status = initial; 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) void vcgen_contour::add_vertex(double x, double y, unsigned cmd)
{ {
@ -91,14 +74,12 @@ namespace agg
} }
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
void vcgen_contour::rewind(unsigned) void vcgen_contour::rewind(unsigned)
{ {
if(m_status == initial) if(m_status == initial)
{ {
m_src_vertices.close(true); m_src_vertices.close(true);
m_signed_width = m_width;
if(m_auto_detect) if(m_auto_detect)
{ {
if(!is_oriented(m_orientation)) if(!is_oriented(m_orientation))
@ -110,14 +91,13 @@ namespace agg
} }
if(is_oriented(m_orientation)) 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_status = ready;
m_src_vertex = 0; m_src_vertex = 0;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
unsigned vcgen_contour::vertex(double* x, double* y) unsigned vcgen_contour::vertex(double* x, double* y)
{ {
@ -146,18 +126,12 @@ namespace agg
m_status = end_poly; m_status = end_poly;
break; break;
} }
stroke_calc_join(m_out_vertices, m_stroker.calc_join(m_out_vertices,
m_src_vertices.prev(m_src_vertex), m_src_vertices.prev(m_src_vertex),
m_src_vertices.curr(m_src_vertex), m_src_vertices.curr(m_src_vertex),
m_src_vertices.next(m_src_vertex), m_src_vertices.next(m_src_vertex),
m_src_vertices.prev(m_src_vertex).dist, m_src_vertices.prev(m_src_vertex).dist,
m_src_vertices.curr(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_vertex; ++m_src_vertex;
m_status = out_vertices; m_status = out_vertices;
m_out_vertex = 0; m_out_vertex = 0;

View file

@ -25,16 +25,10 @@ namespace agg
//------------------------------------------------------------------------ //------------------------------------------------------------------------
vcgen_stroke::vcgen_stroke() : vcgen_stroke::vcgen_stroke() :
m_stroker(),
m_src_vertices(), m_src_vertices(),
m_out_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_shorten(0.0),
m_line_cap(butt_cap),
m_line_join(miter_join),
m_inner_join(inner_miter),
m_closed(0), m_closed(0),
m_status(initial), m_status(initial),
m_src_vertex(0), 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() 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) void vcgen_stroke::rewind(unsigned)
{ {
@ -135,13 +105,10 @@ namespace agg
break; break;
case cap1: case cap1:
stroke_calc_cap(m_out_vertices, m_stroker.calc_cap(m_out_vertices,
m_src_vertices[0], m_src_vertices[0],
m_src_vertices[1], m_src_vertices[1],
m_src_vertices[0].dist, m_src_vertices[0].dist);
m_line_cap,
m_width,
m_approx_scale);
m_src_vertex = 1; m_src_vertex = 1;
m_prev_status = outline1; m_prev_status = outline1;
m_status = out_vertices; m_status = out_vertices;
@ -149,13 +116,10 @@ namespace agg
break; break;
case cap2: 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() - 1],
m_src_vertices[m_src_vertices.size() - 2], m_src_vertices[m_src_vertices.size() - 2],
m_src_vertices[m_src_vertices.size() - 2].dist, m_src_vertices[m_src_vertices.size() - 2].dist);
m_line_cap,
m_width,
m_approx_scale);
m_prev_status = outline2; m_prev_status = outline2;
m_status = out_vertices; m_status = out_vertices;
m_out_vertex = 0; m_out_vertex = 0;
@ -179,18 +143,12 @@ namespace agg
break; break;
} }
} }
stroke_calc_join(m_out_vertices, m_stroker.calc_join(m_out_vertices,
m_src_vertices.prev(m_src_vertex), m_src_vertices.prev(m_src_vertex),
m_src_vertices.curr(m_src_vertex), m_src_vertices.curr(m_src_vertex),
m_src_vertices.next(m_src_vertex), m_src_vertices.next(m_src_vertex),
m_src_vertices.prev(m_src_vertex).dist, m_src_vertices.prev(m_src_vertex).dist,
m_src_vertices.curr(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_vertex; ++m_src_vertex;
m_prev_status = m_status; m_prev_status = m_status;
m_status = out_vertices; m_status = out_vertices;
@ -210,18 +168,12 @@ namespace agg
} }
--m_src_vertex; --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.next(m_src_vertex),
m_src_vertices.curr(m_src_vertex), m_src_vertices.curr(m_src_vertex),
m_src_vertices.prev(m_src_vertex), m_src_vertices.prev(m_src_vertex),
m_src_vertices.curr(m_src_vertex).dist, m_src_vertices.curr(m_src_vertex).dist,
m_src_vertices.prev(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_prev_status = m_status; m_prev_status = m_status;
m_status = out_vertices; 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_fill = Color('white')
popplaces_text_symbolizer.halo_radius = 1 popplaces_text_symbolizer.halo_radius = 1
popplaces_rule.symbols.append(popplaces_text_symbolizer) 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) popplaces_style.rules.append(popplaces_rule)

View file

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

View file

@ -126,16 +126,23 @@ namespace mapnik
if ( sym.first == "PointSymbolizer") if ( sym.first == "PointSymbolizer")
{ {
std::string file = boost::optional<std::string> file =
sym.second.get<std::string>("<xmlattr>.file"); sym.second.get_optional<std::string>("<xmlattr>.file");
std::string type = boost::optional<std::string> type =
sym.second.get<std::string>("<xmlattr>.type"); sym.second.get_optional<std::string>("<xmlattr>.type");
unsigned width = boost::optional<unsigned> width =
sym.second.get<unsigned>("<xmlattr>.width"); sym.second.get_optional<unsigned>("<xmlattr>.width");
unsigned height = boost::optional<unsigned> height =
sym.second.get<unsigned>("<xmlattr>.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") else if ( sym.first == "LinePatternSymbolizer")
{ {