1.upgrade to latest agg2.4
2.added default PointSymbolizer in load_map.cpp
This commit is contained in:
parent
e7bab0b8c8
commit
bf297ec3ca
79 changed files with 4130 additions and 2262 deletions
|
@ -57,7 +57,7 @@ namespace agg
|
|||
};
|
||||
|
||||
alpha_mask_u8() : m_rbuf(0) {}
|
||||
alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
|
||||
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||
|
||||
|
@ -70,7 +70,7 @@ namespace agg
|
|||
{
|
||||
if(x >= 0 && y >= 0 &&
|
||||
x < (int)m_rbuf->width() &&
|
||||
y <= (int)m_rbuf->height())
|
||||
y < (int)m_rbuf->height())
|
||||
{
|
||||
return (cover_type)m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset);
|
||||
|
@ -83,7 +83,7 @@ namespace agg
|
|||
{
|
||||
if(x >= 0 && y >= 0 &&
|
||||
x < (int)m_rbuf->width() &&
|
||||
y <= (int)m_rbuf->height())
|
||||
y < (int)m_rbuf->height())
|
||||
{
|
||||
return (cover_type)((cover_full + val *
|
||||
m_mask_function.calculate(
|
||||
|
@ -361,7 +361,7 @@ namespace agg
|
|||
};
|
||||
|
||||
amask_no_clip_u8() : m_rbuf(0) {}
|
||||
amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
|
||||
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||
|
||||
|
|
|
@ -109,20 +109,27 @@ namespace agg
|
|||
typedef T value_type;
|
||||
typedef pod_array<T> self_type;
|
||||
|
||||
~pod_array() { delete [] m_array; }
|
||||
~pod_array() { pod_allocator<T>::deallocate(m_array, m_size); }
|
||||
pod_array() : m_array(0), m_size(0) {}
|
||||
pod_array(unsigned size) : m_array(new T[size]), m_size(size) {}
|
||||
|
||||
pod_array(unsigned size) :
|
||||
m_array(pod_allocator<T>::allocate(size)),
|
||||
m_size(size)
|
||||
{}
|
||||
|
||||
pod_array(const self_type& v) :
|
||||
m_array(new T[v.m_size]), m_size(v.m_size)
|
||||
m_array(pod_allocator<T>::allocate(v.m_size)),
|
||||
m_size(v.m_size)
|
||||
{
|
||||
memcpy(m_array, v.m_array, sizeof(T) * m_size);
|
||||
}
|
||||
|
||||
void resize(unsigned size)
|
||||
{
|
||||
if(size != m_size)
|
||||
{
|
||||
delete [] m_array;
|
||||
m_array = new T[m_size = size];
|
||||
pod_allocator<T>::deallocate(m_array, m_size);
|
||||
m_array = pod_allocator<T>::allocate(m_size = size);
|
||||
}
|
||||
}
|
||||
const self_type& operator = (const self_type& v)
|
||||
|
@ -157,7 +164,7 @@ namespace agg
|
|||
public:
|
||||
typedef T value_type;
|
||||
|
||||
~pod_vector() { delete [] m_array; }
|
||||
~pod_vector() { pod_allocator<T>::deallocate(m_array, m_capacity); }
|
||||
pod_vector() : m_size(0), m_capacity(0), m_array(0) {}
|
||||
pod_vector(unsigned cap, unsigned extra_tail=0);
|
||||
|
||||
|
@ -215,9 +222,9 @@ namespace agg
|
|||
m_size = 0;
|
||||
if(cap > m_capacity)
|
||||
{
|
||||
delete [] m_array;
|
||||
pod_allocator<T>::deallocate(m_array, m_capacity);
|
||||
m_capacity = cap + extra_tail;
|
||||
m_array = m_capacity ? new T [m_capacity] : 0;
|
||||
m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,9 +245,9 @@ namespace agg
|
|||
{
|
||||
if(new_size > m_capacity)
|
||||
{
|
||||
T* data = new T[new_size];
|
||||
T* data = pod_allocator<T>::allocate(new_size);
|
||||
memcpy(data, m_array, m_size * sizeof(T));
|
||||
delete [] m_array;
|
||||
pod_allocator<T>::deallocate(m_array, m_capacity);
|
||||
m_array = data;
|
||||
}
|
||||
}
|
||||
|
@ -252,13 +259,15 @@ namespace agg
|
|||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) :
|
||||
m_size(0), m_capacity(cap + extra_tail), m_array(new T[m_capacity]) {}
|
||||
m_size(0),
|
||||
m_capacity(cap + extra_tail),
|
||||
m_array(pod_allocator<T>::allocate(m_capacity)) {}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) :
|
||||
m_size(v.m_size),
|
||||
m_capacity(v.m_capacity),
|
||||
m_array(v.m_capacity ? new T [v.m_capacity] : 0)
|
||||
m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0)
|
||||
{
|
||||
memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
|
||||
}
|
||||
|
@ -509,11 +518,11 @@ namespace agg
|
|||
T** blk = m_blocks + m_num_blocks - 1;
|
||||
while(m_num_blocks--)
|
||||
{
|
||||
delete [] *blk;
|
||||
pod_allocator<T>::deallocate(*blk, block_size);
|
||||
--blk;
|
||||
}
|
||||
delete [] m_blocks;
|
||||
}
|
||||
pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
|
||||
}
|
||||
|
||||
|
||||
|
@ -526,7 +535,13 @@ namespace agg
|
|||
unsigned nb = (size + block_mask) >> block_shift;
|
||||
while(m_num_blocks > nb)
|
||||
{
|
||||
delete [] m_blocks[--m_num_blocks];
|
||||
pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size);
|
||||
}
|
||||
if(m_num_blocks == 0)
|
||||
{
|
||||
pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
|
||||
m_blocks = 0;
|
||||
m_max_blocks = 0;
|
||||
}
|
||||
m_size = size;
|
||||
}
|
||||
|
@ -562,13 +577,15 @@ namespace agg
|
|||
m_size(v.m_size),
|
||||
m_num_blocks(v.m_num_blocks),
|
||||
m_max_blocks(v.m_max_blocks),
|
||||
m_blocks(v.m_max_blocks ? new T* [v.m_max_blocks] : 0),
|
||||
m_blocks(v.m_max_blocks ?
|
||||
pod_allocator<T*>::allocate(v.m_max_blocks) :
|
||||
0),
|
||||
m_block_ptr_inc(v.m_block_ptr_inc)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < v.m_num_blocks; ++i)
|
||||
{
|
||||
m_blocks[i] = new T [block_size];
|
||||
m_blocks[i] = pod_allocator<T>::allocate(block_size);
|
||||
memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
@ -599,7 +616,7 @@ namespace agg
|
|||
{
|
||||
if(nb >= m_max_blocks)
|
||||
{
|
||||
T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc];
|
||||
T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc);
|
||||
|
||||
if(m_blocks)
|
||||
{
|
||||
|
@ -607,12 +624,12 @@ namespace agg
|
|||
m_blocks,
|
||||
m_num_blocks * sizeof(T*));
|
||||
|
||||
delete [] m_blocks;
|
||||
pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
|
||||
}
|
||||
m_blocks = new_blocks;
|
||||
m_max_blocks += m_block_ptr_inc;
|
||||
}
|
||||
m_blocks[nb] = new T [block_size];
|
||||
m_blocks[nb] = pod_allocator<T>::allocate(block_size);
|
||||
m_num_blocks++;
|
||||
}
|
||||
|
||||
|
@ -753,7 +770,7 @@ namespace agg
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------pod_allocator
|
||||
//---------------------------------------------------------block_allocator
|
||||
// Allocator for arbitrary POD data. Most usable in different cache
|
||||
// systems for efficient memory allocations.
|
||||
// Memory is allocated with blocks of fixed size ("block_size" in
|
||||
|
@ -761,20 +778,26 @@ namespace agg
|
|||
// creates a new block of the required size. However, the most efficient
|
||||
// use is when the average reqired size is much less than the block size.
|
||||
//------------------------------------------------------------------------
|
||||
class pod_allocator
|
||||
class block_allocator
|
||||
{
|
||||
struct block_type
|
||||
{
|
||||
int8u* data;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
public:
|
||||
void remove_all()
|
||||
{
|
||||
if(m_num_blocks)
|
||||
{
|
||||
int8u** blk = m_blocks + m_num_blocks - 1;
|
||||
block_type* blk = m_blocks + m_num_blocks - 1;
|
||||
while(m_num_blocks--)
|
||||
{
|
||||
delete [] *blk;
|
||||
pod_allocator<int8u>::deallocate(blk->data, blk->size);
|
||||
--blk;
|
||||
}
|
||||
delete [] m_blocks;
|
||||
pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
|
||||
}
|
||||
m_num_blocks = 0;
|
||||
m_max_blocks = 0;
|
||||
|
@ -783,12 +806,12 @@ namespace agg
|
|||
m_rest = 0;
|
||||
}
|
||||
|
||||
~pod_allocator()
|
||||
~block_allocator()
|
||||
{
|
||||
remove_all();
|
||||
}
|
||||
|
||||
pod_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
|
||||
block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
|
||||
m_block_size(block_size),
|
||||
m_block_ptr_inc(block_ptr_inc),
|
||||
m_num_blocks(0),
|
||||
|
@ -808,7 +831,9 @@ namespace agg
|
|||
int8u* ptr = m_buf_ptr;
|
||||
if(alignment > 1)
|
||||
{
|
||||
unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment;
|
||||
unsigned align =
|
||||
(alignment - unsigned((size_t)ptr) % alignment) % alignment;
|
||||
|
||||
size += align;
|
||||
ptr += align;
|
||||
if(size <= m_rest)
|
||||
|
@ -835,20 +860,25 @@ namespace agg
|
|||
if(size < m_block_size) size = m_block_size;
|
||||
if(m_num_blocks >= m_max_blocks)
|
||||
{
|
||||
int8u** new_blocks = new int8u* [m_max_blocks + m_block_ptr_inc];
|
||||
block_type* new_blocks =
|
||||
pod_allocator<block_type>::allocate(m_max_blocks + m_block_ptr_inc);
|
||||
|
||||
if(m_blocks)
|
||||
{
|
||||
memcpy(new_blocks,
|
||||
m_blocks,
|
||||
m_num_blocks * sizeof(int8u*));
|
||||
|
||||
delete [] m_blocks;
|
||||
m_num_blocks * sizeof(block_type));
|
||||
pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
|
||||
}
|
||||
m_blocks = new_blocks;
|
||||
m_max_blocks += m_block_ptr_inc;
|
||||
}
|
||||
m_blocks[m_num_blocks] = m_buf_ptr = new int8u [size];
|
||||
|
||||
m_blocks[m_num_blocks].size = size;
|
||||
m_blocks[m_num_blocks].data =
|
||||
m_buf_ptr =
|
||||
pod_allocator<int8u>::allocate(size);
|
||||
|
||||
m_num_blocks++;
|
||||
m_rest = size;
|
||||
}
|
||||
|
@ -857,7 +887,7 @@ namespace agg
|
|||
unsigned m_block_ptr_inc;
|
||||
unsigned m_num_blocks;
|
||||
unsigned m_max_blocks;
|
||||
int8u** m_blocks;
|
||||
block_type* m_blocks;
|
||||
int8u* m_buf_ptr;
|
||||
unsigned m_rest;
|
||||
};
|
||||
|
@ -1014,7 +1044,6 @@ namespace agg
|
|||
return j;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------invert_container
|
||||
template<class Array> void invert_container(Array& arr)
|
||||
{
|
||||
|
@ -1026,7 +1055,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------binary_search_pos
|
||||
template<class Array, class Value, class Less>
|
||||
unsigned binary_search_pos(const Array& arr, const Value& val, Less less)
|
||||
|
@ -1052,6 +1080,40 @@ namespace agg
|
|||
return end;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------range_adaptor
|
||||
template<class Array> class range_adaptor
|
||||
{
|
||||
public:
|
||||
typedef typename Array::value_type value_type;
|
||||
|
||||
range_adaptor(Array& array, unsigned start, unsigned size) :
|
||||
m_array(array), m_start(start), m_size(size)
|
||||
{}
|
||||
|
||||
unsigned size() const { return m_size; }
|
||||
const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; }
|
||||
value_type& operator [] (unsigned i) { return m_array[m_start + i]; }
|
||||
const value_type& at(unsigned i) const { return m_array[m_start + i]; }
|
||||
value_type& at(unsigned i) { return m_array[m_start + i]; }
|
||||
value_type value_at(unsigned i) const { return m_array[m_start + i]; }
|
||||
|
||||
private:
|
||||
Array& m_array;
|
||||
unsigned m_start;
|
||||
unsigned m_size;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------int_less
|
||||
inline bool int_less(int a, int b) { return a < b; }
|
||||
|
||||
//------------------------------------------------------------int_greater
|
||||
inline bool int_greater(int a, int b) { return a > b; }
|
||||
|
||||
//----------------------------------------------------------unsigned_less
|
||||
inline bool unsigned_less(unsigned a, unsigned b) { return a < b; }
|
||||
|
||||
//-------------------------------------------------------unsigned_greater
|
||||
inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,43 @@
|
|||
#include <math.h>
|
||||
#include "agg_config.h"
|
||||
|
||||
//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
|
||||
#ifdef AGG_CUSTOM_ALLOCATOR
|
||||
#include "agg_allocator.h"
|
||||
#else
|
||||
namespace agg
|
||||
{
|
||||
// The policy of all AGG containers and memory allocation strategy
|
||||
// in general is that no allocated data requires explicit construction.
|
||||
// It means that the allocator can be really simple; you can even
|
||||
// replace new/delete to malloc/free. The constructors and destructors
|
||||
// won't be called in this case, however everything will remain working.
|
||||
// The second argument of deallocate() is the size of the allocated
|
||||
// block. You can use this information if you wish.
|
||||
//------------------------------------------------------------pod_allocator
|
||||
template<class T> struct pod_allocator
|
||||
{
|
||||
static T* allocate(unsigned num) { return new T [num]; }
|
||||
static void deallocate(T* ptr, unsigned) { delete [] ptr; }
|
||||
};
|
||||
|
||||
// Single object allocator. It's also can be replaced with your custom
|
||||
// allocator. The difference is that it can only allocate a single
|
||||
// object and the constructor and destructor must be called.
|
||||
// In AGG there is no need to allocate an array of objects with
|
||||
// calling their constructors (only single ones). So that, if you
|
||||
// replace these new/delete to malloc/free make sure that the in-place
|
||||
// new is called and take care of calling the destructor too.
|
||||
//------------------------------------------------------------obj_allocator
|
||||
template<class T> struct obj_allocator
|
||||
{
|
||||
static T* allocate() { return new T; }
|
||||
static void deallocate(T* ptr) { delete ptr; }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-------------------------------------------------------- Default basic types
|
||||
//
|
||||
// If the compiler has different capacity of the basic types you can redefine
|
||||
|
@ -93,15 +130,17 @@ namespace agg
|
|||
#pragma warning(disable : 4035) //Disable warning "no return value"
|
||||
AGG_INLINE int iround(double v) //-------iround
|
||||
{
|
||||
int t;
|
||||
__asm fld qword ptr [v]
|
||||
__asm fistp dword ptr [ebp-8]
|
||||
__asm mov eax, dword ptr [ebp-8]
|
||||
__asm fistp dword ptr [t]
|
||||
__asm mov eax, dword ptr [t]
|
||||
}
|
||||
AGG_INLINE unsigned uround(double v) //-------uround
|
||||
{
|
||||
unsigned t;
|
||||
__asm fld qword ptr [v]
|
||||
__asm fistp dword ptr [ebp-8]
|
||||
__asm mov eax, dword ptr [ebp-8]
|
||||
__asm fistp dword ptr [t]
|
||||
__asm mov eax, dword ptr [t]
|
||||
}
|
||||
#pragma warning(pop)
|
||||
AGG_INLINE unsigned ufloor(double v) //-------ufloor
|
||||
|
@ -218,16 +257,19 @@ namespace agg
|
|||
//----------------------------------------------------------------rect_base
|
||||
template<class T> struct rect_base
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef rect_base<T> self_type;
|
||||
T x1;
|
||||
T y1;
|
||||
T x2;
|
||||
T y2;
|
||||
T x1, y1, x2, y2;
|
||||
|
||||
rect_base() {}
|
||||
rect_base(T x1_, T y1_, T x2_, T y2_) :
|
||||
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
|
||||
|
||||
void init(T x1_, T y1_, T x2_, T y2_)
|
||||
{
|
||||
x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
|
||||
}
|
||||
|
||||
const self_type& normalize()
|
||||
{
|
||||
T t;
|
||||
|
@ -249,6 +291,11 @@ namespace agg
|
|||
{
|
||||
return x1 <= x2 && y1 <= y2;
|
||||
}
|
||||
|
||||
bool hit_test(T x, T y) const
|
||||
{
|
||||
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------intersect_rectangles
|
||||
|
@ -451,6 +498,31 @@ namespace agg
|
|||
typedef vertex_base<float> vertex_f; //-----vertex_f
|
||||
typedef vertex_base<double> vertex_d; //-----vertex_d
|
||||
|
||||
//----------------------------------------------------------------row_info
|
||||
template<class T> struct row_info
|
||||
{
|
||||
int x1, x2;
|
||||
T* ptr;
|
||||
row_info() {}
|
||||
row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------const_row_info
|
||||
template<class T> struct const_row_info
|
||||
{
|
||||
int x1, x2;
|
||||
const T* ptr;
|
||||
const_row_info() {}
|
||||
const_row_info(int x1_, int x2_, const T* ptr_) :
|
||||
x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------is_equal_eps
|
||||
template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
|
||||
{
|
||||
return fabs(v1 - v2) <= double(epsilon);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef AGG_BSPLINE_INCLUDED
|
||||
#define AGG_BSPLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
@ -40,7 +40,6 @@ namespace agg
|
|||
class bspline
|
||||
{
|
||||
public:
|
||||
~bspline();
|
||||
bspline();
|
||||
bspline(int num);
|
||||
bspline(int num, const double* x, const double* y);
|
||||
|
@ -67,7 +66,7 @@ namespace agg
|
|||
int m_num;
|
||||
double* m_x;
|
||||
double* m_y;
|
||||
double* m_am;
|
||||
pod_array<double> m_am;
|
||||
mutable int m_last_idx;
|
||||
};
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace agg
|
|||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * base_mask) / a;
|
||||
v = value_type((v_ > base_mask) ? base_mask : v_);
|
||||
v = value_type((v_ > base_mask) ? (value_type)base_mask : v_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -162,6 +162,31 @@ namespace agg
|
|||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cv, ca;
|
||||
if(cover == cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
|
||||
ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
|
||||
v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0); }
|
||||
};
|
||||
|
@ -324,6 +349,31 @@ namespace agg
|
|||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cv, ca;
|
||||
if(cover == cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
|
||||
ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
|
||||
v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0); }
|
||||
};
|
||||
|
|
|
@ -443,32 +443,43 @@ namespace agg
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------rgb8_packed
|
||||
//-------------------------------------------------------------rgb8_packed
|
||||
inline rgba8 rgb8_packed(unsigned v)
|
||||
{
|
||||
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------bgr8_packed
|
||||
//-------------------------------------------------------------bgr8_packed
|
||||
inline rgba8 bgr8_packed(unsigned v)
|
||||
{
|
||||
return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------argb8_packed
|
||||
//------------------------------------------------------------argb8_packed
|
||||
inline rgba8 argb8_packed(unsigned v)
|
||||
{
|
||||
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------rgba8_gamma_dir
|
||||
template<class GammaLUT>
|
||||
rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma)
|
||||
{
|
||||
return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------rgba8_gamma_inv
|
||||
template<class GammaLUT>
|
||||
rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma)
|
||||
{
|
||||
return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=================================================================rgba16
|
||||
//==================================================================rgba16
|
||||
struct rgba16
|
||||
{
|
||||
typedef int16u value_type;
|
||||
|
@ -709,6 +720,22 @@ namespace agg
|
|||
return rgba16(c,a).premultiply();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------rgba16_gamma_dir
|
||||
template<class GammaLUT>
|
||||
rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma)
|
||||
{
|
||||
return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
|
||||
}
|
||||
|
||||
//------------------------------------------------------rgba16_gamma_inv
|
||||
template<class GammaLUT>
|
||||
rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma)
|
||||
{
|
||||
return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#ifndef AGG_CONFIG_INCLUDED
|
||||
#define AGG_CONFIG_INCLUDED
|
||||
|
||||
// This file can be used to redefine the default basic types such as:
|
||||
// This file can be used to redefine certain data types.
|
||||
|
||||
//---------------------------------------
|
||||
// 1. Default basic types such as:
|
||||
//
|
||||
// AGG_INT8
|
||||
// AGG_INT8U
|
||||
|
@ -23,4 +26,20 @@
|
|||
// but it won't result any crash and the rest of the library will remain
|
||||
// fully functional.
|
||||
|
||||
|
||||
//---------------------------------------
|
||||
// 2. Default rendering_buffer type. Can be:
|
||||
//
|
||||
// Provides faster access for massive pixel operations,
|
||||
// such as blur, image filtering:
|
||||
|
||||
// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
|
||||
//
|
||||
// Provides cheaper creation and destruction (no mem allocs):
|
||||
#define AGG_RENDERING_BUFFER row_accessor<int8u>
|
||||
//
|
||||
// You can still use both of them simultaneouslyin your applications
|
||||
// This #define is used only for default rendering_buffer type,
|
||||
// in short hand typedefs like pixfmt_rgba32.
|
||||
|
||||
#endif
|
||||
|
|
|
@ -45,12 +45,11 @@ namespace agg
|
|||
};
|
||||
|
||||
public:
|
||||
conv_adaptor_vcgen(VertexSource& source) :
|
||||
explicit conv_adaptor_vcgen(VertexSource& source) :
|
||||
m_source(&source),
|
||||
m_status(initial)
|
||||
{}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
Generator& generator() { return m_generator; }
|
||||
const Generator& generator() const { return m_generator; }
|
||||
|
|
|
@ -25,9 +25,8 @@ namespace agg
|
|||
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
|
||||
{
|
||||
public:
|
||||
conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
VPGen& vpgen() { return m_vpgen; }
|
||||
const VPGen& vpgen() const { return m_vpgen; }
|
||||
|
|
|
@ -25,9 +25,8 @@ namespace agg
|
|||
template<class VertexSource> class conv_close_polygon
|
||||
{
|
||||
public:
|
||||
conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
|
|
@ -28,9 +28,8 @@ namespace agg
|
|||
public:
|
||||
conv_concat(VS1& source1, VS2& source2) :
|
||||
m_source1(&source1), m_source2(&source2), m_status(2) {}
|
||||
|
||||
void set_source1(VS1& source) { m_source1 = &source; }
|
||||
void set_source2(VS2& source) { m_source2 = &source; }
|
||||
void attach1(VS1& source) { m_source1 = &source; }
|
||||
void attach2(VS2& source) { m_source2 = &source; }
|
||||
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
|
|
|
@ -60,10 +60,9 @@ namespace agg
|
|||
typedef Curve4 curve4_type;
|
||||
typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
|
||||
|
||||
conv_curve(VertexSource& source) :
|
||||
explicit conv_curve(VertexSource& source) :
|
||||
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
|
|
|
@ -89,8 +89,8 @@ namespace agg
|
|||
memset(&m_result, 0, sizeof(m_result));
|
||||
}
|
||||
|
||||
void set_source1(VSA& source) { m_src_a = &source; }
|
||||
void set_source2(VSB& source) { m_src_b = &source; }
|
||||
void attach1(VSA& source) { m_src_a = &source; }
|
||||
void attach2(VSB& source) { m_src_b = &source; }
|
||||
|
||||
void operation(gpc_op_e v) { m_operation = v; }
|
||||
|
||||
|
@ -191,10 +191,10 @@ namespace agg
|
|||
int i;
|
||||
for(i = 0; i < p.num_contours; i++)
|
||||
{
|
||||
delete [] p.contour[i].vertex;
|
||||
pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex,
|
||||
p.contour[i].num_vertices);
|
||||
}
|
||||
delete [] p.hole;
|
||||
delete [] p.contour;
|
||||
pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
|
||||
memset(&p, 0, sizeof(gpc_polygon));
|
||||
}
|
||||
|
||||
|
@ -260,7 +260,7 @@ namespace agg
|
|||
// TO DO: Clarify the "holes"
|
||||
//if(is_cw(orientation)) h.hole_flag = 1;
|
||||
|
||||
h.vertices = new gpc_vertex [h.num_vertices];
|
||||
h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices);
|
||||
gpc_vertex* d = h.vertices;
|
||||
int i;
|
||||
for(i = 0; i < h.num_vertices; i++)
|
||||
|
@ -288,19 +288,14 @@ namespace agg
|
|||
{
|
||||
p.num_contours = m_contour_accumulator.size();
|
||||
|
||||
// TO DO: Clarify the "holes"
|
||||
//p.hole = new int[p.num_contours];
|
||||
p.hole = 0;
|
||||
|
||||
p.contour = new gpc_vertex_list[p.num_contours];
|
||||
p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
|
||||
|
||||
int i;
|
||||
//int* ph = p.hole;
|
||||
gpc_vertex_list* pv = p.contour;
|
||||
for(i = 0; i < p.num_contours; i++)
|
||||
{
|
||||
const contour_header_type& h = m_contour_accumulator[i];
|
||||
// *ph++ = h.hole_flag;
|
||||
pv->num_vertices = h.num_vertices;
|
||||
pv->vertex = h.vertices;
|
||||
++pv;
|
||||
|
|
|
@ -31,8 +31,7 @@ namespace agg
|
|||
public:
|
||||
conv_transform(VertexSource& source, const Transformer& tr) :
|
||||
m_source(&source), m_trans(&tr) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
|
|
|
@ -24,9 +24,8 @@ namespace agg
|
|||
template<class VertexSource> class conv_unclose_polygon
|
||||
{
|
||||
public:
|
||||
conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
|
||||
void set_source(VertexSource& source) { m_source = &source; }
|
||||
explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
|
|
|
@ -152,7 +152,6 @@ namespace agg
|
|||
|
||||
double m_approximation_scale;
|
||||
double m_distance_tolerance_square;
|
||||
double m_distance_tolerance_manhattan;
|
||||
double m_angle_tolerance;
|
||||
unsigned m_count;
|
||||
pod_bvector<point_d> m_points;
|
||||
|
@ -464,7 +463,6 @@ namespace agg
|
|||
|
||||
double m_approximation_scale;
|
||||
double m_distance_tolerance_square;
|
||||
double m_distance_tolerance_manhattan;
|
||||
double m_angle_tolerance;
|
||||
double m_cusp_limit;
|
||||
unsigned m_count;
|
||||
|
|
|
@ -52,9 +52,13 @@ namespace agg
|
|||
enum block_size_e { block_size = 16384-16 };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
font_cache(const char* font_signature) :
|
||||
font_cache() :
|
||||
m_allocator(block_size),
|
||||
m_font_signature(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void signature(const char* font_signature)
|
||||
{
|
||||
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
|
||||
strcpy(m_font_signature, font_signature);
|
||||
|
@ -114,7 +118,7 @@ namespace agg
|
|||
}
|
||||
|
||||
private:
|
||||
pod_allocator m_allocator;
|
||||
block_allocator m_allocator;
|
||||
glyph_cache** m_glyphs[256];
|
||||
char* m_font_signature;
|
||||
};
|
||||
|
@ -135,14 +139,14 @@ namespace agg
|
|||
unsigned i;
|
||||
for(i = 0; i < m_num_fonts; ++i)
|
||||
{
|
||||
delete m_fonts[i];
|
||||
obj_allocator<font_cache>::deallocate(m_fonts[i]);
|
||||
}
|
||||
delete [] m_fonts;
|
||||
pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
font_cache_pool(unsigned max_fonts=32) :
|
||||
m_fonts(new font_cache* [max_fonts]),
|
||||
m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)),
|
||||
m_max_fonts(max_fonts),
|
||||
m_num_fonts(0),
|
||||
m_cur_font(0)
|
||||
|
@ -157,8 +161,9 @@ namespace agg
|
|||
{
|
||||
if(reset_cache)
|
||||
{
|
||||
delete m_fonts[idx];
|
||||
m_fonts[idx] = new font_cache(font_signature);
|
||||
obj_allocator<font_cache>::deallocate(m_fonts[idx]);
|
||||
m_fonts[idx] = obj_allocator<font_cache>::allocate();
|
||||
m_fonts[idx]->signature(font_signature);
|
||||
}
|
||||
m_cur_font = m_fonts[idx];
|
||||
}
|
||||
|
@ -166,13 +171,14 @@ namespace agg
|
|||
{
|
||||
if(m_num_fonts >= m_max_fonts)
|
||||
{
|
||||
delete m_fonts[0];
|
||||
obj_allocator<font_cache>::deallocate(m_fonts[0]);
|
||||
memcpy(m_fonts,
|
||||
m_fonts + 1,
|
||||
(m_max_fonts - 1) * sizeof(font_cache*));
|
||||
m_num_fonts = m_max_fonts - 1;
|
||||
}
|
||||
m_fonts[m_num_fonts] = new font_cache(font_signature);
|
||||
m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
|
||||
m_fonts[m_num_fonts]->signature(font_signature);
|
||||
m_cur_font = m_fonts[m_num_fonts];
|
||||
++m_num_fonts;
|
||||
}
|
||||
|
@ -269,6 +275,12 @@ namespace agg
|
|||
m_last_glyph(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_last_glyph()
|
||||
{
|
||||
m_prev_glyph = m_last_glyph = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* glyph(unsigned glyph_code)
|
||||
{
|
||||
|
|
|
@ -45,14 +45,14 @@ namespace agg
|
|||
|
||||
~gamma_lut()
|
||||
{
|
||||
delete [] m_inv_gamma;
|
||||
delete [] m_dir_gamma;
|
||||
pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
|
||||
pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
|
||||
}
|
||||
|
||||
gamma_lut() :
|
||||
m_gamma(1.0),
|
||||
m_dir_gamma(new HiResT[gamma_size]),
|
||||
m_inv_gamma(new LoResT[hi_res_size])
|
||||
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
|
||||
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < gamma_size; i++)
|
||||
|
@ -68,8 +68,8 @@ namespace agg
|
|||
|
||||
gamma_lut(double g) :
|
||||
m_gamma(1.0),
|
||||
m_dir_gamma(new HiResT[gamma_size]),
|
||||
m_inv_gamma(new LoResT[hi_res_size])
|
||||
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
|
||||
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
|
||||
{
|
||||
gamma(g);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef AGG_GSV_TEXT_INCLUDED
|
||||
#define AGG_GSV_TEXT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_transform.h"
|
||||
|
||||
|
@ -43,7 +43,6 @@ namespace agg
|
|||
};
|
||||
|
||||
public:
|
||||
~gsv_text();
|
||||
gsv_text();
|
||||
|
||||
void font(const void* font);
|
||||
|
@ -55,6 +54,8 @@ namespace agg
|
|||
void start_point(double x, double y);
|
||||
void text(const char* text);
|
||||
|
||||
double text_width();
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
|
@ -89,15 +90,13 @@ namespace agg
|
|||
double m_line_space;
|
||||
char m_chr[2];
|
||||
char* m_text;
|
||||
char* m_text_buf;
|
||||
unsigned m_buf_size;
|
||||
pod_array<char> m_text_buf;
|
||||
char* m_cur_chr;
|
||||
const void* m_font;
|
||||
char* m_loaded_font;
|
||||
pod_array<char> m_loaded_font;
|
||||
status m_status;
|
||||
bool m_big_endian;
|
||||
bool m_flip;
|
||||
|
||||
int8u* m_indices;
|
||||
int8* m_glyphs;
|
||||
int8* m_bglyph;
|
||||
|
|
|
@ -32,13 +32,14 @@ namespace agg
|
|||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_clip() {}
|
||||
image_accessor_clip(const pixfmt_type& pixf, const color_type& bk) :
|
||||
explicit image_accessor_clip(const pixfmt_type& pixf,
|
||||
const color_type& bk) :
|
||||
m_pixf(&pixf)
|
||||
{
|
||||
pixfmt_type::make_pix(m_bk_buf, bk);
|
||||
}
|
||||
|
||||
void set_source(const pixfmt_type& pixf)
|
||||
void attach(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ namespace agg
|
|||
m_x = m_x0 = x;
|
||||
m_y = y;
|
||||
if(y >= 0 && y < (int)m_pixf->height() &&
|
||||
x >= 0 && x+len <= (int)m_pixf->width())
|
||||
x >= 0 && x+(int)len <= (int)m_pixf->width())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
|
@ -114,9 +115,11 @@ namespace agg
|
|||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_no_clip() {}
|
||||
image_accessor_no_clip(const pixfmt_type& pixf) : m_pixf(&pixf) {}
|
||||
explicit image_accessor_no_clip(const pixfmt_type& pixf) :
|
||||
m_pixf(&pixf)
|
||||
{}
|
||||
|
||||
void set_source(const pixfmt_type& pixf)
|
||||
void attach(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
@ -159,9 +162,11 @@ namespace agg
|
|||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_clone() {}
|
||||
image_accessor_clone(const pixfmt_type& pixf) : m_pixf(&pixf) {}
|
||||
explicit image_accessor_clone(const pixfmt_type& pixf) :
|
||||
m_pixf(&pixf)
|
||||
{}
|
||||
|
||||
void set_source(const pixfmt_type& pixf)
|
||||
void attach(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
@ -233,13 +238,13 @@ namespace agg
|
|||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_wrap() {}
|
||||
image_accessor_wrap(const pixfmt_type& pixf) :
|
||||
explicit image_accessor_wrap(const pixfmt_type& pixf) :
|
||||
m_pixf(&pixf),
|
||||
m_wrap_x(pixf.width()),
|
||||
m_wrap_y(pixf.height())
|
||||
{}
|
||||
|
||||
void set_source(const pixfmt_type& pixf)
|
||||
void attach(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#ifndef AGG_IMAGE_FILTERS_INCLUDED
|
||||
#define AGG_IMAGE_FILTERS_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
#include "agg_math.h"
|
||||
|
||||
namespace agg
|
||||
|
@ -46,9 +47,6 @@ namespace agg
|
|||
class image_filter_lut
|
||||
{
|
||||
public:
|
||||
~image_filter_lut();
|
||||
image_filter_lut();
|
||||
|
||||
template<class FilterF> void calculate(const FilterF& filter,
|
||||
bool normalization=true)
|
||||
{
|
||||
|
@ -71,10 +69,10 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {}
|
||||
|
||||
template<class FilterF> image_filter_lut(const FilterF& filter,
|
||||
bool normalization=true) :
|
||||
m_weight_array(0),
|
||||
m_max_size(0)
|
||||
bool normalization=true)
|
||||
{
|
||||
calculate(filter, normalization);
|
||||
}
|
||||
|
@ -82,7 +80,7 @@ namespace agg
|
|||
double radius() const { return m_radius; }
|
||||
unsigned diameter() const { return m_diameter; }
|
||||
int start() const { return m_start; }
|
||||
const int16* weight_array() const { return m_weight_array; }
|
||||
const int16* weight_array() const { return &m_weight_array[0]; }
|
||||
void normalize();
|
||||
|
||||
private:
|
||||
|
@ -93,8 +91,7 @@ namespace agg
|
|||
double m_radius;
|
||||
unsigned m_diameter;
|
||||
int m_start;
|
||||
int16* m_weight_array;
|
||||
unsigned m_max_size;
|
||||
pod_array<int16> m_weight_array;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -142,8 +142,8 @@ namespace agg
|
|||
int octant;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
static int8u s_orthogonal_quadrant[8];
|
||||
static int8u s_diagonal_quadrant[8];
|
||||
static const int8u s_orthogonal_quadrant[8];
|
||||
static const int8u s_diagonal_quadrant[8];
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ namespace agg
|
|||
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------point_in_triangle
|
||||
AGG_INLINE bool point_in_triangle(double x1, double y1,
|
||||
double x2, double y2,
|
||||
|
@ -54,7 +53,6 @@ namespace agg
|
|||
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------calc_distance
|
||||
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
|
@ -63,6 +61,13 @@ namespace agg
|
|||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------calc_sq_distance
|
||||
AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double dx = x2-x1;
|
||||
double dy = y2-y1;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
//------------------------------------------------calc_line_point_distance
|
||||
AGG_INLINE double calc_line_point_distance(double x1, double y1,
|
||||
|
@ -79,6 +84,53 @@ namespace agg
|
|||
return ((x - x2) * dy - (y - y2) * dx) / d;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------calc_line_point_u
|
||||
AGG_INLINE double calc_segment_point_u(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y)
|
||||
{
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
|
||||
if(dx == 0 && dy == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
double pdx = x - x1;
|
||||
double pdy = y - y1;
|
||||
|
||||
return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
//---------------------------------------------calc_line_point_sq_distance
|
||||
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y,
|
||||
double u)
|
||||
{
|
||||
if(u <= 0)
|
||||
{
|
||||
return calc_sq_distance(x, y, x1, y1);
|
||||
}
|
||||
else
|
||||
if(u >= 1)
|
||||
{
|
||||
return calc_sq_distance(x, y, x2, y2);
|
||||
}
|
||||
return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
|
||||
}
|
||||
|
||||
//---------------------------------------------calc_line_point_sq_distance
|
||||
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y)
|
||||
{
|
||||
return
|
||||
calc_segment_point_sq_distance(
|
||||
x1, y1, x2, y2, x, y,
|
||||
calc_segment_point_u(x1, y1, x2, y2, x, y));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------calc_intersection
|
||||
AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
|
||||
|
@ -94,7 +146,6 @@ namespace agg
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------intersection_exists
|
||||
AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
|
||||
double x3, double y3, double x4, double y4)
|
||||
|
@ -122,7 +173,6 @@ namespace agg
|
|||
//return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------calc_orthogonal
|
||||
AGG_INLINE void calc_orthogonal(double thickness,
|
||||
double x1, double y1,
|
||||
|
@ -133,10 +183,9 @@ namespace agg
|
|||
double dy = y2 - y1;
|
||||
double d = sqrt(dx*dx + dy*dy);
|
||||
*x = thickness * dy / d;
|
||||
*y = thickness * dx / d;
|
||||
*y = -thickness * dx / d;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------dilate_triangle
|
||||
AGG_INLINE void dilate_triangle(double x1, double y1,
|
||||
double x2, double y2,
|
||||
|
@ -161,12 +210,12 @@ namespace agg
|
|||
calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
|
||||
calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
|
||||
}
|
||||
*x++ = x1 + dx1; *y++ = y1 - dy1;
|
||||
*x++ = x2 + dx1; *y++ = y2 - dy1;
|
||||
*x++ = x2 + dx2; *y++ = y2 - dy2;
|
||||
*x++ = x3 + dx2; *y++ = y3 - dy2;
|
||||
*x++ = x3 + dx3; *y++ = y3 - dy3;
|
||||
*x++ = x1 + dx3; *y++ = y1 - dy3;
|
||||
*x++ = x1 + dx1; *y++ = y1 + dy1;
|
||||
*x++ = x2 + dx1; *y++ = y2 + dy1;
|
||||
*x++ = x2 + dx2; *y++ = y2 + dy2;
|
||||
*x++ = x3 + dx2; *y++ = y3 + dy2;
|
||||
*x++ = x3 + dx3; *y++ = y3 + dy3;
|
||||
*x++ = x1 + dx3; *y++ = y1 + dy3;
|
||||
}
|
||||
|
||||
//------------------------------------------------------calc_triangle_area
|
||||
|
@ -177,7 +226,6 @@ namespace agg
|
|||
return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------calc_polygon_area
|
||||
template<class Storage> double calc_polygon_area(const Storage& st)
|
||||
{
|
||||
|
@ -274,7 +322,7 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
//This is calculation sqrt itself.
|
||||
//This code calculates the sqrt.
|
||||
bit -= 9;
|
||||
if(bit > 0)
|
||||
{
|
||||
|
|
|
@ -53,75 +53,176 @@ namespace agg
|
|||
inner_round
|
||||
};
|
||||
|
||||
// Minimal angle to calculate round joins, less than 0.1 degree.
|
||||
const double stroke_theta = 0.001; //----stroke_theta
|
||||
|
||||
//--------------------------------------------------------stroke_calc_arc
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_arc(VertexConsumer& out_vertices,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double width,
|
||||
double approximation_scale)
|
||||
//------------------------------------------------------------math_stroke
|
||||
template<class VertexConsumer> class math_stroke
|
||||
{
|
||||
public:
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
double a1 = atan2(dy1, dx1);
|
||||
double a2 = atan2(dy2, dx2);
|
||||
math_stroke();
|
||||
|
||||
void line_cap(line_cap_e lc) { m_line_cap = lc; }
|
||||
void line_join(line_join_e lj) { m_line_join = lj; }
|
||||
void inner_join(inner_join_e ij) { m_inner_join = ij; }
|
||||
|
||||
line_cap_e line_cap() const { return m_line_cap; }
|
||||
line_join_e line_join() const { return m_line_join; }
|
||||
inner_join_e inner_join() const { return m_inner_join; }
|
||||
|
||||
void width(double w);
|
||||
void miter_limit(double ml) { m_miter_limit = ml; }
|
||||
void miter_limit_theta(double t);
|
||||
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
|
||||
void approximation_scale(double as) { m_approx_scale = as; }
|
||||
|
||||
double width() const { return m_width * 2.0; }
|
||||
double miter_limit() const { return m_miter_limit; }
|
||||
double inner_miter_limit() const { return m_inner_miter_limit; }
|
||||
double approximation_scale() const { return m_approx_scale; }
|
||||
|
||||
void calc_cap(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len);
|
||||
|
||||
void calc_join(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1,
|
||||
double len2);
|
||||
|
||||
private:
|
||||
AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y)
|
||||
{
|
||||
vc.add(coord_type(x, y));
|
||||
}
|
||||
|
||||
void calc_arc(VertexConsumer& vc,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2);
|
||||
|
||||
void calc_miter(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
line_join_e lj,
|
||||
double mlimit,
|
||||
double dbevel);
|
||||
|
||||
double m_width;
|
||||
double m_width_abs;
|
||||
double m_width_eps;
|
||||
int m_width_sign;
|
||||
double m_miter_limit;
|
||||
double m_inner_miter_limit;
|
||||
double m_approx_scale;
|
||||
line_cap_e m_line_cap;
|
||||
line_join_e m_line_join;
|
||||
inner_join_e m_inner_join;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> math_stroke<VC>::math_stroke() :
|
||||
m_width(0.5),
|
||||
m_width_abs(0.5),
|
||||
m_width_eps(0.5/1024.0),
|
||||
m_width_sign(1),
|
||||
m_miter_limit(4.0),
|
||||
m_inner_miter_limit(1.01),
|
||||
m_approx_scale(1.0),
|
||||
m_line_cap(butt_cap),
|
||||
m_line_join(miter_join),
|
||||
m_inner_join(inner_miter)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> void math_stroke<VC>::width(double w)
|
||||
{
|
||||
m_width = w * 0.5;
|
||||
if(m_width < 0)
|
||||
{
|
||||
m_width_abs = -m_width;
|
||||
m_width_sign = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_width_abs = m_width;
|
||||
m_width_sign = 1;
|
||||
}
|
||||
m_width_eps = m_width / 1024.0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> void math_stroke<VC>::miter_limit_theta(double t)
|
||||
{
|
||||
m_miter_limit = 1.0 / sin(t * 0.5) ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_arc(VC& vc,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign);
|
||||
double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign);
|
||||
double da = a1 - a2;
|
||||
int i, n;
|
||||
|
||||
bool ccw = da > 0.0 && da < pi;
|
||||
da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
|
||||
|
||||
if(width < 0) width = -width;
|
||||
da = acos(width / (width + 0.125 / approximation_scale)) * 2;
|
||||
|
||||
out_vertices.add(coord_type(x + dx1, y + dy1));
|
||||
if(!ccw)
|
||||
add_vertex(vc, x + dx1, y + dy1);
|
||||
if(m_width_sign > 0)
|
||||
{
|
||||
if(a1 > a2) a2 += 2 * pi;
|
||||
a2 -= da / 4;
|
||||
n = int((a2 - a1) / da);
|
||||
da = (a2 - a1) / (n + 1);
|
||||
a1 += da;
|
||||
while(a1 < a2)
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width));
|
||||
add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
|
||||
a1 += da;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(a1 < a2) a2 -= 2 * pi;
|
||||
a2 += da / 4;
|
||||
n = int((a1 - a2) / da);
|
||||
da = (a1 - a2) / (n + 1);
|
||||
a1 -= da;
|
||||
while(a1 > a2)
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width));
|
||||
add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
out_vertices.add(coord_type(x + dx2, y + dy2));
|
||||
add_vertex(vc, x + dx2, y + dy2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------stroke_calc_miter
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_miter(VertexConsumer& out_vertices,
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_miter(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double width,
|
||||
line_join_e line_join,
|
||||
double miter_limit,
|
||||
double approximation_scale)
|
||||
line_join_e lj,
|
||||
double mlimit,
|
||||
double dbevel)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
double xi = v1.x;
|
||||
double yi = v1.y;
|
||||
double di = 1;
|
||||
double lim = m_width_abs * mlimit;
|
||||
bool miter_limit_exceeded = true; // Assume the worst
|
||||
bool intersection_failed = true; // Assume the worst
|
||||
|
||||
if(calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
|
@ -131,15 +232,15 @@ namespace agg
|
|||
{
|
||||
// Calculation of the intersection succeeded
|
||||
//---------------------
|
||||
double d1 = calc_distance(v1.x, v1.y, xi, yi);
|
||||
double lim = width * miter_limit;
|
||||
if(d1 <= lim)
|
||||
di = calc_distance(v1.x, v1.y, xi, yi);
|
||||
if(di <= lim)
|
||||
{
|
||||
// Inside the miter limit
|
||||
//---------------------
|
||||
out_vertices.add(coord_type(xi, yi));
|
||||
add_vertex(vc, xi, yi);
|
||||
miter_limit_exceeded = false;
|
||||
}
|
||||
intersection_failed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -153,13 +254,13 @@ namespace agg
|
|||
//----------------
|
||||
double x2 = v1.x + dx1;
|
||||
double y2 = v1.y - dy1;
|
||||
if(((x2 - v0.x)*dy1 - (v0.y - y2)*dx1 < 0.0) !=
|
||||
((x2 - v2.x)*dy1 - (v2.y - y2)*dx1 < 0.0))
|
||||
if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
|
||||
(cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
|
||||
{
|
||||
// This case means that the next segment continues
|
||||
// the previous one (straight line)
|
||||
//-----------------
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
miter_limit_exceeded = false;
|
||||
}
|
||||
}
|
||||
|
@ -168,171 +269,177 @@ namespace agg
|
|||
{
|
||||
// Miter limit exceeded
|
||||
//------------------------
|
||||
switch(line_join)
|
||||
switch(lj)
|
||||
{
|
||||
case miter_join_revert:
|
||||
// For the compatibility with SVG, PDF, etc,
|
||||
// we use a simple bevel join instead of
|
||||
// "smart" bevel
|
||||
//-------------------
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
|
||||
case miter_join_round:
|
||||
stroke_calc_arc(out_vertices,
|
||||
v1.x, v1.y, dx1, -dy1, dx2, -dy2,
|
||||
width, approximation_scale);
|
||||
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
|
||||
break;
|
||||
|
||||
default:
|
||||
// If no miter-revert, calculate new dx1, dy1, dx2, dy2
|
||||
//----------------
|
||||
out_vertices.add(coord_type(v1.x + dx1 + dy1 * miter_limit,
|
||||
v1.y - dy1 + dx1 * miter_limit));
|
||||
out_vertices.add(coord_type(v1.x + dx2 - dy2 * miter_limit,
|
||||
v1.y - dy2 - dx2 * miter_limit));
|
||||
if(intersection_failed)
|
||||
{
|
||||
mlimit *= m_width_sign;
|
||||
add_vertex(vc, v1.x + dx1 + dy1 * mlimit,
|
||||
v1.y - dy1 + dx1 * mlimit);
|
||||
add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
|
||||
v1.y - dy2 - dx2 * mlimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
double x1 = v1.x + dx1;
|
||||
double y1 = v1.y - dy1;
|
||||
double x2 = v1.x + dx2;
|
||||
double y2 = v1.y - dy2;
|
||||
di = (lim - dbevel) / (di - dbevel);
|
||||
add_vertex(vc, x1 + (xi - x1) * di,
|
||||
y1 + (yi - y1) * di);
|
||||
add_vertex(vc, x2 + (xi - x2) * di,
|
||||
y2 + (yi - y2) * di);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------stroke_calc_cap
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_cap(VertexConsumer& out_vertices,
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_cap(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len,
|
||||
line_cap_e line_cap,
|
||||
double width,
|
||||
double approximation_scale)
|
||||
double len)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
out_vertices.remove_all();
|
||||
vc.remove_all();
|
||||
|
||||
double dx1 = (v1.y - v0.y) / len;
|
||||
double dy1 = (v1.x - v0.x) / len;
|
||||
double dx2 = 0;
|
||||
double dy2 = 0;
|
||||
|
||||
dx1 *= width;
|
||||
dy1 *= width;
|
||||
dx1 *= m_width;
|
||||
dy1 *= m_width;
|
||||
|
||||
if(line_cap != round_cap)
|
||||
if(m_line_cap != round_cap)
|
||||
{
|
||||
if(line_cap == square_cap)
|
||||
if(m_line_cap == square_cap)
|
||||
{
|
||||
dx2 = dy1;
|
||||
dy2 = dx1;
|
||||
dx2 = dy1 * m_width_sign;
|
||||
dy2 = dx1 * m_width_sign;
|
||||
}
|
||||
out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2));
|
||||
out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2));
|
||||
add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
|
||||
add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
|
||||
}
|
||||
else
|
||||
{
|
||||
double a1 = atan2(dy1, -dx1);
|
||||
double a2 = a1 + pi;
|
||||
double da = acos(width / (width + 0.125 / approximation_scale)) * 2;
|
||||
out_vertices.add(coord_type(v0.x - dx1, v0.y + dy1));
|
||||
a1 += da;
|
||||
a2 -= da/4;
|
||||
while(a1 < a2)
|
||||
double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
|
||||
double a1;
|
||||
int i;
|
||||
int n = int(pi / da);
|
||||
|
||||
da = pi / (n + 1);
|
||||
add_vertex(vc, v0.x - dx1, v0.y + dy1);
|
||||
if(m_width_sign > 0)
|
||||
{
|
||||
out_vertices.add(coord_type(v0.x + cos(a1) * width,
|
||||
v0.y + sin(a1) * width));
|
||||
a1 = atan2(dy1, -dx1);
|
||||
a1 += da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, v0.x + cos(a1) * m_width,
|
||||
v0.y + sin(a1) * m_width);
|
||||
a1 += da;
|
||||
}
|
||||
out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1));
|
||||
}
|
||||
else
|
||||
{
|
||||
a1 = atan2(-dy1, dx1);
|
||||
a1 -= da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, v0.x + cos(a1) * m_width,
|
||||
v0.y + sin(a1) * m_width);
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
add_vertex(vc, v0.x + dx1, v0.y - dy1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------stroke_calc_join
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_join(VertexConsumer& out_vertices,
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_join(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1,
|
||||
double len2,
|
||||
double width,
|
||||
line_join_e line_join,
|
||||
inner_join_e inner_join,
|
||||
double miter_limit,
|
||||
double inner_miter_limit,
|
||||
double approximation_scale)
|
||||
double len2)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
double dx1 = m_width * (v1.y - v0.y) / len1;
|
||||
double dy1 = m_width * (v1.x - v0.x) / len1;
|
||||
double dx2 = m_width * (v2.y - v1.y) / len2;
|
||||
double dy2 = m_width * (v2.x - v1.x) / len2;
|
||||
|
||||
double dx1, dy1, dx2, dy2;
|
||||
double d;
|
||||
vc.remove_all();
|
||||
|
||||
dx1 = width * (v1.y - v0.y) / len1;
|
||||
dy1 = width * (v1.x - v0.x) / len1;
|
||||
|
||||
dx2 = width * (v2.y - v1.y) / len2;
|
||||
dy2 = width * (v2.x - v1.x) / len2;
|
||||
|
||||
out_vertices.remove_all();
|
||||
|
||||
if(cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0)
|
||||
double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
|
||||
if(cp != 0 && (cp > 0) == (m_width > 0))
|
||||
{
|
||||
// Inner join
|
||||
//---------------
|
||||
switch(inner_join)
|
||||
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
|
||||
if(limit < m_inner_miter_limit)
|
||||
{
|
||||
limit = m_inner_miter_limit;
|
||||
}
|
||||
|
||||
switch(m_inner_join)
|
||||
{
|
||||
default: // inner_bevel
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
|
||||
case inner_miter:
|
||||
stroke_calc_miter(out_vertices,
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
miter_join_revert,
|
||||
inner_miter_limit,
|
||||
1.0);
|
||||
limit, 0);
|
||||
break;
|
||||
|
||||
case inner_jag:
|
||||
case inner_round:
|
||||
cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
|
||||
if(cp < len1 * len1 && cp < len2 * len2)
|
||||
{
|
||||
d = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
|
||||
if(d < len1 * len1 && d < len2 * len2)
|
||||
{
|
||||
stroke_calc_miter(out_vertices,
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
miter_join_revert,
|
||||
inner_miter_limit,
|
||||
1.0);
|
||||
limit, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(inner_join == inner_jag)
|
||||
if(m_inner_join == inner_jag)
|
||||
{
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x, v1.y ));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x, v1.y ));
|
||||
stroke_calc_arc(out_vertices,
|
||||
v1.x, v1.y, dx2, -dy2, dx1, -dy1,
|
||||
width, approximation_scale);
|
||||
out_vertices.add(coord_type(v1.x, v1.y ));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
}
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -342,10 +449,18 @@ namespace agg
|
|||
{
|
||||
// Outer join
|
||||
//---------------
|
||||
if(line_join == round_join || line_join == bevel_join)
|
||||
|
||||
// Calculate the distance between v1 and
|
||||
// the central point of the bevel line segment
|
||||
//---------------
|
||||
double dx = (dx1 + dx2) / 2;
|
||||
double dy = (dy1 + dy2) / 2;
|
||||
double dbevel = sqrt(dx * dx + dy * dy);
|
||||
|
||||
if(m_line_join == round_join || m_line_join == bevel_join)
|
||||
{
|
||||
// This is an optimization that reduces the number of points
|
||||
// in cases of almost collonear segments. If there's no
|
||||
// in cases of almost collinear segments. If there's no
|
||||
// visible difference between bevel and miter joins we'd rather
|
||||
// use miter join because it adds only one point instead of two.
|
||||
//
|
||||
|
@ -354,44 +469,50 @@ namespace agg
|
|||
// At outer joins this distance always less than stroke width,
|
||||
// because it's actually the height of an isosceles triangle of
|
||||
// v1 and its two bevel points. If the difference between this
|
||||
// width and this value is small (no visible bevel) we can switch
|
||||
// to the miter join.
|
||||
// width and this value is small (no visible bevel) we can
|
||||
// add just one point.
|
||||
//
|
||||
// The constant in the expression makes the result approximately
|
||||
// the same as in round joins and caps. One can safely comment
|
||||
// out this "if".
|
||||
// the same as in round joins and caps. You can safely comment
|
||||
// out this entire "if".
|
||||
//-------------------
|
||||
double dx = (dx1 + dx2) / 2;
|
||||
double dy = (dy1 + dy2) / 2;
|
||||
d = width - sqrt(dx * dx + dy * dy);
|
||||
if(d < 0.0625 / approximation_scale)
|
||||
if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
|
||||
{
|
||||
line_join = miter_join;
|
||||
if(calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&dx, &dy))
|
||||
{
|
||||
add_vertex(vc, dx, dy);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch(line_join)
|
||||
switch(m_line_join)
|
||||
{
|
||||
case miter_join:
|
||||
case miter_join_revert:
|
||||
case miter_join_round:
|
||||
stroke_calc_miter(out_vertices,
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
line_join,
|
||||
miter_limit,
|
||||
approximation_scale);
|
||||
m_line_join,
|
||||
m_miter_limit,
|
||||
dbevel);
|
||||
break;
|
||||
|
||||
case round_join:
|
||||
stroke_calc_arc(out_vertices,
|
||||
v1.x, v1.y, dx1, -dy1, dx2, -dy2,
|
||||
width, approximation_scale);
|
||||
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
|
||||
break;
|
||||
|
||||
default: // Bevel join
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,10 +90,13 @@ namespace agg
|
|||
T** coord_blk = m_coord_blocks + m_total_blocks - 1;
|
||||
while(m_total_blocks--)
|
||||
{
|
||||
delete [] *coord_blk;
|
||||
pod_allocator<T>::deallocate(
|
||||
*coord_blk,
|
||||
block_size * 2 +
|
||||
block_size / (sizeof(T) / sizeof(unsigned char)));
|
||||
--coord_blk;
|
||||
}
|
||||
delete [] m_coord_blocks;
|
||||
pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2);
|
||||
m_total_blocks = 0;
|
||||
m_max_blocks = 0;
|
||||
m_coord_blocks = 0;
|
||||
|
@ -298,7 +301,7 @@ namespace agg
|
|||
if(nb >= m_max_blocks)
|
||||
{
|
||||
T** new_coords =
|
||||
new T* [(m_max_blocks + block_pool) * 2];
|
||||
pod_allocator<T*>::allocate((m_max_blocks + block_pool) * 2);
|
||||
|
||||
unsigned char** new_cmds =
|
||||
(unsigned char**)(new_coords + m_max_blocks + block_pool);
|
||||
|
@ -313,15 +316,15 @@ namespace agg
|
|||
m_cmd_blocks,
|
||||
m_max_blocks * sizeof(unsigned char*));
|
||||
|
||||
delete [] m_coord_blocks;
|
||||
pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2);
|
||||
}
|
||||
m_coord_blocks = new_coords;
|
||||
m_cmd_blocks = new_cmds;
|
||||
m_max_blocks += block_pool;
|
||||
}
|
||||
m_coord_blocks[nb] =
|
||||
new T [block_size * 2 +
|
||||
block_size / (sizeof(T) / sizeof(unsigned char))];
|
||||
pod_allocator<T>::allocate(block_size * 2 +
|
||||
block_size / (sizeof(T) / sizeof(unsigned char)));
|
||||
|
||||
m_cmd_blocks[nb] =
|
||||
(unsigned char*)(m_coord_blocks[nb] + block_size * 2);
|
||||
|
@ -766,7 +769,7 @@ namespace agg
|
|||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
m_vertices.add_vertex(x, y, is_move_to(cmd) ?
|
||||
path_cmd_line_to :
|
||||
unsigned(path_cmd_line_to) :
|
||||
cmd);
|
||||
}
|
||||
}
|
||||
|
@ -792,6 +795,46 @@ namespace agg
|
|||
join_path(poly);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void translate(double dx, double dy, unsigned path_id=0);
|
||||
void translate_all_paths(double dx, double dy);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Trans>
|
||||
void transform(const Trans& trans, unsigned path_id=0)
|
||||
{
|
||||
unsigned num_ver = m_vertices.total_vertices();
|
||||
for(; path_id < num_ver; path_id++)
|
||||
{
|
||||
double x, y;
|
||||
unsigned cmd = m_vertices.vertex(path_id, &x, &y);
|
||||
if(is_stop(cmd)) break;
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
trans.transform(&x, &y);
|
||||
m_vertices.modify_vertex(path_id, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Trans>
|
||||
void transform_all_paths(const Trans& trans)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned num_ver = m_vertices.total_vertices();
|
||||
for(idx = 0; idx < num_ver; idx++)
|
||||
{
|
||||
double x, y;
|
||||
if(is_vertex(m_vertices.vertex(idx, &x, &y)))
|
||||
{
|
||||
trans.transform(&x, &y);
|
||||
m_vertices.modify_vertex(idx, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
unsigned perceive_polygon_orientation(unsigned start, unsigned end);
|
||||
|
@ -1167,7 +1210,6 @@ namespace agg
|
|||
return m_vertices.vertex(m_iterator++, x, y);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
unsigned path_base<VC>::perceive_polygon_orientation(unsigned start,
|
||||
|
@ -1188,7 +1230,6 @@ namespace agg
|
|||
return (area < 0.0) ? path_flags_cw : path_flags_ccw;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void path_base<VC>::invert_polygon(unsigned start, unsigned end)
|
||||
|
@ -1232,11 +1273,8 @@ namespace agg
|
|||
while(end < m_vertices.total_vertices() &&
|
||||
!is_next_poly(m_vertices.command(end))) ++end;
|
||||
|
||||
if(end - start > 2)
|
||||
{
|
||||
invert_polygon(start, end);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
|
@ -1276,7 +1314,6 @@ namespace agg
|
|||
return end;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
unsigned path_base<VC>::arrange_orientations(unsigned start,
|
||||
|
@ -1297,7 +1334,6 @@ namespace agg
|
|||
return start;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void path_base<VC>::arrange_orientations_all_paths(path_flags_e orientation)
|
||||
|
@ -1312,7 +1348,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void path_base<VC>::flip_x(double x1, double x2)
|
||||
|
@ -1329,7 +1364,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void path_base<VC>::flip_y(double y1, double y2)
|
||||
|
@ -1346,9 +1380,42 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void path_base<VC>::translate(double dx, double dy, unsigned path_id)
|
||||
{
|
||||
unsigned num_ver = m_vertices.total_vertices();
|
||||
for(; path_id < num_ver; path_id++)
|
||||
{
|
||||
double x, y;
|
||||
unsigned cmd = m_vertices.vertex(path_id, &x, &y);
|
||||
if(is_stop(cmd)) break;
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
x += dx;
|
||||
y += dy;
|
||||
m_vertices.modify_vertex(path_id, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void path_base<VC>::translate_all_paths(double dx, double dy)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned num_ver = m_vertices.total_vertices();
|
||||
for(idx = 0; idx < num_ver; idx++)
|
||||
{
|
||||
double x, y;
|
||||
if(is_vertex(m_vertices.vertex(idx, &x, &y)))
|
||||
{
|
||||
x += dx;
|
||||
y += dy;
|
||||
m_vertices.modify_vertex(idx, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------vertex_stl_storage
|
||||
template<class Container> class vertex_stl_storage
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_array.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
|
||||
|
@ -38,38 +39,40 @@ namespace agg
|
|||
|
||||
void realloc_span(unsigned len)
|
||||
{
|
||||
if(len > m_max_len)
|
||||
if(len > m_span.size())
|
||||
{
|
||||
delete [] m_span;
|
||||
m_span = new cover_type[m_max_len = len + span_extra_tail];
|
||||
m_span.resize(len + span_extra_tail);
|
||||
}
|
||||
}
|
||||
|
||||
void init_span(unsigned len)
|
||||
{
|
||||
realloc_span(len);
|
||||
|
||||
// ATTN! May work incorrectly if cover_type is more that one byte
|
||||
memset(m_span, amask_type::cover_full, len * sizeof(cover_type));
|
||||
memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
|
||||
}
|
||||
|
||||
void init_span(unsigned len, const cover_type* covers)
|
||||
{
|
||||
realloc_span(len);
|
||||
memcpy(m_span, covers, len * sizeof(cover_type));
|
||||
memcpy(&m_span[0], covers, len * sizeof(cover_type));
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
~pixfmt_amask_adaptor() { delete [] m_span; }
|
||||
|
||||
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
|
||||
m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0)
|
||||
m_pixf(&pixf), m_mask(&mask), m_span()
|
||||
{}
|
||||
|
||||
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
|
||||
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class PixFmt2>
|
||||
bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
return m_pixf->attach(pixf, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_pixf->width(); }
|
||||
unsigned height() const { return m_pixf->height(); }
|
||||
|
@ -98,8 +101,8 @@ namespace agg
|
|||
const color_type& c)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||
m_mask->fill_hspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -109,8 +112,8 @@ namespace agg
|
|||
cover_type cover)
|
||||
{
|
||||
init_span(len);
|
||||
m_mask->combine_hspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||
m_mask->combine_hspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -119,8 +122,8 @@ namespace agg
|
|||
const color_type& c)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_vspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||
m_mask->fill_vspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -130,8 +133,8 @@ namespace agg
|
|||
cover_type cover)
|
||||
{
|
||||
init_span(len);
|
||||
m_mask->combine_vspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||
m_mask->combine_vspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -151,8 +154,8 @@ namespace agg
|
|||
const cover_type* covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_hspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||
m_mask->combine_hspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -163,8 +166,8 @@ namespace agg
|
|||
const cover_type* covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_vspan(x, y, m_span, len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||
m_mask->combine_vspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -172,10 +175,17 @@ namespace agg
|
|||
void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, m_span, len);
|
||||
m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover_full);
|
||||
m_mask->fill_hspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_vspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
|
@ -187,14 +197,14 @@ namespace agg
|
|||
if(covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_hspan(x, y, m_span, len);
|
||||
m_mask->combine_hspan(x, y, &m_span[0], len);
|
||||
}
|
||||
else
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, m_span, len);
|
||||
m_mask->fill_hspan(x, y, &m_span[0], len);
|
||||
}
|
||||
m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover);
|
||||
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
|
||||
}
|
||||
|
||||
|
||||
|
@ -208,22 +218,20 @@ namespace agg
|
|||
if(covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_vspan(x, y, m_span, len);
|
||||
m_mask->combine_vspan(x, y, &m_span[0], len);
|
||||
}
|
||||
else
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_vspan(x, y, m_span, len);
|
||||
m_mask->fill_vspan(x, y, &m_span[0], len);
|
||||
}
|
||||
m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover);
|
||||
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
|
||||
}
|
||||
|
||||
private:
|
||||
pixfmt_type* m_pixf;
|
||||
const amask_type* m_mask;
|
||||
|
||||
cover_type* m_span;
|
||||
unsigned m_max_len;
|
||||
pod_array<cover_type> m_span;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -128,7 +128,9 @@ namespace agg
|
|||
base_shift = color_type::base_shift,
|
||||
base_scale = color_type::base_scale,
|
||||
base_mask = color_type::base_mask,
|
||||
pix_width = sizeof(value_type)
|
||||
pix_width = sizeof(value_type),
|
||||
pix_step = Step,
|
||||
pix_offset = Offset
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -171,30 +173,46 @@ namespace agg
|
|||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_alpha_blend_gray(rbuf_type& rb) :
|
||||
explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
|
||||
m_rbuf(&rb)
|
||||
{}
|
||||
void attach(rbuf_type& rb) { m_rbuf = &rb; }
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
template<class PixFmt>
|
||||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i r(x1, y1, x2, y2);
|
||||
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
(r.x2 - r.x1) + 1,
|
||||
(r.y2 - r.y1) + 1,
|
||||
stride);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y);
|
||||
}
|
||||
int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
return m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data row(int x, int y) const
|
||||
int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row(y);
|
||||
return m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -206,7 +224,7 @@ namespace agg
|
|||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type pixel(int x, int y) const
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset;
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
return color_type(*p);
|
||||
}
|
||||
|
||||
|
@ -399,13 +417,29 @@ namespace agg
|
|||
|
||||
do
|
||||
{
|
||||
*p++ = colors->v;
|
||||
*p = colors->v;
|
||||
p += Step;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
*p = colors->v;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
|
@ -565,6 +599,58 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst,
|
||||
color,
|
||||
(*psrc * cover + base_mask) >> base_shift);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst, color_lut[*psrc], cover);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
};
|
||||
|
|
|
@ -173,8 +173,8 @@ namespace agg
|
|||
{
|
||||
public:
|
||||
typedef RenBuf rbuf_type;
|
||||
typedef typename rbuf_type::row_data row_data;
|
||||
typedef Blender blender_type;
|
||||
typedef typename rbuf_type::row_data row_data;
|
||||
typedef typename blender_type::color_type color_type;
|
||||
typedef typename blender_type::order_type order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
|
@ -231,9 +231,27 @@ namespace agg
|
|||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_alpha_blend_rgb(rbuf_type& rb) :
|
||||
explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
|
||||
m_rbuf(&rb)
|
||||
{}
|
||||
void attach(rbuf_type& rb) { m_rbuf = &rb; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class PixFmt>
|
||||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i r(x1, y1, x2, y2);
|
||||
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
(r.x2 - r.x1) + 1,
|
||||
(r.y2 - r.y1) + 1,
|
||||
stride);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
Blender& blender() { return m_blender; }
|
||||
|
@ -241,23 +259,22 @@ namespace agg
|
|||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y);
|
||||
}
|
||||
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
AGG_INLINE int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data row(int x, int y) const
|
||||
AGG_INLINE const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row(y);
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -484,6 +501,24 @@ namespace agg
|
|||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
p[order_type::R] = colors->r;
|
||||
p[order_type::G] = colors->g;
|
||||
p[order_type::B] = colors->b;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
|
@ -687,6 +722,74 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst,
|
||||
color,
|
||||
(*psrc * cover + base_mask) >> base_shift);
|
||||
++psrc;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
|
||||
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
const color_type& color = color_lut[*psrc];
|
||||
m_blender.blend_pix(pdst,
|
||||
color.r, color.g, color.b, color.a);
|
||||
++psrc;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst, color_lut[*psrc], cover);
|
||||
++psrc;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
Blender m_blender;
|
||||
|
|
|
@ -828,29 +828,47 @@ namespace agg
|
|||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {}
|
||||
explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {}
|
||||
void attach(rbuf_type& rb) { m_rbuf = &rb; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class PixFmt>
|
||||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i r(x1, y1, x2, y2);
|
||||
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
(r.x2 - r.x1) + 1,
|
||||
(r.y2 - r.y1) + 1,
|
||||
stride);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Blender& blender() { return m_blender; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y);
|
||||
}
|
||||
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
AGG_INLINE int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data row(int x, int y) const
|
||||
AGG_INLINE const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row(y);
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -1012,6 +1030,20 @@ namespace agg
|
|||
while(--len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
do
|
||||
{
|
||||
pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x;
|
||||
*p = m_blender.make_pix(colors->r, colors->g, colors->b);
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
|
@ -1102,6 +1134,65 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
pixel_type* pdst =
|
||||
(pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
|
||||
do
|
||||
{
|
||||
m_blender.blend_pix(pdst,
|
||||
color.r, color.g, color.b, color.a,
|
||||
cover);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
pixel_type* pdst =
|
||||
(pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
|
||||
do
|
||||
{
|
||||
const color_type& color = color_lut[*psrc];
|
||||
m_blender.blend_pix(pdst,
|
||||
color.r, color.g, color.b, color.a,
|
||||
cover);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
Blender m_blender;
|
||||
|
|
|
@ -614,6 +614,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift);
|
||||
|
@ -621,6 +623,7 @@ namespace agg
|
|||
p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift);
|
||||
p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=========================================================comp_op_rgba_plus
|
||||
|
@ -649,14 +652,17 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type dr = p[Order::R] + sr;
|
||||
calc_type dg = p[Order::G] + sg;
|
||||
calc_type db = p[Order::B] + sb;
|
||||
calc_type da = p[Order::A] + sa;
|
||||
p[Order::R] = (dr > base_mask) ? base_mask : dr;
|
||||
p[Order::G] = (dg > base_mask) ? base_mask : dg;
|
||||
p[Order::B] = (db > base_mask) ? base_mask : db;
|
||||
p[Order::A] = (da > base_mask) ? base_mask : da;
|
||||
p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr;
|
||||
p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg;
|
||||
p[Order::B] = (db > base_mask) ? (value_type)base_mask : db;
|
||||
p[Order::A] = (da > base_mask) ? (value_type)base_mask : da;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -686,13 +692,17 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type dr = p[Order::R] - sr;
|
||||
calc_type dg = p[Order::G] - sg;
|
||||
calc_type db = p[Order::B] - sb;
|
||||
p[Order::R] = (dr > base_mask) ? 0 : dr;
|
||||
p[Order::G] = (dg > base_mask) ? 0 : dg;
|
||||
p[Order::B] = (db > base_mask) ? 0 : db;
|
||||
p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift));
|
||||
p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
|
||||
//p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -722,6 +732,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
calc_type dr = p[Order::R];
|
||||
|
@ -732,6 +744,7 @@ namespace agg
|
|||
p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift);
|
||||
p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_screen
|
||||
|
@ -760,6 +773,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type dr = p[Order::R];
|
||||
calc_type dg = p[Order::G];
|
||||
calc_type db = p[Order::B];
|
||||
|
@ -769,6 +784,7 @@ namespace agg
|
|||
p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift));
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_overlay
|
||||
|
@ -801,6 +817,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type dr = p[Order::R];
|
||||
|
@ -811,18 +829,19 @@ namespace agg
|
|||
|
||||
p[Order::R] = (value_type)(((2*dr < da) ?
|
||||
2*sr*dr + sr*d1a + dr*s1a :
|
||||
sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a) >> base_shift);
|
||||
sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::G] = (value_type)(((2*dg < da) ?
|
||||
2*sg*dg + sg*d1a + dg*s1a :
|
||||
sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a) >> base_shift);
|
||||
sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::B] = (value_type)(((2*db < da) ?
|
||||
2*sb*db + sb*d1a + db*s1a :
|
||||
sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a) >> base_shift);
|
||||
sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -855,6 +874,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type dr = p[Order::R];
|
||||
|
@ -862,11 +883,12 @@ namespace agg
|
|||
calc_type db = p[Order::B];
|
||||
calc_type da = p[Order::A];
|
||||
|
||||
p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a) >> base_shift);
|
||||
p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a) >> base_shift);
|
||||
p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a) >> base_shift);
|
||||
p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
|
||||
p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
|
||||
p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_lighten
|
||||
|
@ -895,6 +917,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type dr = p[Order::R];
|
||||
|
@ -902,11 +926,12 @@ namespace agg
|
|||
calc_type db = p[Order::B];
|
||||
calc_type da = p[Order::A];
|
||||
|
||||
p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a) >> base_shift);
|
||||
p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a) >> base_shift);
|
||||
p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a) >> base_shift);
|
||||
p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
|
||||
p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
|
||||
p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_color_dodge
|
||||
|
@ -940,6 +965,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type dr = p[Order::R];
|
||||
|
@ -955,19 +982,20 @@ namespace agg
|
|||
long_type sada = sa * da;
|
||||
|
||||
p[Order::R] = (value_type)((srda + drsa >= sada) ?
|
||||
(sada + sr * d1a + dr * s1a) >> base_shift :
|
||||
drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a) >> base_shift));
|
||||
(sada + sr * d1a + dr * s1a + base_mask) >> base_shift :
|
||||
drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift));
|
||||
|
||||
p[Order::G] = (value_type)((sgda + dgsa >= sada) ?
|
||||
(sada + sg * d1a + dg * s1a) >> base_shift :
|
||||
dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a) >> base_shift));
|
||||
(sada + sg * d1a + dg * s1a + base_mask) >> base_shift :
|
||||
dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift));
|
||||
|
||||
p[Order::B] = (value_type)((sbda + dbsa >= sada) ?
|
||||
(sada + sb * d1a + db * s1a) >> base_shift :
|
||||
dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a) >> base_shift));
|
||||
(sada + sb * d1a + db * s1a + base_mask) >> base_shift :
|
||||
dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift));
|
||||
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_color_burn
|
||||
|
@ -1001,6 +1029,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type dr = p[Order::R];
|
||||
|
@ -1017,18 +1047,19 @@ namespace agg
|
|||
|
||||
p[Order::R] = (value_type)(((srda + drsa <= sada) ?
|
||||
sr * d1a + dr * s1a :
|
||||
sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a) >> base_shift);
|
||||
sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::G] = (value_type)(((sgda + dgsa <= sada) ?
|
||||
sg * d1a + dg * s1a :
|
||||
sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a) >> base_shift);
|
||||
sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::B] = (value_type)(((sbda + dbsa <= sada) ?
|
||||
sb * d1a + db * s1a :
|
||||
sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a) >> base_shift);
|
||||
sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_hard_light
|
||||
|
@ -1062,6 +1093,8 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type dr = p[Order::R];
|
||||
|
@ -1072,18 +1105,19 @@ namespace agg
|
|||
|
||||
p[Order::R] = (value_type)(((2*sr < sa) ?
|
||||
2*sr*dr + sr*d1a + dr*s1a :
|
||||
sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a) >> base_shift);
|
||||
sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::G] = (value_type)(((2*sg < sa) ?
|
||||
2*sg*dg + sg*d1a + dg*s1a :
|
||||
sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a) >> base_shift);
|
||||
sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::B] = (value_type)(((2*sb < sa) ?
|
||||
2*sb*db + sb*d1a + db*s1a :
|
||||
sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a) >> base_shift);
|
||||
sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
|
||||
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_soft_light
|
||||
|
@ -1117,6 +1151,8 @@ namespace agg
|
|||
double sg = double(g * cover) / (base_mask * 255);
|
||||
double sb = double(b * cover) / (base_mask * 255);
|
||||
double sa = double(a * cover) / (base_mask * 255);
|
||||
if(sa > 0)
|
||||
{
|
||||
double dr = double(p[Order::R]) / base_mask;
|
||||
double dg = double(p[Order::G]) / base_mask;
|
||||
double db = double(p[Order::B]) / base_mask;
|
||||
|
@ -1143,6 +1179,7 @@ namespace agg
|
|||
p[Order::B] = (value_type)uround(db * base_mask);
|
||||
p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_difference
|
||||
|
@ -1156,6 +1193,7 @@ namespace agg
|
|||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_scale = color_type::base_scale,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
|
@ -1172,15 +1210,18 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type dr = p[Order::R];
|
||||
calc_type dg = p[Order::G];
|
||||
calc_type db = p[Order::B];
|
||||
calc_type da = p[Order::A];
|
||||
p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa)) >> base_shift));
|
||||
p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa)) >> base_shift));
|
||||
p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa)) >> base_shift));
|
||||
p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift));
|
||||
p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift));
|
||||
p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift));
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_exclusion
|
||||
|
@ -1210,17 +1251,20 @@ namespace agg
|
|||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type d1a = base_mask - p[Order::A];
|
||||
calc_type s1a = base_mask - sa;
|
||||
calc_type dr = p[Order::R];
|
||||
calc_type dg = p[Order::G];
|
||||
calc_type db = p[Order::B];
|
||||
calc_type da = p[Order::A];
|
||||
p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a) >> base_shift);
|
||||
p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a) >> base_shift);
|
||||
p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a) >> base_shift);
|
||||
p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift);
|
||||
p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift);
|
||||
p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift);
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_contrast
|
||||
|
@ -1270,11 +1314,83 @@ namespace agg
|
|||
}
|
||||
};
|
||||
|
||||
//=====================================================comp_op_rgba_invert
|
||||
template<class ColorT, class Order> struct comp_op_rgba_invert
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
// Dca' = (Da - Dca) * Sa + Dca.(1 - Sa)
|
||||
// Da' = Sa + Da - Sa.Da
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned sr, unsigned sg, unsigned sb,
|
||||
unsigned sa, unsigned cover)
|
||||
{
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
if(sa)
|
||||
{
|
||||
calc_type da = p[Order::A];
|
||||
calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift;
|
||||
calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift;
|
||||
calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift;
|
||||
calc_type s1a = base_mask - sa;
|
||||
p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
|
||||
p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
|
||||
p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=================================================comp_op_rgba_invert_rgb
|
||||
template<class ColorT, class Order> struct comp_op_rgba_invert_rgb
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_mask = color_type::base_mask
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Dca' = (Da - Dca) * Sca + Dca.(1 - Sa)
|
||||
// Da' = Sa + Da - Sa.Da
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned sr, unsigned sg, unsigned sb,
|
||||
unsigned sa, unsigned cover)
|
||||
{
|
||||
if(cover < 255)
|
||||
{
|
||||
sr = (sr * cover + 255) >> 8;
|
||||
sg = (sg * cover + 255) >> 8;
|
||||
sb = (sb * cover + 255) >> 8;
|
||||
sa = (sa * cover + 255) >> 8;
|
||||
}
|
||||
if(sa)
|
||||
{
|
||||
calc_type da = p[Order::A];
|
||||
calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift;
|
||||
calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift;
|
||||
calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift;
|
||||
calc_type s1a = base_mask - sa;
|
||||
p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
|
||||
p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
|
||||
p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
|
||||
p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -1324,6 +1440,8 @@ namespace agg
|
|||
comp_op_rgba_difference <ColorT,Order>::blend_pix,
|
||||
comp_op_rgba_exclusion <ColorT,Order>::blend_pix,
|
||||
comp_op_rgba_contrast <ColorT,Order>::blend_pix,
|
||||
comp_op_rgba_invert <ColorT,Order>::blend_pix,
|
||||
comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix,
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -1357,6 +1475,8 @@ namespace agg
|
|||
comp_op_difference, //----comp_op_difference
|
||||
comp_op_exclusion, //----comp_op_exclusion
|
||||
comp_op_contrast, //----comp_op_contrast
|
||||
comp_op_invert, //----comp_op_invert
|
||||
comp_op_invert_rgb, //----comp_op_invert_rgb
|
||||
|
||||
end_of_comp_op_e
|
||||
};
|
||||
|
@ -1652,31 +1772,48 @@ namespace agg
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_alpha_blend_rgba() : m_rbuf(0) {}
|
||||
pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
|
||||
explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
|
||||
void attach(rbuf_type& rb) { m_rbuf = &rb; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class PixFmt>
|
||||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i r(x1, y1, x2, y2);
|
||||
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
(r.x2 - r.x1) + 1,
|
||||
(r.y2 - r.y1) + 1,
|
||||
stride);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y);
|
||||
}
|
||||
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
AGG_INLINE int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data row(int y) const
|
||||
AGG_INLINE const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row(y);
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
|
||||
{
|
||||
|
@ -1938,6 +2075,24 @@ namespace agg
|
|||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
|
||||
p[order_type::R] = colors->r;
|
||||
p[order_type::G] = colors->g;
|
||||
p[order_type::B] = colors->b;
|
||||
p[order_type::A] = colors->a;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
|
@ -2170,6 +2325,77 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
|
||||
do
|
||||
{
|
||||
cob_type::copy_or_blend_pix(pdst,
|
||||
color.r, color.g, color.b, color.a,
|
||||
(*psrc * cover + base_mask) >> base_shift);
|
||||
++psrc;
|
||||
pdst += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
|
||||
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
const color_type& color = color_lut[*psrc];
|
||||
cob_type::copy_or_blend_pix(pdst,
|
||||
color.r, color.g, color.b, color.a);
|
||||
++psrc;
|
||||
pdst += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
const color_type& color = color_lut[*psrc];
|
||||
cob_type::copy_or_blend_pix(pdst,
|
||||
color.r, color.g, color.b, color.a,
|
||||
cover);
|
||||
++psrc;
|
||||
pdst += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
};
|
||||
|
@ -2199,37 +2425,53 @@ namespace agg
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {}
|
||||
pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) :
|
||||
explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) :
|
||||
m_rbuf(&rb),
|
||||
m_comp_op(comp_op)
|
||||
{}
|
||||
void attach(rbuf_type& rb) { m_rbuf = &rb; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_rbuf->width(); }
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void comp_op(unsigned op) { m_comp_op = op; }
|
||||
unsigned comp_op() const { return m_comp_op; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const
|
||||
template<class PixFmt>
|
||||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
return m_rbuf->row_ptr(y);
|
||||
rect_i r(x1, y1, x2, y2);
|
||||
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
(r.x2 - r.x1) + 1,
|
||||
(r.y2 - r.y1) + 1,
|
||||
stride);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data row(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row(y);
|
||||
}
|
||||
void comp_op(unsigned op) { m_comp_op = op; }
|
||||
unsigned comp_op() const { return m_comp_op; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
|
||||
|
@ -2373,6 +2615,23 @@ namespace agg
|
|||
while(--len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
|
||||
p[order_type::R] = colors->r;
|
||||
p[order_type::G] = colors->g;
|
||||
p[order_type::B] = colors->b;
|
||||
p[order_type::A] = colors->a;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
|
@ -2518,6 +2777,63 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
|
||||
do
|
||||
{
|
||||
blender_type::blend_pix(m_comp_op,
|
||||
pdst,
|
||||
color.r, color.g, color.b, color.a,
|
||||
(*psrc * cover + base_mask) >> base_shift);
|
||||
++psrc;
|
||||
pdst += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
|
||||
do
|
||||
{
|
||||
const color_type& color = color_lut[*psrc];
|
||||
blender_type::blend_pix(m_comp_op,
|
||||
pdst,
|
||||
color.r, color.g, color.b, color.a,
|
||||
cover);
|
||||
++psrc;
|
||||
pdst += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
unsigned m_comp_op;
|
||||
|
|
|
@ -132,10 +132,10 @@ namespace agg
|
|||
cell_type** ptr = m_cells + m_num_blocks - 1;
|
||||
while(m_num_blocks--)
|
||||
{
|
||||
delete [] *ptr;
|
||||
pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
|
||||
ptr--;
|
||||
}
|
||||
delete [] m_cells;
|
||||
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,10 +188,6 @@ namespace agg
|
|||
}
|
||||
*m_curr_cell_ptr++ = m_curr_cell;
|
||||
++m_num_cells;
|
||||
//if(m_curr_cell.x < m_min_x) m_min_x = m_curr_cell.x;
|
||||
//if(m_curr_cell.x > m_max_x) m_max_x = m_curr_cell.x;
|
||||
//if(m_curr_cell.y < m_min_y) m_min_y = m_curr_cell.y;
|
||||
//if(m_curr_cell.y > m_max_y) m_max_y = m_curr_cell.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,16 +470,22 @@ namespace agg
|
|||
{
|
||||
if(m_num_blocks >= m_max_blocks)
|
||||
{
|
||||
cell_type** new_cells = new cell_type* [m_max_blocks + cell_block_pool];
|
||||
cell_type** new_cells =
|
||||
pod_allocator<cell_type*>::allocate(m_max_blocks +
|
||||
cell_block_pool);
|
||||
|
||||
if(m_cells)
|
||||
{
|
||||
memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*));
|
||||
delete [] m_cells;
|
||||
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
|
||||
}
|
||||
m_cells = new_cells;
|
||||
m_max_blocks += cell_block_pool;
|
||||
}
|
||||
m_cells[m_num_blocks++] = new cell_type [unsigned(cell_block_size)];
|
||||
|
||||
m_cells[m_num_blocks++] =
|
||||
pod_allocator<cell_type>::allocate(cell_block_size);
|
||||
|
||||
}
|
||||
m_curr_cell_ptr = m_cells[m_curr_block++];
|
||||
}
|
||||
|
@ -642,7 +644,6 @@ namespace agg
|
|||
// cell = cell; // Breakpoint here
|
||||
// }
|
||||
//}
|
||||
|
||||
// Allocate the array of cell pointers
|
||||
m_sorted_cells.allocate(m_num_cells, 16);
|
||||
|
||||
|
@ -721,6 +722,33 @@ namespace agg
|
|||
m_sorted = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------scanline_hit_test
|
||||
class scanline_hit_test
|
||||
{
|
||||
public:
|
||||
scanline_hit_test(int x) : m_x(x), m_hit(false) {}
|
||||
|
||||
void reset_spans() {}
|
||||
void finalize(int) {}
|
||||
void add_cell(int x, int)
|
||||
{
|
||||
if(m_x == x) m_hit = true;
|
||||
}
|
||||
void add_span(int x, int len, int)
|
||||
{
|
||||
if(m_x >= x && m_x < x+len) m_hit = true;
|
||||
}
|
||||
unsigned num_spans() const { return 1; }
|
||||
bool hit() const { return m_hit; }
|
||||
|
||||
private:
|
||||
int m_x;
|
||||
bool m_hit;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -70,6 +70,15 @@ namespace agg
|
|||
};
|
||||
|
||||
|
||||
//===========================================================layer_order_e
|
||||
enum layer_order_e
|
||||
{
|
||||
layer_unsorted, //------layer_unsorted
|
||||
layer_direct, //------layer_direct
|
||||
layer_inverse //------layer_inverse
|
||||
};
|
||||
|
||||
|
||||
//==================================================rasterizer_compound_aa
|
||||
template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa
|
||||
{
|
||||
|
@ -88,6 +97,7 @@ namespace agg
|
|||
public:
|
||||
typedef Clip clip_type;
|
||||
typedef typename Clip::conv_type conv_type;
|
||||
typedef typename Clip::coord_type coord_type;
|
||||
|
||||
enum aa_scale_e
|
||||
{
|
||||
|
@ -103,13 +113,20 @@ namespace agg
|
|||
m_outline(),
|
||||
m_clipper(),
|
||||
m_filling_rule(fill_non_zero),
|
||||
m_layer_order(layer_direct),
|
||||
m_styles(), // Active Styles
|
||||
m_ast(), // Active Style Table (unique values)
|
||||
m_asm(), // Active Style Mask
|
||||
m_cells(),
|
||||
m_cover_buf(),
|
||||
m_master_alpha(),
|
||||
m_min_style(0x7FFFFFFF),
|
||||
m_max_style(-0x7FFFFFFF),
|
||||
m_scan_y(0x7FFFFFFF)
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_scan_y(0x7FFFFFFF),
|
||||
m_sl_start(0),
|
||||
m_sl_len(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -117,6 +134,8 @@ namespace agg
|
|||
void reset_clipping();
|
||||
void clip_box(double x1, double y1, double x2, double y2);
|
||||
void filling_rule(filling_rule_e filling_rule);
|
||||
void layer_order(layer_order_e order);
|
||||
void master_alpha(int style, double alpha);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void styles(int left, int right);
|
||||
|
@ -158,10 +177,18 @@ namespace agg
|
|||
void sort();
|
||||
bool rewind_scanlines();
|
||||
unsigned sweep_styles();
|
||||
int scanline_start() const { return m_sl_start; }
|
||||
unsigned scanline_length() const { return m_sl_len; }
|
||||
unsigned style(unsigned style_idx) const;
|
||||
|
||||
cover_type* allocate_cover_buffer(unsigned len);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned calculate_alpha(int area) const
|
||||
bool navigate_scanline(int y);
|
||||
bool hit_test(int tx, int ty);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned calculate_alpha(int area, unsigned master_alpha) const
|
||||
{
|
||||
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
|
||||
if(cover < 0) cover = -cover;
|
||||
|
@ -174,7 +201,7 @@ namespace agg
|
|||
}
|
||||
}
|
||||
if(cover > aa_mask) cover = aa_mask;
|
||||
return cover;
|
||||
return (cover * master_alpha + aa_mask) >> aa_shift;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -187,8 +214,17 @@ namespace agg
|
|||
|
||||
sl.reset_spans();
|
||||
|
||||
if(style_idx < 0) style_idx = 0;
|
||||
else style_idx++;
|
||||
unsigned master_alpha = aa_mask;
|
||||
|
||||
if(style_idx < 0)
|
||||
{
|
||||
style_idx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
style_idx++;
|
||||
master_alpha = m_master_alpha[m_ast[style_idx] + m_min_style - 1];
|
||||
}
|
||||
|
||||
const style_info& st = m_styles[m_ast[style_idx]];
|
||||
|
||||
|
@ -208,14 +244,16 @@ namespace agg
|
|||
|
||||
if(area)
|
||||
{
|
||||
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
|
||||
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area,
|
||||
master_alpha);
|
||||
sl.add_cell(x, alpha);
|
||||
x++;
|
||||
}
|
||||
|
||||
if(num_cells && cell->x > x)
|
||||
{
|
||||
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
|
||||
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1),
|
||||
master_alpha);
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_span(x, cell->x - x, alpha);
|
||||
|
@ -226,11 +264,11 @@ namespace agg
|
|||
if(sl.num_spans() == 0) return false;
|
||||
sl.finalize(scan_y);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
void add_style(int style_id);
|
||||
void allocate_master_alpha();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Disable copying
|
||||
|
@ -242,14 +280,21 @@ namespace agg
|
|||
rasterizer_cells_aa<cell_style_aa> m_outline;
|
||||
clip_type m_clipper;
|
||||
filling_rule_e m_filling_rule;
|
||||
layer_order_e m_layer_order;
|
||||
pod_vector<style_info> m_styles; // Active Styles
|
||||
pod_vector<unsigned> m_ast; // Active Style Table (unique values)
|
||||
pod_vector<int8u> m_asm; // Active Style Mask
|
||||
pod_vector<cell_info> m_cells;
|
||||
pod_vector<cover_type> m_cover_buf;
|
||||
pod_bvector<unsigned> m_master_alpha;
|
||||
|
||||
int m_min_style;
|
||||
int m_max_style;
|
||||
coord_type m_start_x;
|
||||
coord_type m_start_y;
|
||||
int m_scan_y;
|
||||
int m_sl_start;
|
||||
unsigned m_sl_len;
|
||||
};
|
||||
|
||||
|
||||
|
@ -269,6 +314,8 @@ namespace agg
|
|||
m_min_style = 0x7FFFFFFF;
|
||||
m_max_style = -0x7FFFFFFF;
|
||||
m_scan_y = 0x7FFFFFFF;
|
||||
m_sl_start = 0;
|
||||
m_sl_len = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -278,6 +325,13 @@ namespace agg
|
|||
m_filling_rule = filling_rule;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::layer_order(layer_order_e order)
|
||||
{
|
||||
m_layer_order = order;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1,
|
||||
|
@ -316,7 +370,8 @@ namespace agg
|
|||
void rasterizer_compound_aa<Clip>::move_to(int x, int y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::downscale(x), conv_type::downscale(y));
|
||||
m_clipper.move_to(m_start_x = conv_type::downscale(x),
|
||||
m_start_y = conv_type::downscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -333,7 +388,8 @@ namespace agg
|
|||
void rasterizer_compound_aa<Clip>::move_to_d(double x, double y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::upscale(x), conv_type::upscale(y));
|
||||
m_clipper.move_to(m_start_x = conv_type::upscale(x),
|
||||
m_start_y = conv_type::upscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -354,11 +410,14 @@ namespace agg
|
|||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
else
|
||||
if(is_close(cmd))
|
||||
{
|
||||
m_clipper.line_to(m_outline, m_start_x, m_start_y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -407,6 +466,7 @@ namespace agg
|
|||
}
|
||||
m_scan_y = m_outline.min_y();
|
||||
m_styles.allocate(m_max_style - m_min_style + 2, 128);
|
||||
allocate_master_alpha();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -453,6 +513,8 @@ namespace agg
|
|||
m_asm.allocate((num_styles + 7) >> 3, 8);
|
||||
m_asm.zero();
|
||||
|
||||
if(num_cells)
|
||||
{
|
||||
// Pre-add zero (for no-fill style, that is, -1).
|
||||
// We need that to ensure that the "-1 style" would go first.
|
||||
m_asm[0] |= 1;
|
||||
|
@ -462,6 +524,8 @@ namespace agg
|
|||
style->num_cells = 0;
|
||||
style->last_x = -0x7FFFFFFF;
|
||||
|
||||
m_sl_start = cells[0]->x;
|
||||
m_sl_len = cells[num_cells-1]->x - m_sl_start + 1;
|
||||
while(num_cells--)
|
||||
{
|
||||
curr_cell = *cells++;
|
||||
|
@ -526,10 +590,19 @@ namespace agg
|
|||
style->num_cells++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(m_ast.size() > 1) break;
|
||||
++m_scan_y;
|
||||
}
|
||||
++m_scan_y;
|
||||
|
||||
if(m_layer_order != layer_unsorted)
|
||||
{
|
||||
range_adaptor<pod_vector<unsigned> > ra(m_ast, 1, m_ast.size() - 1);
|
||||
if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater);
|
||||
else quick_sort(ra, unsigned_less);
|
||||
}
|
||||
|
||||
return m_ast.size() - 1;
|
||||
}
|
||||
|
||||
|
@ -542,6 +615,80 @@ namespace agg
|
|||
return m_ast[style_idx + 1] + m_min_style - 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_compound_aa<Clip>::navigate_scanline(int y)
|
||||
{
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(m_max_style < m_min_style)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(y < m_outline.min_y() || y > m_outline.max_y())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = y;
|
||||
m_styles.allocate(m_max_style - m_min_style + 2, 128);
|
||||
allocate_master_alpha();
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
bool rasterizer_compound_aa<Clip>::hit_test(int tx, int ty)
|
||||
{
|
||||
if(!navigate_scanline(ty))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned num_styles = sweep_styles();
|
||||
if(num_styles <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
scanline_hit_test sl(tx);
|
||||
sweep_scanline(sl, -1);
|
||||
return sl.hit();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
cover_type* rasterizer_compound_aa<Clip>::allocate_cover_buffer(unsigned len)
|
||||
{
|
||||
m_cover_buf.allocate(len, 256);
|
||||
return &m_cover_buf[0];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::allocate_master_alpha()
|
||||
{
|
||||
while((int)m_master_alpha.size() <= m_max_style)
|
||||
{
|
||||
m_master_alpha.add(aa_mask);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::master_alpha(int style, double alpha)
|
||||
{
|
||||
if(style >= 0)
|
||||
{
|
||||
while((int)m_master_alpha.size() <= style)
|
||||
{
|
||||
m_master_alpha.add(aa_mask);
|
||||
}
|
||||
m_master_alpha[style] = uround(alpha * aa_mask);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -23,13 +23,14 @@ namespace agg
|
|||
template<class Renderer> class rasterizer_outline
|
||||
{
|
||||
public:
|
||||
rasterizer_outline(Renderer& ren) :
|
||||
explicit rasterizer_outline(Renderer& ren) :
|
||||
m_ren(&ren),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_vertices(0)
|
||||
{
|
||||
}
|
||||
{}
|
||||
void attach(Renderer& ren) { m_ren = &ren; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(int x, int y)
|
||||
|
|
|
@ -85,21 +85,21 @@ namespace agg
|
|||
typedef line_aa_vertex vertex_type;
|
||||
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
|
||||
|
||||
rasterizer_outline_aa(Renderer& ren) :
|
||||
m_ren(ren),
|
||||
explicit rasterizer_outline_aa(Renderer& ren) :
|
||||
m_ren(&ren),
|
||||
m_line_join(ren.accurate_join_only() ?
|
||||
outline_miter_accurate_join :
|
||||
outline_round_join),
|
||||
m_round_cap(false),
|
||||
m_start_x(0),
|
||||
m_start_y(0)
|
||||
{
|
||||
}
|
||||
{}
|
||||
void attach(Renderer& ren) { m_ren = &ren; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void line_join(outline_aa_join_e join)
|
||||
{
|
||||
m_line_join = m_ren.accurate_join_only() ?
|
||||
m_line_join = m_ren->accurate_join_only() ?
|
||||
outline_miter_accurate_join :
|
||||
join;
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ namespace agg
|
|||
{
|
||||
for(unsigned i = 0; i < num_paths; i++)
|
||||
{
|
||||
m_ren.color(colors[i]);
|
||||
m_ren->color(colors[i]);
|
||||
add_path(vs, path_id[i]);
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ namespace agg
|
|||
unsigned i;
|
||||
for(i = 0; i < c.num_paths(); i++)
|
||||
{
|
||||
m_ren.color(c.color(i));
|
||||
m_ren->color(c.color(i));
|
||||
add_path(c, i);
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ namespace agg
|
|||
const rasterizer_outline_aa<Renderer, Coord>& operator =
|
||||
(const rasterizer_outline_aa<Renderer, Coord>&);
|
||||
|
||||
Renderer& m_ren;
|
||||
Renderer* m_ren;
|
||||
vertex_storage_type m_src_vertices;
|
||||
outline_aa_join_e m_line_join;
|
||||
bool m_round_cap;
|
||||
|
@ -245,15 +245,15 @@ namespace agg
|
|||
|
||||
switch(dv.flags)
|
||||
{
|
||||
case 0: m_ren.line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
|
||||
case 1: m_ren.line2(dv.curr, dv.xb2, dv.yb2); break;
|
||||
case 2: m_ren.line1(dv.curr, dv.xb1, dv.yb1); break;
|
||||
case 3: m_ren.line0(dv.curr); break;
|
||||
case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
|
||||
case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break;
|
||||
case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break;
|
||||
case 3: m_ren->line0(dv.curr); break;
|
||||
}
|
||||
|
||||
if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
|
||||
{
|
||||
m_ren.pie(dv.curr.x2, dv.curr.y2,
|
||||
m_ren->pie(dv.curr.x2, dv.curr.y2,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
|
||||
dv.curr.x2 + (dv.next.y2 - dv.next.y1),
|
||||
|
@ -406,16 +406,16 @@ namespace agg
|
|||
line_parameters lp(x1, y1, x2, y2, lprev);
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
m_ren.line3(lp,
|
||||
m_ren->line3(lp,
|
||||
x1 + (y2 - y1),
|
||||
y1 - (x2 - x1),
|
||||
x2 + (y2 - y1),
|
||||
y2 - (x2 - x1));
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -440,32 +440,32 @@ namespace agg
|
|||
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren.line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
|
||||
m_ren.pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
|
||||
m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
|
||||
x2 + (y3 - y2), y2 - (x3 - x2));
|
||||
|
||||
m_ren.line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
|
||||
m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
|
||||
x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
else
|
||||
{
|
||||
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
|
||||
m_ren.line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
dv.xb1, dv.yb1);
|
||||
|
||||
m_ren.line3(lp2, dv.xb1, dv.yb1,
|
||||
m_ren->line3(lp2, dv.xb1, dv.yb1,
|
||||
x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -521,15 +521,15 @@ namespace agg
|
|||
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
if((dv.flags & 1) == 0)
|
||||
{
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
m_ren.pie(prev.x2, prev.y2,
|
||||
m_ren->pie(prev.x2, prev.y2,
|
||||
x2 + (y2 - y1), y2 - (x2 - x1),
|
||||
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
|
||||
|
@ -537,13 +537,13 @@ namespace agg
|
|||
else
|
||||
{
|
||||
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
|
||||
m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
dv.xb1, dv.yb1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ren.line1(prev,
|
||||
m_ren->line1(prev,
|
||||
x1 + (y2 - y1),
|
||||
y1 - (x2 - x1));
|
||||
}
|
||||
|
@ -558,7 +558,7 @@ namespace agg
|
|||
{
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren.line3(dv.curr,
|
||||
m_ren->line3(dv.curr,
|
||||
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
|
@ -566,20 +566,20 @@ namespace agg
|
|||
}
|
||||
else
|
||||
{
|
||||
m_ren.line3(dv.curr, dv.xb1, dv.yb1,
|
||||
m_ren->line3(dv.curr, dv.xb1, dv.yb1,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ren.line2(dv.curr,
|
||||
m_ren->line2(dv.curr,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren.semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
|
||||
m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
|
|
|
@ -357,7 +357,7 @@ namespace agg
|
|||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::close_polygon()
|
||||
{
|
||||
if(m_auto_close && m_status == status_line_to)
|
||||
if(m_status == status_line_to)
|
||||
{
|
||||
m_clipper.line_to(m_outline, m_start_x, m_start_y);
|
||||
m_status = status_closed;
|
||||
|
@ -369,7 +369,7 @@ namespace agg
|
|||
void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
if(m_status == status_line_to) close_polygon();
|
||||
if(m_auto_close) close_polygon();
|
||||
m_clipper.move_to(m_start_x = conv_type::downscale(x),
|
||||
m_start_y = conv_type::downscale(y));
|
||||
m_status = status_move_to;
|
||||
|
@ -390,7 +390,7 @@ namespace agg
|
|||
void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
if(m_status == status_line_to) close_polygon();
|
||||
if(m_auto_close) close_polygon();
|
||||
m_clipper.move_to(m_start_x = conv_type::upscale(x),
|
||||
m_start_y = conv_type::upscale(y));
|
||||
m_status = status_move_to;
|
||||
|
@ -415,11 +415,14 @@ namespace agg
|
|||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
else
|
||||
if(is_close(cmd))
|
||||
{
|
||||
close_polygon();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,6 +455,7 @@ namespace agg
|
|||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::sort()
|
||||
{
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
}
|
||||
|
||||
|
@ -459,7 +463,7 @@ namespace agg
|
|||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
|
||||
{
|
||||
close_polygon();
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0)
|
||||
{
|
||||
|
@ -474,7 +478,7 @@ namespace agg
|
|||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
|
||||
{
|
||||
close_polygon();
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0 ||
|
||||
y < m_outline.min_y() ||
|
||||
|
@ -486,31 +490,6 @@ namespace agg
|
|||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------scanline_hit_test
|
||||
class scanline_hit_test
|
||||
{
|
||||
public:
|
||||
scanline_hit_test(int x) : m_x(x), m_hit(false) {}
|
||||
|
||||
void reset_spans() {}
|
||||
void finalize(int) {}
|
||||
void add_cell(int x, int)
|
||||
{
|
||||
if(m_x == x) m_hit = true;
|
||||
}
|
||||
void add_span(int x, int len, int)
|
||||
{
|
||||
if(m_x >= x && m_x < x+len) m_hit = true;
|
||||
}
|
||||
unsigned num_spans() const { return 1; }
|
||||
bool hit() const { return m_hit; }
|
||||
|
||||
private:
|
||||
int m_x;
|
||||
bool m_hit;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace agg
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {}
|
||||
renderer_base(pixfmt_type& ren) :
|
||||
explicit renderer_base(pixfmt_type& ren) :
|
||||
m_ren(&ren),
|
||||
m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
|
||||
{}
|
||||
|
@ -327,6 +327,30 @@ namespace agg
|
|||
m_ren->copy_color_hspan(x, y, len, colors);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y, int len, const color_type* colors)
|
||||
{
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
|
||||
if(y < ymin())
|
||||
{
|
||||
int d = ymin() - y;
|
||||
len -= d;
|
||||
if(len <= 0) return;
|
||||
colors += d;
|
||||
y = ymin();
|
||||
}
|
||||
if(y + len > ymax())
|
||||
{
|
||||
len = ymax() - y + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->copy_color_vspan(x, y, len, colors);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
|
@ -539,6 +563,150 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& src,
|
||||
const color_type& color,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
rect_i rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
|
||||
if(rw.ptr)
|
||||
{
|
||||
int x1src = rsrc.x1;
|
||||
int x1dst = rdst.x1;
|
||||
int len = rc.x2;
|
||||
if(rw.x1 > x1src)
|
||||
{
|
||||
x1dst += rw.x1 - x1src;
|
||||
len -= rw.x1 - x1src;
|
||||
x1src = rw.x1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x1src + len-1 > rw.x2)
|
||||
{
|
||||
len -= x1src + len - rw.x2 - 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_from_color(src,
|
||||
color,
|
||||
x1dst, rdst.y1,
|
||||
x1src, rsrc.y1,
|
||||
len,
|
||||
cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& src,
|
||||
const color_type* color_lut,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
rect_i rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
|
||||
if(rw.ptr)
|
||||
{
|
||||
int x1src = rsrc.x1;
|
||||
int x1dst = rdst.x1;
|
||||
int len = rc.x2;
|
||||
if(rw.x1 > x1src)
|
||||
{
|
||||
x1dst += rw.x1 - x1src;
|
||||
len -= rw.x1 - x1src;
|
||||
x1src = rw.x1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x1src + len-1 > rw.x2)
|
||||
{
|
||||
len -= x1src + len - rw.x2 - 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_from_lut(src,
|
||||
color_lut,
|
||||
x1dst, rdst.y1,
|
||||
x1src, rsrc.y1,
|
||||
len,
|
||||
cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pixfmt_type* m_ren;
|
||||
rect_i m_clip_box;
|
||||
|
|
|
@ -65,8 +65,7 @@ namespace agg
|
|||
//--------------------------------------------------------------------
|
||||
renderer_markers(base_ren_type& rbuf) :
|
||||
base_type(rbuf)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool visible(int x, int y, int r) const
|
||||
|
|
|
@ -37,11 +37,15 @@ namespace agg
|
|||
typedef renderer_base<pixfmt_type> base_ren_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_mclip(pixfmt_type& ren) :
|
||||
m_ren(ren),
|
||||
explicit renderer_mclip(pixfmt_type& pixf) :
|
||||
m_ren(pixf),
|
||||
m_curr_cb(0),
|
||||
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
|
||||
{}
|
||||
void attach(pixfmt_type& pixf)
|
||||
{
|
||||
m_ren.attach(pixf);
|
||||
reset_clipping(true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED
|
||||
#define AGG_RENDERER_OUTLINE_AA_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
#include "agg_math.h"
|
||||
#include "agg_line_aa_basics.h"
|
||||
#include "agg_dda_line.h"
|
||||
|
@ -1273,13 +1273,8 @@ namespace agg
|
|||
aa_mask = aa_scale - 1
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
~line_profile_aa() { delete [] m_profile; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
line_profile_aa() :
|
||||
m_size(0),
|
||||
m_profile(0),
|
||||
m_subpixel_width(0),
|
||||
m_min_width(1.0),
|
||||
m_smoother_width(1.0)
|
||||
|
@ -1291,8 +1286,6 @@ namespace agg
|
|||
//---------------------------------------------------------------------
|
||||
template<class GammaF>
|
||||
line_profile_aa(double w, const GammaF& gamma_function) :
|
||||
m_size(0),
|
||||
m_profile(0),
|
||||
m_subpixel_width(0),
|
||||
m_min_width(1.0),
|
||||
m_smoother_width(1.0)
|
||||
|
@ -1318,7 +1311,7 @@ namespace agg
|
|||
|
||||
void width(double w);
|
||||
|
||||
unsigned profile_size() const { return m_size; }
|
||||
unsigned profile_size() const { return m_profile.size(); }
|
||||
int subpixel_width() const { return m_subpixel_width; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
@ -1339,8 +1332,7 @@ namespace agg
|
|||
void set(double center_width, double smoother_width);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
unsigned m_size;
|
||||
value_type* m_profile;
|
||||
pod_array<value_type> m_profile;
|
||||
value_type m_gamma[aa_scale];
|
||||
int m_subpixel_width;
|
||||
double m_min_width;
|
||||
|
@ -1363,8 +1355,8 @@ namespace agg
|
|||
m_profile(&prof),
|
||||
m_clip_box(0,0,0,0),
|
||||
m_clipping(false)
|
||||
{
|
||||
}
|
||||
{}
|
||||
void attach(base_ren_type& ren) { m_ren = &ren; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
|
@ -1657,7 +1649,7 @@ namespace agg
|
|||
}
|
||||
else
|
||||
{
|
||||
while(abs(sx - lp.x1) + abs(sy - lp.y1) > 2 * lp2.len)
|
||||
while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
|
||||
{
|
||||
sx = (lp.x1 + sx) >> 1;
|
||||
sy = (lp.y1 + sy) >> 1;
|
||||
|
@ -1724,7 +1716,7 @@ namespace agg
|
|||
}
|
||||
else
|
||||
{
|
||||
while(abs(ex - lp.x2) + abs(ey - lp.y2) > 2 * lp2.len)
|
||||
while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
|
||||
{
|
||||
ex = (lp.x2 + ex) >> 1;
|
||||
ey = (lp.y2 + ey) >> 1;
|
||||
|
@ -1796,7 +1788,7 @@ namespace agg
|
|||
}
|
||||
else
|
||||
{
|
||||
while(abs(sx - lp.x1) + abs(sy - lp.y1) > 2 * lp2.len)
|
||||
while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
|
||||
{
|
||||
sx = (lp.x1 + sx) >> 1;
|
||||
sy = (lp.y1 + sy) >> 1;
|
||||
|
@ -1809,7 +1801,7 @@ namespace agg
|
|||
}
|
||||
else
|
||||
{
|
||||
while(abs(ex - lp.x2) + abs(ey - lp.y2) > 2 * lp2.len)
|
||||
while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
|
||||
{
|
||||
ex = (lp.x2 + ex) >> 1;
|
||||
ey = (lp.y2 + ey) >> 1;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
|
||||
#define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
#include "agg_math.h"
|
||||
#include "agg_line_aa_basics.h"
|
||||
#include "agg_dda_line.h"
|
||||
|
@ -69,18 +70,12 @@ namespace agg
|
|||
typedef Filter filter_type;
|
||||
typedef typename filter_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~line_image_pattern()
|
||||
{
|
||||
delete [] m_data;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
line_image_pattern(const Filter& filter) :
|
||||
m_filter(&filter),
|
||||
m_dilation(filter.dilation() + 1),
|
||||
m_dilation_hr(m_dilation << line_subpixel_shift),
|
||||
m_data(0),
|
||||
m_data(),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_width_hr(0),
|
||||
|
@ -96,7 +91,7 @@ namespace agg
|
|||
m_filter(&filter),
|
||||
m_dilation(filter.dilation() + 1),
|
||||
m_dilation_hr(m_dilation << line_subpixel_shift),
|
||||
m_data(0),
|
||||
m_data(),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_width_hr(0),
|
||||
|
@ -117,10 +112,9 @@ namespace agg
|
|||
m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2;
|
||||
m_half_height_hr += line_subpixel_scale/2;
|
||||
|
||||
delete [] m_data;
|
||||
m_data = new color_type [(m_width + m_dilation * 2) * (m_height + m_dilation * 2)];
|
||||
m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2));
|
||||
|
||||
m_buf.attach(m_data, m_width + m_dilation * 2,
|
||||
m_buf.attach(&m_data[0], m_width + m_dilation * 2,
|
||||
m_height + m_dilation * 2,
|
||||
m_width + m_dilation * 2);
|
||||
unsigned x, y;
|
||||
|
@ -195,7 +189,7 @@ namespace agg
|
|||
const filter_type* m_filter;
|
||||
unsigned m_dilation;
|
||||
int m_dilation_hr;
|
||||
color_type* m_data;
|
||||
pod_array<color_type> m_data;
|
||||
unsigned m_width;
|
||||
unsigned m_height;
|
||||
int m_width_hr;
|
||||
|
@ -829,8 +823,8 @@ namespace agg
|
|||
m_scale_x(1.0),
|
||||
m_clip_box(0,0,0,0),
|
||||
m_clipping(false)
|
||||
{
|
||||
}
|
||||
{}
|
||||
void attach(base_ren_type& ren) { m_ren = &ren; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void pattern(const pattern_type& p) { m_pattern = &p; }
|
||||
|
@ -924,10 +918,6 @@ namespace agg
|
|||
|
||||
fix_degenerate_bisectrix_start(lp, &sx, &sy);
|
||||
fix_degenerate_bisectrix_end(lp, &ex, &ey);
|
||||
//sx = lp.x1 + (lp.y2 - lp.y1);
|
||||
//sy = lp.y1 - (lp.x2 - lp.x1);
|
||||
//ex = lp.x2 + (lp.y2 - lp.y1);
|
||||
//ey = lp.y2 - (lp.x2 - lp.x1);
|
||||
line_interpolator_image<self_type> li(*this, lp,
|
||||
sx, sy,
|
||||
ex, ey,
|
||||
|
|
|
@ -35,14 +35,14 @@ namespace agg
|
|||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_primitives(base_ren_type& ren) :
|
||||
explicit renderer_primitives(base_ren_type& ren) :
|
||||
m_ren(&ren),
|
||||
m_fill_color(),
|
||||
m_line_color(),
|
||||
m_curr_x(0),
|
||||
m_curr_y(0)
|
||||
{
|
||||
}
|
||||
{}
|
||||
void attach(base_ren_type& ren) { m_ren = &ren; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static int coord(double c)
|
||||
|
|
|
@ -34,8 +34,8 @@ namespace agg
|
|||
renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) :
|
||||
m_ren(&ren),
|
||||
m_glyph(&glyph)
|
||||
{
|
||||
}
|
||||
{}
|
||||
void attach(ren_type& ren) { m_ren = &ren; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
|
|
|
@ -52,7 +52,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//===============================================render_scanlines_aa_solid
|
||||
template<class Rasterizer, class Scanline,
|
||||
class BaseRenderer, class ColorT>
|
||||
|
@ -103,7 +102,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================renderer_scanline_aa_solid
|
||||
template<class BaseRenderer> class renderer_scanline_aa_solid
|
||||
{
|
||||
|
@ -113,7 +111,7 @@ namespace agg
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_aa_solid() : m_ren(0) {}
|
||||
renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {}
|
||||
explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {}
|
||||
void attach(base_ren_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
|
@ -176,8 +174,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=====================================================render_scanlines_aa
|
||||
template<class Rasterizer, class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
|
@ -195,8 +191,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//====================================================renderer_scanline_aa
|
||||
template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
|
||||
class renderer_scanline_aa
|
||||
|
@ -244,318 +238,6 @@ namespace agg
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
//===================================================renderer_scanline_bin
|
||||
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin() : m_ren(0), m_span_gen(0) {}
|
||||
renderer_scanline_bin(base_ren_type& ren, span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren, span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(unsigned max_span_len)
|
||||
{
|
||||
m_span_gen->prepare(max_span_len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
int y = sl.y();
|
||||
m_ren->first_clip_box();
|
||||
do
|
||||
{
|
||||
int xmin = m_ren->xmin();
|
||||
int xmax = m_ren->xmax();
|
||||
|
||||
if(y >= m_ren->ymin() && y <= m_ren->ymax())
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
|
||||
if(len < 0) len = -len;
|
||||
if(x < xmin)
|
||||
{
|
||||
len -= xmin - x;
|
||||
x = xmin;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x + len > xmax)
|
||||
{
|
||||
len = xmax - x + 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_color_hspan_no_clip(
|
||||
x, y, len,
|
||||
m_span_gen->generate(x, y, len),
|
||||
0);
|
||||
}
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(m_ren->next_clip_box());
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
SpanGenerator* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================================================renderer_scanline_direct
|
||||
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_direct
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_direct() : m_ren(0), m_span_gen(0) {}
|
||||
renderer_scanline_direct(base_ren_type& ren, span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren, span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(unsigned max_span_len)
|
||||
{
|
||||
m_span_gen->prepare(max_span_len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
int y = sl.y();
|
||||
m_ren->first_clip_box();
|
||||
do
|
||||
{
|
||||
int xmin = m_ren->xmin();
|
||||
int xmax = m_ren->xmax();
|
||||
|
||||
if(y >= m_ren->ymin() && y <= m_ren->ymax())
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
|
||||
if(len < 0) len = -len;
|
||||
if(x < xmin)
|
||||
{
|
||||
len -= xmin - x;
|
||||
x = xmin;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x + len > xmax)
|
||||
{
|
||||
len = xmax - x + 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
span_data span = m_ren->span(x, y, len);
|
||||
if(span.ptr)
|
||||
{
|
||||
m_span_gen->generate(span.x, y, span.len, span.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(m_ren->next_clip_box());
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
SpanGenerator* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============================================renderer_scanline_bin_copy
|
||||
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin_copy
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin_copy() : m_ren(0), m_span_gen(0) {}
|
||||
renderer_scanline_bin_copy(base_ren_type& ren, span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren, span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(unsigned max_span_len)
|
||||
{
|
||||
m_span_gen->prepare(max_span_len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
int y = sl.y();
|
||||
m_ren->first_clip_box();
|
||||
do
|
||||
{
|
||||
int xmin = m_ren->xmin();
|
||||
int xmax = m_ren->xmax();
|
||||
|
||||
if(y >= m_ren->ymin() && y <= m_ren->ymax())
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
|
||||
if(len < 0) len = -len;
|
||||
if(x < xmin)
|
||||
{
|
||||
len -= xmin - x;
|
||||
x = xmin;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x + len > xmax)
|
||||
{
|
||||
len = xmax - x + 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->copy_color_hspan_no_clip(
|
||||
x, y, len,
|
||||
m_span_gen->generate(x, y, len));
|
||||
}
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(m_ren->next_clip_box());
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
SpanGenerator* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============================================renderer_scanline_bin_solid
|
||||
template<class BaseRenderer> class renderer_scanline_bin_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin_solid() : m_ren(0) {}
|
||||
renderer_scanline_bin_solid(base_ren_type& ren) :
|
||||
m_ren(&ren)
|
||||
{}
|
||||
void attach(base_ren_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(unsigned) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
m_ren->blend_hline(span->x,
|
||||
sl.y(),
|
||||
span->x - 1 + ((span->len < 0) ?
|
||||
-span->len :
|
||||
span->len),
|
||||
m_color,
|
||||
cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
color_type m_color;
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============================================render_scanline_bin_solid
|
||||
template<class Scanline, class BaseRenderer, class ColorT>
|
||||
void render_scanline_bin_solid(const Scanline& sl,
|
||||
|
@ -578,7 +260,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================render_scanlines_bin_solid
|
||||
template<class Rasterizer, class Scanline,
|
||||
class BaseRenderer, class ColorT>
|
||||
|
@ -621,7 +302,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================renderer_scanline_bin_solid
|
||||
template<class BaseRenderer> class renderer_scanline_bin_solid
|
||||
{
|
||||
|
@ -631,7 +311,7 @@ namespace agg
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin_solid() : m_ren(0) {}
|
||||
renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {}
|
||||
explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {}
|
||||
void attach(base_ren_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
|
@ -662,6 +342,92 @@ namespace agg
|
|||
|
||||
|
||||
|
||||
//======================================================render_scanline_bin
|
||||
template<class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
void render_scanline_bin(const Scanline& sl, BaseRenderer& ren,
|
||||
SpanAllocator& alloc, SpanGenerator& span_gen)
|
||||
{
|
||||
int y = sl.y();
|
||||
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
if(len < 0) len = -len;
|
||||
typename BaseRenderer::color_type* colors = alloc.allocate(len);
|
||||
span_gen.generate(colors, x, y, len);
|
||||
ren.blend_color_hspan(x, y, len, colors, 0, cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================render_scanlines_bin
|
||||
template<class Rasterizer, class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
|
||||
SpanAllocator& alloc, SpanGenerator& span_gen)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
span_gen.prepare();
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
render_scanline_bin(sl, ren, alloc, span_gen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//====================================================renderer_scanline_bin
|
||||
template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
|
||||
class renderer_scanline_bin
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanAllocator alloc_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {}
|
||||
renderer_scanline_bin(base_ren_type& ren,
|
||||
alloc_type& alloc,
|
||||
span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_alloc(&alloc),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren,
|
||||
alloc_type& alloc,
|
||||
span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_alloc = &alloc;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() { m_span_gen->prepare(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen);
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
alloc_type* m_alloc;
|
||||
span_gen_type* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -682,7 +448,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================render_all_paths
|
||||
template<class Rasterizer, class Scanline, class Renderer,
|
||||
class VertexSource, class ColorStorage, class PathId>
|
||||
|
@ -707,6 +472,7 @@ namespace agg
|
|||
|
||||
|
||||
|
||||
|
||||
//=============================================render_scanlines_compound
|
||||
template<class Rasterizer,
|
||||
class ScanlineAA,
|
||||
|
@ -820,8 +586,15 @@ namespace agg
|
|||
colors = mix_buffer + span_aa->x - min_x;
|
||||
covers = span_aa->covers;
|
||||
do
|
||||
{
|
||||
if(*covers == cover_full)
|
||||
{
|
||||
*colors = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
colors->add(c, *covers);
|
||||
}
|
||||
++colors;
|
||||
++covers;
|
||||
}
|
||||
|
@ -846,8 +619,15 @@ namespace agg
|
|||
style);
|
||||
covers = span_aa->covers;
|
||||
do
|
||||
{
|
||||
if(*covers == cover_full)
|
||||
{
|
||||
*colors = *cspan;
|
||||
}
|
||||
else
|
||||
{
|
||||
colors->add(*cspan, *covers);
|
||||
}
|
||||
++cspan;
|
||||
++colors;
|
||||
++covers;
|
||||
|
@ -875,15 +655,196 @@ namespace agg
|
|||
if(--num_spans == 0) break;
|
||||
++span_bin;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if(ras.sweep_scanline(sl_bin, -1))
|
||||
} // if(num_styles == 1) ... else
|
||||
} // while((num_styles = ras.sweep_styles()) > 0)
|
||||
} // if(ras.rewind_scanlines())
|
||||
}
|
||||
|
||||
//=======================================render_scanlines_compound_layered
|
||||
template<class Rasterizer,
|
||||
class ScanlineAA,
|
||||
class BaseRenderer,
|
||||
class SpanAllocator,
|
||||
class StyleHandler>
|
||||
void render_scanlines_compound_layered(Rasterizer& ras,
|
||||
ScanlineAA& sl_aa,
|
||||
BaseRenderer& ren,
|
||||
SpanAllocator& alloc,
|
||||
StyleHandler& sh)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
int min_x = ras.min_x();
|
||||
int len = ras.max_x() - min_x + 2;
|
||||
sl_aa.reset(min_x, ras.max_x());
|
||||
|
||||
typedef typename BaseRenderer::color_type color_type;
|
||||
color_type* color_span = alloc.allocate(len * 2);
|
||||
color_type* mix_buffer = color_span + len;
|
||||
cover_type* cover_buffer = ras.allocate_cover_buffer(len);
|
||||
unsigned num_spans;
|
||||
|
||||
unsigned num_styles;
|
||||
unsigned style;
|
||||
bool solid;
|
||||
while((num_styles = ras.sweep_styles()) > 0)
|
||||
{
|
||||
typename ScanlineAA::const_iterator span_aa;
|
||||
if(num_styles == 1)
|
||||
{
|
||||
// Optimization for a single style. Happens often
|
||||
//-------------------------
|
||||
if(ras.sweep_scanline(sl_aa, 0))
|
||||
{
|
||||
style = ras.style(0);
|
||||
if(sh.is_solid(style))
|
||||
{
|
||||
// Just solid fill
|
||||
//-----------------------
|
||||
render_scanline_aa_solid(sl_aa, ren, sh.color(style));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary span generator
|
||||
//-----------------------
|
||||
span_aa = sl_aa.begin();
|
||||
num_spans = sl_aa.num_spans();
|
||||
for(;;)
|
||||
{
|
||||
len = span_aa->len;
|
||||
sh.generate_span(color_span,
|
||||
span_aa->x,
|
||||
sl_aa.y(),
|
||||
len,
|
||||
style);
|
||||
|
||||
ren.blend_color_hspan(span_aa->x,
|
||||
sl_aa.y(),
|
||||
span_aa->len,
|
||||
color_span,
|
||||
span_aa->covers);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int sl_start = ras.scanline_start();
|
||||
unsigned sl_len = ras.scanline_length();
|
||||
|
||||
if(sl_len)
|
||||
{
|
||||
memset(mix_buffer + sl_start - min_x,
|
||||
0,
|
||||
sl_len * sizeof(color_type));
|
||||
|
||||
memset(cover_buffer + sl_start - min_x,
|
||||
0,
|
||||
sl_len * sizeof(cover_type));
|
||||
|
||||
int sl_y = 0x7FFFFFFF;
|
||||
unsigned i;
|
||||
for(i = 0; i < num_styles; i++)
|
||||
{
|
||||
style = ras.style(i);
|
||||
solid = sh.is_solid(style);
|
||||
|
||||
if(ras.sweep_scanline(sl_aa, i))
|
||||
{
|
||||
unsigned cover;
|
||||
color_type* colors;
|
||||
color_type* cspan;
|
||||
cover_type* src_covers;
|
||||
cover_type* dst_covers;
|
||||
span_aa = sl_aa.begin();
|
||||
num_spans = sl_aa.num_spans();
|
||||
sl_y = sl_aa.y();
|
||||
if(solid)
|
||||
{
|
||||
// Just solid fill
|
||||
//-----------------------
|
||||
for(;;)
|
||||
{
|
||||
color_type c = sh.color(style);
|
||||
len = span_aa->len;
|
||||
colors = mix_buffer + span_aa->x - min_x;
|
||||
src_covers = span_aa->covers;
|
||||
dst_covers = cover_buffer + span_aa->x - min_x;
|
||||
do
|
||||
{
|
||||
cover = *src_covers;
|
||||
if(*dst_covers + cover > cover_full)
|
||||
{
|
||||
cover = cover_full - *dst_covers;
|
||||
}
|
||||
if(cover)
|
||||
{
|
||||
colors->add(c, cover);
|
||||
*dst_covers += cover;
|
||||
}
|
||||
++colors;
|
||||
++src_covers;
|
||||
++dst_covers;
|
||||
}
|
||||
while(--len);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary span generator
|
||||
//-----------------------
|
||||
for(;;)
|
||||
{
|
||||
len = span_aa->len;
|
||||
colors = mix_buffer + span_aa->x - min_x;
|
||||
cspan = color_span;
|
||||
sh.generate_span(cspan,
|
||||
span_aa->x,
|
||||
sl_aa.y(),
|
||||
len,
|
||||
style);
|
||||
src_covers = span_aa->covers;
|
||||
dst_covers = cover_buffer + span_aa->x - min_x;
|
||||
do
|
||||
{
|
||||
cover = *src_covers;
|
||||
if(*dst_covers + cover > cover_full)
|
||||
{
|
||||
cover = cover_full - *dst_covers;
|
||||
}
|
||||
if(cover)
|
||||
{
|
||||
colors->add(*cspan, cover);
|
||||
*dst_covers += cover;
|
||||
}
|
||||
++cspan;
|
||||
++colors;
|
||||
++src_covers;
|
||||
++dst_covers;
|
||||
}
|
||||
while(--len);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ren.blend_color_hspan(sl_start,
|
||||
sl_y,
|
||||
sl_len,
|
||||
mix_buffer + sl_start - min_x,
|
||||
0,
|
||||
cover_full);
|
||||
} //if(sl_len)
|
||||
} //if(num_styles == 1) ... else
|
||||
} //while((num_styles = ras.sweep_styles()) > 0)
|
||||
} //if(ras.rewind_scanlines())
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -20,102 +20,74 @@
|
|||
#ifndef AGG_RENDERING_BUFFER_INCLUDED
|
||||
#define AGG_RENDERING_BUFFER_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//==========================================================row_ptr_cache
|
||||
template<class T> class row_ptr_cache
|
||||
//===========================================================row_accessor
|
||||
template<class T> class row_accessor
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
struct row_data
|
||||
{
|
||||
int x1, x2;
|
||||
const int8u* ptr;
|
||||
row_data() {}
|
||||
row_data(int x1_, int x2_, const int8u* ptr_) :
|
||||
x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
typedef const_row_info<T> row_data;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
~row_ptr_cache()
|
||||
{
|
||||
delete [] m_rows;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
row_ptr_cache() :
|
||||
row_accessor() :
|
||||
m_buf(0),
|
||||
m_rows(0),
|
||||
m_start(0),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0),
|
||||
m_max_height(0)
|
||||
m_stride(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
|
||||
row_accessor(T* buf, unsigned width, unsigned height, int stride) :
|
||||
m_buf(0),
|
||||
m_rows(0),
|
||||
m_start(0),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0),
|
||||
m_max_height(0)
|
||||
m_stride(0)
|
||||
{
|
||||
attach(buf, width, height, stride);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void attach(T* buf, unsigned width, unsigned height, int stride)
|
||||
{
|
||||
m_buf = buf;
|
||||
m_buf = m_start = buf;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_stride = stride;
|
||||
if(height > m_max_height)
|
||||
{
|
||||
delete [] m_rows;
|
||||
m_rows = new T* [m_max_height = height];
|
||||
}
|
||||
|
||||
T* row_ptr = m_buf;
|
||||
|
||||
if(stride < 0)
|
||||
{
|
||||
row_ptr = m_buf - (height - 1) * stride;
|
||||
}
|
||||
|
||||
T** rows = m_rows;
|
||||
|
||||
while(height--)
|
||||
{
|
||||
*rows++ = row_ptr;
|
||||
row_ptr += stride;
|
||||
m_start = m_buf - int(height - 1) * stride;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
T* buf() { return m_buf; }
|
||||
const T* buf() const { return m_buf; }
|
||||
unsigned width() const { return m_width; }
|
||||
unsigned height() const { return m_height; }
|
||||
int stride() const { return m_stride; }
|
||||
unsigned stride_abs() const
|
||||
AGG_INLINE T* buf() { return m_buf; }
|
||||
AGG_INLINE const T* buf() const { return m_buf; }
|
||||
AGG_INLINE unsigned width() const { return m_width; }
|
||||
AGG_INLINE unsigned height() const { return m_height; }
|
||||
AGG_INLINE int stride() const { return m_stride; }
|
||||
AGG_INLINE unsigned stride_abs() const
|
||||
{
|
||||
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
T* row_ptr(int, int y, unsigned) { return m_rows[y]; }
|
||||
T* row_ptr(int y) { return m_rows[y]; }
|
||||
const T* row_ptr(int y) const { return m_rows[y]; }
|
||||
row_data row (int y) const { return row_data(0, m_width-1, m_rows[y]); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
T const* const* rows() const { return m_rows; }
|
||||
AGG_INLINE T* row_ptr(int, int y, unsigned)
|
||||
{
|
||||
return m_start + y * m_stride;
|
||||
}
|
||||
AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; }
|
||||
AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
|
||||
AGG_INLINE row_data row (int y) const
|
||||
{
|
||||
return row_data(0, m_width-1, row_ptr(y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf>
|
||||
|
@ -154,27 +126,173 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Prohibit copying
|
||||
row_ptr_cache(const row_ptr_cache<T>&);
|
||||
const row_ptr_cache<T>& operator = (const row_ptr_cache<T>&);
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
T* m_buf; // Pointer to renrdering buffer
|
||||
T** m_rows; // Pointers to each row of the buffer
|
||||
T* m_start; // Pointer to first pixel depending on stride
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
int m_stride; // Number of bytes per row. Can be < 0
|
||||
unsigned m_max_height; // The maximal height (currently allocated)
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================row_ptr_cache
|
||||
template<class T> class row_ptr_cache
|
||||
{
|
||||
public:
|
||||
typedef const_row_info<T> row_data;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
row_ptr_cache() :
|
||||
m_buf(0),
|
||||
m_rows(),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
|
||||
m_buf(0),
|
||||
m_rows(),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0)
|
||||
{
|
||||
attach(buf, width, height, stride);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void attach(T* buf, unsigned width, unsigned height, int stride)
|
||||
{
|
||||
m_buf = buf;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_stride = stride;
|
||||
if(height > m_rows.size())
|
||||
{
|
||||
m_rows.resize(height);
|
||||
}
|
||||
|
||||
T* row_ptr = m_buf;
|
||||
|
||||
if(stride < 0)
|
||||
{
|
||||
row_ptr = m_buf - int(height - 1) * stride;
|
||||
}
|
||||
|
||||
T** rows = &m_rows[0];
|
||||
|
||||
while(height--)
|
||||
{
|
||||
*rows++ = row_ptr;
|
||||
row_ptr += stride;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE T* buf() { return m_buf; }
|
||||
AGG_INLINE const T* buf() const { return m_buf; }
|
||||
AGG_INLINE unsigned width() const { return m_width; }
|
||||
AGG_INLINE unsigned height() const { return m_height; }
|
||||
AGG_INLINE int stride() const { return m_stride; }
|
||||
AGG_INLINE unsigned stride_abs() const
|
||||
{
|
||||
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE T* row_ptr(int, int y, unsigned)
|
||||
{
|
||||
return m_rows[y];
|
||||
}
|
||||
AGG_INLINE T* row_ptr(int y) { return m_rows[y]; }
|
||||
AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
|
||||
AGG_INLINE row_data row (int y) const
|
||||
{
|
||||
return row_data(0, m_width-1, m_rows[y]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
T const* const* rows() const { return &m_rows[0]; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf>
|
||||
void copy_from(const RenBuf& src)
|
||||
{
|
||||
unsigned h = height();
|
||||
if(src.height() < h) h = src.height();
|
||||
|
||||
unsigned l = stride_abs();
|
||||
if(src.stride_abs() < l) l = src.stride_abs();
|
||||
|
||||
l *= sizeof(T);
|
||||
|
||||
unsigned y;
|
||||
unsigned w = width();
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(T value)
|
||||
{
|
||||
unsigned y;
|
||||
unsigned w = width();
|
||||
unsigned stride = stride_abs();
|
||||
for(y = 0; y < height(); y++)
|
||||
{
|
||||
T* p = row_ptr(0, y, w);
|
||||
unsigned x;
|
||||
for(x = 0; x < stride; x++)
|
||||
{
|
||||
*p++ = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
T* m_buf; // Pointer to renrdering buffer
|
||||
pod_array<T*> m_rows; // Pointers to each row of the buffer
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
int m_stride; // Number of bytes per row. Can be < 0
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================================rendering_buffer
|
||||
typedef row_ptr_cache<int8u> rendering_buffer;
|
||||
//
|
||||
// The definition of the main type for accessing the rows in the frame
|
||||
// buffer. It provides functionality to navigate to the rows in a
|
||||
// rectangular matrix, from top to bottom or from bottom to top depending
|
||||
// on stride.
|
||||
//
|
||||
// row_accessor is cheap to create/destroy, but performs one multiplication
|
||||
// when calling row_ptr().
|
||||
//
|
||||
// row_ptr_cache creates an array of pointers to rows, so, the access
|
||||
// via row_ptr() may be faster. But it requires memory allocation
|
||||
// when creating. For example, on typical Intel Pentium hardware
|
||||
// row_ptr_cache speeds span_image_filter_rgb_nn up to 10%
|
||||
//
|
||||
// It's used only in short hand typedefs like pixfmt_rgba32 and can be
|
||||
// redefined in agg_config.h
|
||||
// In real applications you can use both, depending on your needs
|
||||
//------------------------------------------------------------------------
|
||||
#ifdef AGG_RENDERING_BUFFER
|
||||
typedef AGG_RENDERING_BUFFER rendering_buffer;
|
||||
#else
|
||||
// typedef row_ptr_cache<int8u> rendering_buffer;
|
||||
typedef row_accessor<int8u> rendering_buffer;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
|
||||
#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
@ -36,12 +35,7 @@ namespace agg
|
|||
class rendering_buffer_dynarow
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------
|
||||
struct row_data
|
||||
{
|
||||
int x1, x2;
|
||||
const int8u* ptr;
|
||||
};
|
||||
typedef row_info<int8u> row_data;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
~rendering_buffer_dynarow()
|
||||
|
@ -51,9 +45,10 @@ namespace agg
|
|||
|
||||
//-------------------------------------------------------------------
|
||||
rendering_buffer_dynarow() :
|
||||
m_rows(0),
|
||||
m_rows(),
|
||||
m_width(0),
|
||||
m_height(0)
|
||||
m_height(0),
|
||||
m_byte_width(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -61,12 +56,12 @@ namespace agg
|
|||
//--------------------------------------------------------------------
|
||||
rendering_buffer_dynarow(unsigned width, unsigned height,
|
||||
unsigned byte_width) :
|
||||
m_rows(new row_data[height]),
|
||||
m_rows(height),
|
||||
m_width(width),
|
||||
m_height(height),
|
||||
m_byte_width(byte_width)
|
||||
{
|
||||
memset(m_rows, 0, sizeof(row_data) * height);
|
||||
memset(&m_rows[0], 0, sizeof(row_data) * height);
|
||||
}
|
||||
|
||||
// Allocate and clear the buffer
|
||||
|
@ -74,16 +69,17 @@ namespace agg
|
|||
void init(unsigned width, unsigned height, unsigned byte_width)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_height; ++i) delete [] (int8u*)m_rows[i].ptr;
|
||||
delete [] m_rows;
|
||||
m_rows = 0;
|
||||
for(i = 0; i < m_height; ++i)
|
||||
{
|
||||
pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
|
||||
}
|
||||
if(width && height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_byte_width = byte_width;
|
||||
m_rows = new row_data[height];
|
||||
memset(m_rows, 0, sizeof(row_data) * height);
|
||||
m_rows.resize(height);
|
||||
memset(&m_rows[0], 0, sizeof(row_data) * height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +93,7 @@ namespace agg
|
|||
//--------------------------------------------------------------------
|
||||
int8u* row_ptr(int x, int y, unsigned len)
|
||||
{
|
||||
row_data* r = m_rows + y;
|
||||
row_data* r = &m_rows[y];
|
||||
int x2 = x + len - 1;
|
||||
if(r->ptr)
|
||||
{
|
||||
|
@ -106,7 +102,7 @@ namespace agg
|
|||
}
|
||||
else
|
||||
{
|
||||
int8u* p = new int8u [m_byte_width];
|
||||
int8u* p = pod_allocator<int8u>::allocate(m_byte_width);
|
||||
r->ptr = p;
|
||||
r->x1 = x;
|
||||
r->x2 = x2;
|
||||
|
@ -128,7 +124,7 @@ namespace agg
|
|||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
row_data* m_rows; // Pointers to each row of the buffer
|
||||
pod_array<row_data> m_rows; // Pointers to each row of the buffer
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
unsigned m_byte_width; // Width in bytes
|
||||
|
|
|
@ -54,15 +54,9 @@ namespace agg
|
|||
typedef const span* const_iterator;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline_bin()
|
||||
{
|
||||
delete [] m_spans;
|
||||
}
|
||||
|
||||
scanline_bin() :
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_spans(0),
|
||||
m_spans(),
|
||||
m_cur_span(0)
|
||||
{
|
||||
}
|
||||
|
@ -71,14 +65,12 @@ namespace agg
|
|||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_max_len)
|
||||
if(max_len > m_spans.size())
|
||||
{
|
||||
delete [] m_spans;
|
||||
m_spans = new span [max_len];
|
||||
m_max_len = max_len;
|
||||
m_spans.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = m_spans;
|
||||
m_cur_span = &m_spans[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -129,22 +121,21 @@ namespace agg
|
|||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = m_spans;
|
||||
m_cur_span = &m_spans[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||
const_iterator begin() const { return m_spans + 1; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
|
||||
const_iterator begin() const { return &m_spans[1]; }
|
||||
|
||||
private:
|
||||
scanline_bin(const scanline_bin&);
|
||||
const scanline_bin operator = (const scanline_bin&);
|
||||
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
span* m_spans;
|
||||
pod_array<span> m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
|
|
@ -57,19 +57,11 @@ namespace agg
|
|||
typedef span* iterator;
|
||||
typedef const span* const_iterator;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline_p8()
|
||||
{
|
||||
delete [] m_spans;
|
||||
delete [] m_covers;
|
||||
}
|
||||
|
||||
scanline_p8() :
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(0),
|
||||
m_covers(),
|
||||
m_cover_ptr(0),
|
||||
m_spans(0),
|
||||
m_spans(),
|
||||
m_cur_span(0)
|
||||
{
|
||||
}
|
||||
|
@ -78,17 +70,14 @@ namespace agg
|
|||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_max_len)
|
||||
if(max_len > m_spans.size())
|
||||
{
|
||||
delete [] m_spans;
|
||||
delete [] m_covers;
|
||||
m_covers = new cover_type [max_len];
|
||||
m_spans = new span [max_len];
|
||||
m_max_len = max_len;
|
||||
m_spans.resize(max_len);
|
||||
m_covers.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = m_covers;
|
||||
m_cur_span = m_spans;
|
||||
m_cover_ptr = &m_covers[0];
|
||||
m_cur_span = &m_spans[0];
|
||||
m_cur_span->len = 0;
|
||||
}
|
||||
|
||||
|
@ -160,26 +149,25 @@ namespace agg
|
|||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = m_covers;
|
||||
m_cur_span = m_spans;
|
||||
m_cover_ptr = &m_covers[0];
|
||||
m_cur_span = &m_spans[0];
|
||||
m_cur_span->len = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||
const_iterator begin() const { return m_spans + 1; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
|
||||
const_iterator begin() const { return &m_spans[1]; }
|
||||
|
||||
private:
|
||||
scanline_p8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
cover_type* m_covers;
|
||||
pod_array<cover_type> m_covers;
|
||||
cover_type* m_cover_ptr;
|
||||
span* m_spans;
|
||||
pod_array<span> m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
@ -231,15 +219,10 @@ namespace agg
|
|||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline32_p8()
|
||||
{
|
||||
delete [] m_covers;
|
||||
}
|
||||
|
||||
scanline32_p8() :
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(0),
|
||||
m_covers(),
|
||||
m_cover_ptr(0)
|
||||
{
|
||||
}
|
||||
|
@ -248,14 +231,12 @@ namespace agg
|
|||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_max_len)
|
||||
if(max_len > m_covers.size())
|
||||
{
|
||||
delete [] m_covers;
|
||||
m_covers = new cover_type[max_len];
|
||||
m_max_len = max_len;
|
||||
m_covers.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = m_covers;
|
||||
m_cover_ptr = &m_covers[0];
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
|
@ -319,7 +300,7 @@ namespace agg
|
|||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = m_covers;
|
||||
m_cover_ptr = &m_covers[0];
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
|
@ -335,7 +316,7 @@ namespace agg
|
|||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
cover_type* m_covers;
|
||||
pod_array<cover_type> m_covers;
|
||||
cover_type* m_cover_ptr;
|
||||
span_array_type m_spans;
|
||||
};
|
||||
|
|
|
@ -83,7 +83,8 @@ namespace agg
|
|||
int i;
|
||||
for(i = m_extra_storage.size()-1; i >= 0; --i)
|
||||
{
|
||||
delete [] m_extra_storage[(unsigned)i].ptr;
|
||||
pod_allocator<T>::deallocate(m_extra_storage[i].ptr,
|
||||
m_extra_storage[i].len);
|
||||
}
|
||||
m_extra_storage.remove_all();
|
||||
m_cells.remove_all();
|
||||
|
@ -101,7 +102,7 @@ namespace agg
|
|||
}
|
||||
extra_span s;
|
||||
s.len = num_cells;
|
||||
s.ptr = new T [num_cells];
|
||||
s.ptr = pod_allocator<T>::allocate(num_cells);
|
||||
memcpy(s.ptr, cells, sizeof(T) * num_cells);
|
||||
m_extra_storage.add(s);
|
||||
return -int(m_extra_storage.size());
|
||||
|
@ -142,7 +143,7 @@ namespace agg
|
|||
const extra_span& src = v.m_extra_storage[i];
|
||||
extra_span dst;
|
||||
dst.len = src.len;
|
||||
dst.ptr = new T [dst.len];
|
||||
dst.ptr = pod_allocator<T>::allocate(dst.len);
|
||||
memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
|
||||
m_extra_storage.add(dst);
|
||||
}
|
||||
|
|
|
@ -125,18 +125,9 @@ namespace agg
|
|||
typedef const span* const_iterator;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline_u8()
|
||||
{
|
||||
delete [] m_spans;
|
||||
delete [] m_covers;
|
||||
}
|
||||
|
||||
scanline_u8() :
|
||||
m_min_x(0),
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(0),
|
||||
m_spans(0),
|
||||
m_cur_span(0)
|
||||
{}
|
||||
|
||||
|
@ -144,17 +135,14 @@ namespace agg
|
|||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 2;
|
||||
if(max_len > m_max_len)
|
||||
if(max_len > m_spans.size())
|
||||
{
|
||||
delete [] m_spans;
|
||||
delete [] m_covers;
|
||||
m_covers = new cover_type [max_len];
|
||||
m_spans = new span [max_len];
|
||||
m_max_len = max_len;
|
||||
m_spans.resize(max_len);
|
||||
m_covers.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_min_x = min_x;
|
||||
m_cur_span = m_spans;
|
||||
m_cur_span = &m_spans[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -171,7 +159,7 @@ namespace agg
|
|||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = 1;
|
||||
m_cur_span->covers = m_covers + x;
|
||||
m_cur_span->covers = &m_covers[x];
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
@ -180,7 +168,7 @@ namespace agg
|
|||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memcpy(m_covers + x, covers, len * sizeof(cover_type));
|
||||
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len += (coord_type)len;
|
||||
|
@ -190,7 +178,7 @@ namespace agg
|
|||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = (coord_type)len;
|
||||
m_cur_span->covers = m_covers + x;
|
||||
m_cur_span->covers = &m_covers[x];
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
@ -199,7 +187,7 @@ namespace agg
|
|||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memset(m_covers + x, cover, len);
|
||||
memset(&m_covers[x], cover, len);
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len += (coord_type)len;
|
||||
|
@ -209,7 +197,7 @@ namespace agg
|
|||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = (coord_type)len;
|
||||
m_cur_span->covers = m_covers + x;
|
||||
m_cur_span->covers = &m_covers[x];
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
@ -224,14 +212,14 @@ namespace agg
|
|||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = m_spans;
|
||||
m_cur_span = &m_spans[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||
const_iterator begin() const { return m_spans + 1; }
|
||||
iterator begin() { return m_spans + 1; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
|
||||
const_iterator begin() const { return &m_spans[1]; }
|
||||
iterator begin() { return &m_spans[1]; }
|
||||
|
||||
private:
|
||||
scanline_u8(const self_type&);
|
||||
|
@ -239,11 +227,10 @@ namespace agg
|
|||
|
||||
private:
|
||||
int m_min_x;
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
cover_type* m_covers;
|
||||
span* m_spans;
|
||||
pod_array<cover_type> m_covers;
|
||||
pod_array<span> m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
@ -357,27 +344,19 @@ namespace agg
|
|||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~scanline32_u8()
|
||||
{
|
||||
delete [] m_covers;
|
||||
}
|
||||
|
||||
scanline32_u8() :
|
||||
m_min_x(0),
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(0)
|
||||
m_covers()
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 2;
|
||||
if(max_len > m_max_len)
|
||||
if(max_len > m_covers.size())
|
||||
{
|
||||
delete [] m_covers;
|
||||
m_covers = new cover_type [max_len];
|
||||
m_max_len = max_len;
|
||||
m_covers.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_min_x = min_x;
|
||||
|
@ -395,7 +374,7 @@ namespace agg
|
|||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x), 1, m_covers + x));
|
||||
m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
@ -404,14 +383,16 @@ namespace agg
|
|||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memcpy(m_covers + x, covers, len * sizeof(cover_type));
|
||||
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x), coord_type(len), m_covers + x));
|
||||
m_spans.add(span(coord_type(x + m_min_x),
|
||||
coord_type(len),
|
||||
&m_covers[x]));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
@ -420,14 +401,16 @@ namespace agg
|
|||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memset(m_covers + x, cover, len);
|
||||
memset(&m_covers[x], cover, len);
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x), coord_type(len), m_covers + x));
|
||||
m_spans.add(span(coord_type(x + m_min_x),
|
||||
coord_type(len),
|
||||
&m_covers[x]));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
@ -457,10 +440,9 @@ namespace agg
|
|||
|
||||
private:
|
||||
int m_min_x;
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
cover_type* m_covers;
|
||||
pod_array<cover_type> m_covers;
|
||||
span_array_type m_spans;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#ifndef AGG_SPAN_ALLOCATOR_INCLUDED
|
||||
#define AGG_SPAN_ALLOCATOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
@ -26,45 +26,25 @@ namespace agg
|
|||
public:
|
||||
typedef ColorT color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~span_allocator()
|
||||
{
|
||||
delete [] m_span;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_allocator() :
|
||||
m_max_span_len(0),
|
||||
m_span(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type* allocate(unsigned span_len)
|
||||
{
|
||||
if(span_len > m_max_span_len)
|
||||
if(span_len > m_span.size())
|
||||
{
|
||||
// To reduce the number of reallocs we align the
|
||||
// span_len to 256 color elements.
|
||||
// Well, I just like this number and it looks reasonable.
|
||||
//-----------------------
|
||||
delete [] m_span;
|
||||
span_len = ((span_len + 255) >> 8) << 8;
|
||||
m_span = new color_type[m_max_span_len = span_len];
|
||||
m_span.resize(((span_len + 255) >> 8) << 8);
|
||||
}
|
||||
return m_span;
|
||||
return &m_span[0];
|
||||
}
|
||||
|
||||
AGG_INLINE color_type* span() { return m_span; }
|
||||
AGG_INLINE unsigned max_span_len() const { return m_max_span_len; }
|
||||
AGG_INLINE color_type* span() { return &m_span[0]; }
|
||||
AGG_INLINE unsigned max_span_len() const { return m_span.size(); }
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
span_allocator(const span_allocator<ColorT>&);
|
||||
const span_allocator<ColorT>& operator = (const span_allocator<ColorT>&);
|
||||
|
||||
unsigned m_max_span_len;
|
||||
color_type* m_span;
|
||||
pod_array<color_type> m_span;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@ namespace agg
|
|||
span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) :
|
||||
m_span_gen(&span_gen), m_span_cnv(&span_cnv) {}
|
||||
|
||||
void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; }
|
||||
void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
|
|
|
@ -146,6 +146,10 @@ namespace agg
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================gradient_circle
|
||||
class gradient_circle
|
||||
{
|
||||
|
@ -168,7 +172,6 @@ namespace agg
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//========================================================gradient_radial_d
|
||||
class gradient_radial_d
|
||||
{
|
||||
|
@ -179,25 +182,24 @@ namespace agg
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//====================================================gradient_radial_focus
|
||||
class gradient_radial_focus
|
||||
{
|
||||
public:
|
||||
//---------------------------------------------------------------------
|
||||
gradient_radial_focus() :
|
||||
m_radius(100 * gradient_subpixel_scale),
|
||||
m_focus_x(0),
|
||||
m_focus_y(0)
|
||||
m_r(100 * gradient_subpixel_scale),
|
||||
m_fx(0),
|
||||
m_fy(0)
|
||||
{
|
||||
update_values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
gradient_radial_focus(double r, double fx, double fy) :
|
||||
m_radius (iround(r * gradient_subpixel_scale)),
|
||||
m_focus_x(iround(fx * gradient_subpixel_scale)),
|
||||
m_focus_y(iround(fy * gradient_subpixel_scale))
|
||||
m_r (iround(r * gradient_subpixel_scale)),
|
||||
m_fx(iround(fx * gradient_subpixel_scale)),
|
||||
m_fy(iround(fy * gradient_subpixel_scale))
|
||||
{
|
||||
update_values();
|
||||
}
|
||||
|
@ -205,111 +207,62 @@ namespace agg
|
|||
//---------------------------------------------------------------------
|
||||
void init(double r, double fx, double fy)
|
||||
{
|
||||
m_radius = iround(r * gradient_subpixel_scale);
|
||||
m_focus_x = iround(fx * gradient_subpixel_scale);
|
||||
m_focus_y = iround(fy * gradient_subpixel_scale);
|
||||
m_r = iround(r * gradient_subpixel_scale);
|
||||
m_fx = iround(fx * gradient_subpixel_scale);
|
||||
m_fy = iround(fy * gradient_subpixel_scale);
|
||||
update_values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
double radius() const { return double(m_radius) / gradient_subpixel_scale; }
|
||||
double focus_x() const { return double(m_focus_x) / gradient_subpixel_scale; }
|
||||
double focus_y() const { return double(m_focus_y) / gradient_subpixel_scale; }
|
||||
double radius() const { return double(m_r) / gradient_subpixel_scale; }
|
||||
double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
|
||||
double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
int calculate(int x, int y, int) const
|
||||
{
|
||||
double solution_x;
|
||||
double solution_y;
|
||||
|
||||
// Special case to avoid divide by zero or very near zero
|
||||
//---------------------------------
|
||||
if(x == iround(m_focus_x))
|
||||
{
|
||||
solution_x = m_focus_x;
|
||||
solution_y = 0.0;
|
||||
solution_y += (y > m_focus_y) ? m_trivial : -m_trivial;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slope of the focus-current line
|
||||
//-------------------------------
|
||||
double slope = double(y - m_focus_y) / double(x - m_focus_x);
|
||||
|
||||
// y-intercept of that same line
|
||||
//--------------------------------
|
||||
double yint = double(y) - (slope * x);
|
||||
|
||||
// Use the classical quadratic formula to calculate
|
||||
// the intersection point
|
||||
//--------------------------------
|
||||
double a = (slope * slope) + 1;
|
||||
double b = 2 * slope * yint;
|
||||
double c = yint * yint - m_radius2;
|
||||
double det = sqrt((b * b) - (4.0 * a * c));
|
||||
solution_x = -b;
|
||||
|
||||
// Choose the positive or negative root depending
|
||||
// on where the X coord lies with respect to the focus.
|
||||
solution_x += (x < m_focus_x) ? -det : det;
|
||||
solution_x /= 2.0 * a;
|
||||
|
||||
// Calculating of Y is trivial
|
||||
solution_y = (slope * solution_x) + yint;
|
||||
}
|
||||
|
||||
// Calculate the percentage (0...1) of the current point along the
|
||||
// focus-circumference line and return the normalized (0...d) value
|
||||
//-------------------------------
|
||||
solution_x -= double(m_focus_x);
|
||||
solution_y -= double(m_focus_y);
|
||||
double int_to_focus = solution_x * solution_x + solution_y * solution_y;
|
||||
double cur_to_focus = double(x - m_focus_x) * double(x - m_focus_x) +
|
||||
double(y - m_focus_y) * double(y - m_focus_y);
|
||||
|
||||
return iround(sqrt(cur_to_focus / int_to_focus) * m_radius);
|
||||
double dx = x - m_fx;
|
||||
double dy = y - m_fy;
|
||||
double d2 = dx * m_fy - dy * m_fx;
|
||||
double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
|
||||
return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul);
|
||||
}
|
||||
|
||||
private:
|
||||
//---------------------------------------------------------------------
|
||||
void update_values()
|
||||
{
|
||||
// For use in the quadratic equation
|
||||
//-------------------------------
|
||||
m_radius2 = double(m_radius) * double(m_radius);
|
||||
|
||||
double dist = sqrt(double(m_focus_x) * double(m_focus_x) +
|
||||
double(m_focus_y) * double(m_focus_y));
|
||||
|
||||
// Test if distance from focus to center is greater than the radius
|
||||
// For the sake of assurance factor restrict the point to be
|
||||
// no further than 99% of the radius.
|
||||
//-------------------------------
|
||||
double r = m_radius * 0.99;
|
||||
if(dist > r)
|
||||
// Calculate the invariant values. In case the focal center
|
||||
// lies exactly on the gradient circle the divisor degenerates
|
||||
// into zero. In this case we just move the focal center by
|
||||
// one subpixel unit possibly in the direction to the origin (0,0)
|
||||
// and calculate the values again.
|
||||
//-------------------------
|
||||
m_r2 = double(m_r) * double(m_r);
|
||||
m_fx2 = double(m_fx) * double(m_fx);
|
||||
m_fy2 = double(m_fy) * double(m_fy);
|
||||
double d = (m_r2 - (m_fx2 + m_fy2));
|
||||
if(d == 0)
|
||||
{
|
||||
// clamp focus to radius
|
||||
// x = r cos theta, y = r sin theta
|
||||
//------------------------
|
||||
double a = atan2(double(m_focus_y), double(m_focus_x));
|
||||
m_focus_x = iround(r * cos(a));
|
||||
m_focus_y = iround(r * sin(a));
|
||||
if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; }
|
||||
if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; }
|
||||
m_fx2 = double(m_fx) * double(m_fx);
|
||||
m_fy2 = double(m_fy) * double(m_fy);
|
||||
d = (m_r2 - (m_fx2 + m_fy2));
|
||||
}
|
||||
m_mul = m_r / d;
|
||||
}
|
||||
|
||||
// Calculate the solution to be used in the case where x == focus_x
|
||||
//------------------------------
|
||||
m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x));
|
||||
}
|
||||
|
||||
int m_radius;
|
||||
int m_focus_x;
|
||||
int m_focus_y;
|
||||
double m_radius2;
|
||||
double m_trivial;
|
||||
int m_r;
|
||||
int m_fx;
|
||||
int m_fy;
|
||||
double m_r2;
|
||||
double m_fx2;
|
||||
double m_fy2;
|
||||
double m_mul;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==============================================================gradient_x
|
||||
class gradient_x
|
||||
{
|
||||
|
@ -325,7 +278,6 @@ namespace agg
|
|||
static int calculate(int, int y, int) { return y; }
|
||||
};
|
||||
|
||||
|
||||
//========================================================gradient_diamond
|
||||
class gradient_diamond
|
||||
{
|
||||
|
@ -338,7 +290,6 @@ namespace agg
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================gradient_xy
|
||||
class gradient_xy
|
||||
{
|
||||
|
@ -349,7 +300,6 @@ namespace agg
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//========================================================gradient_sqrt_xy
|
||||
class gradient_sqrt_xy
|
||||
{
|
||||
|
@ -360,7 +310,6 @@ namespace agg
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gradient_conic
|
||||
class gradient_conic
|
||||
{
|
||||
|
@ -371,7 +320,6 @@ namespace agg
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//=================================================gradient_repeat_adaptor
|
||||
template<class GradientF> class gradient_repeat_adaptor
|
||||
{
|
||||
|
@ -390,7 +338,6 @@ namespace agg
|
|||
const GradientF* m_gradient;
|
||||
};
|
||||
|
||||
|
||||
//================================================gradient_reflect_adaptor
|
||||
template<class GradientF> class gradient_reflect_adaptor
|
||||
{
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace agg
|
|||
m_dx_int(image_subpixel_scale / 2),
|
||||
m_dy_int(image_subpixel_scale / 2)
|
||||
{}
|
||||
void attach(source_type& v) { m_src = &v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
source_type& source() { return *m_src; }
|
||||
|
@ -57,7 +58,6 @@ namespace agg
|
|||
double filter_dy_dbl() const { return m_dy_dbl; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void set_source(source_type& v) { m_src = &v; }
|
||||
void interpolator(interpolator_type& v) { m_interpolator = &v; }
|
||||
void filter(const image_filter_lut& v) { m_filter = &v; }
|
||||
void filter_offset(double dx, double dy)
|
||||
|
@ -136,34 +136,30 @@ namespace agg
|
|||
|
||||
base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
|
||||
|
||||
m_rx = image_subpixel_scale;
|
||||
m_ry = image_subpixel_scale;
|
||||
m_rx_inv = image_subpixel_scale;
|
||||
m_ry_inv = image_subpixel_scale;
|
||||
|
||||
scale_x *= m_blur_x;
|
||||
scale_y *= m_blur_y;
|
||||
|
||||
if(scale_x * scale_y > m_scale_limit)
|
||||
{
|
||||
scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
|
||||
scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
|
||||
}
|
||||
|
||||
if(scale_x > 1.0001)
|
||||
{
|
||||
if(scale_x < 1) scale_x = 1;
|
||||
if(scale_y < 1) scale_y = 1;
|
||||
|
||||
if(scale_x > m_scale_limit) scale_x = m_scale_limit;
|
||||
if(scale_y > m_scale_limit) scale_y = m_scale_limit;
|
||||
|
||||
scale_x *= m_blur_x;
|
||||
scale_y *= m_blur_y;
|
||||
|
||||
if(scale_x < 1) scale_x = 1;
|
||||
if(scale_y < 1) scale_y = 1;
|
||||
|
||||
m_rx = uround( scale_x * double(image_subpixel_scale));
|
||||
m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale));
|
||||
}
|
||||
|
||||
if(scale_y > 1.0001)
|
||||
{
|
||||
if(scale_y > m_scale_limit) scale_y = m_scale_limit;
|
||||
m_ry = uround( scale_y * double(image_subpixel_scale));
|
||||
m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_rx;
|
||||
|
@ -219,6 +215,24 @@ namespace agg
|
|||
m_blur_y = uround(v * double(image_subpixel_scale)); }
|
||||
|
||||
protected:
|
||||
AGG_INLINE void adjust_scale(int* rx, int* ry)
|
||||
{
|
||||
if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
|
||||
if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
|
||||
if(*rx > image_subpixel_scale * m_scale_limit)
|
||||
{
|
||||
*rx = image_subpixel_scale * m_scale_limit;
|
||||
}
|
||||
if(*ry > image_subpixel_scale * m_scale_limit)
|
||||
{
|
||||
*ry = image_subpixel_scale * m_scale_limit;
|
||||
}
|
||||
*rx = (*rx * m_blur_x) >> image_subpixel_shift;
|
||||
*ry = (*ry * m_blur_y) >> image_subpixel_shift;
|
||||
if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
|
||||
if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
|
||||
}
|
||||
|
||||
int m_scale_limit;
|
||||
int m_blur_x;
|
||||
int m_blur_y;
|
||||
|
|
|
@ -676,35 +676,10 @@ namespace agg
|
|||
int ry_inv = image_subpixel_scale;
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
base_type::interpolator().local_scale(&rx, &ry);
|
||||
base_type::adjust_scale(&rx, &ry);
|
||||
|
||||
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
|
||||
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
|
||||
|
||||
if(rx < image_subpixel_scale)
|
||||
{
|
||||
rx = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rx > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
rx = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
|
||||
}
|
||||
|
||||
if(ry < image_subpixel_scale)
|
||||
{
|
||||
ry = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ry > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
ry = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
|
||||
}
|
||||
|
||||
int radius_x = (diameter * rx) >> 1;
|
||||
int radius_y = (diameter * ry) >> 1;
|
||||
|
|
|
@ -808,35 +808,10 @@ namespace agg
|
|||
int ry_inv = image_subpixel_scale;
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
base_type::interpolator().local_scale(&rx, &ry);
|
||||
base_type::adjust_scale(&rx, &ry);
|
||||
|
||||
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
|
||||
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
|
||||
|
||||
if(rx < image_subpixel_scale)
|
||||
{
|
||||
rx = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rx > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
rx = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
|
||||
}
|
||||
|
||||
if(ry < image_subpixel_scale)
|
||||
{
|
||||
ry = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ry > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
ry = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
|
||||
}
|
||||
|
||||
int radius_x = (diameter * rx) >> 1;
|
||||
int radius_y = (diameter * ry) >> 1;
|
||||
|
|
|
@ -832,35 +832,10 @@ namespace agg
|
|||
int ry_inv = image_subpixel_scale;
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
base_type::interpolator().local_scale(&rx, &ry);
|
||||
base_type::adjust_scale(&rx, &ry);
|
||||
|
||||
rx = (rx * base_type::m_blur_x) >> image_subpixel_shift;
|
||||
ry = (ry * base_type::m_blur_y) >> image_subpixel_shift;
|
||||
|
||||
if(rx < image_subpixel_scale)
|
||||
{
|
||||
rx = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rx > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
rx = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
|
||||
}
|
||||
|
||||
if(ry < image_subpixel_scale)
|
||||
{
|
||||
ry = image_subpixel_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ry > image_subpixel_scale * base_type::m_scale_limit)
|
||||
{
|
||||
ry = image_subpixel_scale * base_type::m_scale_limit;
|
||||
}
|
||||
ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
|
||||
}
|
||||
|
||||
int radius_x = (diameter * rx) >> 1;
|
||||
int radius_y = (diameter * ry) >> 1;
|
||||
|
|
|
@ -50,9 +50,9 @@ namespace agg
|
|||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void attach(source_type& v) { m_src = &v; }
|
||||
source_type& source() { return *m_src; }
|
||||
const source_type& source() const { return *m_src; }
|
||||
void set_source(source_type& v) { m_src = &v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void offset_x(unsigned v) { m_offset_x = v; }
|
||||
|
|
|
@ -51,9 +51,9 @@ namespace agg
|
|||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void attach(source_type& v) { m_src = &v; }
|
||||
source_type& source() { return *m_src; }
|
||||
const source_type& source() const { return *m_src; }
|
||||
void set_source(source_type& v) { m_src = &v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void offset_x(unsigned v) { m_offset_x = v; }
|
||||
|
|
|
@ -50,9 +50,9 @@ namespace agg
|
|||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void attach(source_type& v) { m_src = &v; }
|
||||
source_type& source() { return *m_src; }
|
||||
const source_type& source() const { return *m_src; }
|
||||
void set_source(source_type& v) { m_src = &v; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void offset_x(unsigned v) { m_offset_x = v; }
|
||||
|
@ -75,7 +75,7 @@ namespace agg
|
|||
span->g = p[order_type::G];
|
||||
span->b = p[order_type::B];
|
||||
span->a = p[order_type::A];
|
||||
p = m_src->next_x();
|
||||
p = (const value_type*)m_src->next_x();
|
||||
++span;
|
||||
}
|
||||
while(--len);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
namespace agg
|
||||
{
|
||||
const double affine_epsilon = 1e-14; // About of precision of doubles
|
||||
const double affine_epsilon = 1e-14;
|
||||
|
||||
//============================================================trans_affine
|
||||
//
|
||||
|
@ -84,48 +84,58 @@ namespace agg
|
|||
// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate
|
||||
// m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)
|
||||
//----------------------------------------------------------------------
|
||||
class trans_affine
|
||||
struct trans_affine
|
||||
{
|
||||
public:
|
||||
double sx, shy, shx, sy, tx, ty;
|
||||
|
||||
//------------------------------------------ Construction
|
||||
// Construct an identity matrix - it does not transform anything
|
||||
// Identity matrix
|
||||
trans_affine() :
|
||||
m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(0.0)
|
||||
sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0)
|
||||
{}
|
||||
|
||||
// Construct a custom matrix. Usually used in derived classes
|
||||
trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) :
|
||||
m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5)
|
||||
// Custom matrix. Usually used in derived classes
|
||||
trans_affine(double v0, double v1, double v2,
|
||||
double v3, double v4, double v5) :
|
||||
sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5)
|
||||
{}
|
||||
|
||||
// Construct a matrix to transform a parallelogram to another one.
|
||||
trans_affine(const double* rect, const double* parl)
|
||||
{
|
||||
parl_to_parl(rect, parl);
|
||||
}
|
||||
// Custom matrix from m[6]
|
||||
explicit trans_affine(const double* m) :
|
||||
sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5])
|
||||
{}
|
||||
|
||||
// Construct a matrix to transform a rectangle to a parallelogram.
|
||||
// Rectangle to a parallelogram.
|
||||
trans_affine(double x1, double y1, double x2, double y2,
|
||||
const double* parl)
|
||||
{
|
||||
rect_to_parl(x1, y1, x2, y2, parl);
|
||||
}
|
||||
|
||||
// Construct a matrix to transform a parallelogram to a rectangle.
|
||||
// Parallelogram to a rectangle.
|
||||
trans_affine(const double* parl,
|
||||
double x1, double y1, double x2, double y2)
|
||||
{
|
||||
parl_to_rect(parl, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
// Arbitrary parallelogram transformation.
|
||||
trans_affine(const double* src, const double* dst)
|
||||
{
|
||||
parl_to_parl(src, dst);
|
||||
}
|
||||
|
||||
//---------------------------------- Parellelogram transformations
|
||||
// Calculate a matrix to transform a parallelogram to another one.
|
||||
// src and dst are pointers to arrays of three points
|
||||
// (double[6], x,y,...) that identify three corners of the
|
||||
// parallelograms assuming implicit fourth points.
|
||||
// There are also transformations rectangtle to parallelogram and
|
||||
// parellelogram to rectangle
|
||||
// transform a parallelogram to another one. Src and dst are
|
||||
// pointers to arrays of three points (double[6], x1,y1,...) that
|
||||
// identify three corners of the parallelograms assuming implicit
|
||||
// fourth point. The arguments are arrays of double[6] mapped
|
||||
// to x1,y1, x2,y2, x3,y3 where the coordinates are:
|
||||
// *-----------------*
|
||||
// / (x3,y3)/
|
||||
// / /
|
||||
// /(x1,y1) (x2,y2)/
|
||||
// *-----------------*
|
||||
const trans_affine& parl_to_parl(const double* src,
|
||||
const double* dst);
|
||||
|
||||
|
@ -139,9 +149,15 @@ namespace agg
|
|||
|
||||
|
||||
//------------------------------------------ Operations
|
||||
// Reset - actually load an identity matrix
|
||||
// Reset - load an identity matrix
|
||||
const trans_affine& reset();
|
||||
|
||||
// Direct transformations operations
|
||||
const trans_affine& translate(double x, double y);
|
||||
const trans_affine& rotate(double a);
|
||||
const trans_affine& scale(double s);
|
||||
const trans_affine& scale(double x, double y);
|
||||
|
||||
// Multiply matrix to another one
|
||||
const trans_affine& multiply(const trans_affine& m);
|
||||
|
||||
|
@ -169,38 +185,38 @@ namespace agg
|
|||
// Store matrix to an array [6] of double
|
||||
void store_to(double* m) const
|
||||
{
|
||||
*m++ = m0; *m++ = m1; *m++ = m2; *m++ = m3; *m++ = m4; *m++ = m5;
|
||||
*m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty;
|
||||
}
|
||||
|
||||
// Load matrix from an array [6] of double
|
||||
const trans_affine& load_from(const double* m)
|
||||
{
|
||||
m0 = *m++; m1 = *m++; m2 = *m++; m3 = *m++; m4 = *m++; m5 = *m++;
|
||||
sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------- Operators
|
||||
|
||||
// Multiply current matrix to another one
|
||||
// Multiply the matrix by another one
|
||||
const trans_affine& operator *= (const trans_affine& m)
|
||||
{
|
||||
return multiply(m);
|
||||
}
|
||||
|
||||
// Multiply current matrix to inverse of another one
|
||||
// Multiply the matrix by inverse of another one
|
||||
const trans_affine& operator /= (const trans_affine& m)
|
||||
{
|
||||
return multiply_inv(m);
|
||||
}
|
||||
|
||||
// Multiply current matrix to another one and return
|
||||
// Multiply the matrix by another one and return
|
||||
// the result in a separete matrix.
|
||||
trans_affine operator * (const trans_affine& m)
|
||||
{
|
||||
return trans_affine(*this).multiply(m);
|
||||
}
|
||||
|
||||
// Multiply current matrix to inverse of another one
|
||||
// Multiply the matrix by inverse of another one
|
||||
// and return the result in a separete matrix.
|
||||
trans_affine operator / (const trans_affine& m)
|
||||
{
|
||||
|
@ -227,22 +243,28 @@ namespace agg
|
|||
}
|
||||
|
||||
//-------------------------------------------- Transformations
|
||||
// Direct transformation x and y
|
||||
// Direct transformation of x and y
|
||||
void transform(double* x, double* y) const;
|
||||
|
||||
// Direct transformation x and y, 2x2 matrix only, no translation
|
||||
// Direct transformation of x and y, 2x2 matrix only, no translation
|
||||
void transform_2x2(double* x, double* y) const;
|
||||
|
||||
// Inverse transformation x and y. It works slower than the
|
||||
// direct transformation, so if the performance is critical
|
||||
// it's better to invert() the matrix and then use transform()
|
||||
// Inverse transformation of x and y. It works slower than the
|
||||
// direct transformation. For massive operations it's better to
|
||||
// invert() the matrix and then use direct transformations.
|
||||
void inverse_transform(double* x, double* y) const;
|
||||
|
||||
//-------------------------------------------- Auxiliary
|
||||
// Calculate the determinant of matrix
|
||||
double determinant() const
|
||||
{
|
||||
return 1.0 / (m0 * m3 - m1 * m2);
|
||||
return sx * sy - shy * shx;
|
||||
}
|
||||
|
||||
// Calculate the reciprocal of the determinant
|
||||
double determinant_reciprocal() const
|
||||
{
|
||||
return 1.0 / (sx * sy - shy * shx);
|
||||
}
|
||||
|
||||
// Get the average scale (by X and Y).
|
||||
|
@ -250,65 +272,109 @@ namespace agg
|
|||
// decomposinting curves into line segments.
|
||||
double scale() const;
|
||||
|
||||
// Check to see if the matrix is not degenerate
|
||||
bool is_valid(double epsilon = affine_epsilon) const;
|
||||
|
||||
// Check to see if it's an identity matrix
|
||||
bool is_identity(double epsilon = affine_epsilon) const;
|
||||
|
||||
// Check to see if two matrices are equal
|
||||
bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
|
||||
|
||||
// Determine the major parameters. Use carefully considering degenerate matrices
|
||||
// Determine the major parameters. Use with caution considering
|
||||
// possible degenerate cases.
|
||||
double rotation() const;
|
||||
void translation(double* dx, double* dy) const;
|
||||
void scaling(double* sx, double* sy) const;
|
||||
void scaling_abs(double* sx, double* sy) const
|
||||
{
|
||||
*sx = sqrt(m0*m0 + m2*m2);
|
||||
*sy = sqrt(m1*m1 + m3*m3);
|
||||
}
|
||||
|
||||
private:
|
||||
double m0;
|
||||
double m1;
|
||||
double m2;
|
||||
double m3;
|
||||
double m4;
|
||||
double m5;
|
||||
void scaling(double* x, double* y) const;
|
||||
void scaling_abs(double* x, double* y) const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_affine::transform(double* x, double* y) const
|
||||
{
|
||||
register double tx = *x;
|
||||
*x = tx * m0 + *y * m2 + m4;
|
||||
*y = tx * m1 + *y * m3 + m5;
|
||||
register double tmp = *x;
|
||||
*x = tmp * sx + *y * shx + tx;
|
||||
*y = tmp * shy + *y * sy + ty;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_affine::transform_2x2(double* x, double* y) const
|
||||
{
|
||||
register double tx = *x;
|
||||
*x = tx * m0 + *y * m2;
|
||||
*y = tx * m1 + *y * m3;
|
||||
register double tmp = *x;
|
||||
*x = tmp * sx + *y * shx;
|
||||
*y = tmp * shy + *y * sy;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_affine::inverse_transform(double* x, double* y) const
|
||||
{
|
||||
register double d = determinant();
|
||||
register double a = (*x - m4) * d;
|
||||
register double b = (*y - m5) * d;
|
||||
*x = a * m3 - b * m2;
|
||||
*y = b * m0 - a * m1;
|
||||
register double d = determinant_reciprocal();
|
||||
register double a = (*x - tx) * d;
|
||||
register double b = (*y - ty) * d;
|
||||
*x = a * sy - b * shx;
|
||||
*y = b * sx - a * shy;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline double trans_affine::scale() const
|
||||
{
|
||||
double x = 0.707106781 * m0 + 0.707106781 * m2;
|
||||
double y = 0.707106781 * m1 + 0.707106781 * m3;
|
||||
double x = 0.707106781 * sx + 0.707106781 * shx;
|
||||
double y = 0.707106781 * shy + 0.707106781 * sy;
|
||||
return sqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_affine& trans_affine::translate(double x, double y)
|
||||
{
|
||||
tx += x;
|
||||
ty += y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_affine& trans_affine::rotate(double a)
|
||||
{
|
||||
double ca = cos(a);
|
||||
double sa = sin(a);
|
||||
double t0 = sx * ca - shy * sa;
|
||||
double t2 = shx * ca - sy * sa;
|
||||
double t4 = tx * ca - ty * sa;
|
||||
shy = sx * sa + shy * ca;
|
||||
sy = shx * sa + sy * ca;
|
||||
ty = tx * sa + ty * ca;
|
||||
sx = t0;
|
||||
shx = t2;
|
||||
tx = t4;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_affine& trans_affine::scale(double x, double y)
|
||||
{
|
||||
double mm0 = x; // Possible hint for the optimizer
|
||||
double mm3 = y;
|
||||
sx *= mm0;
|
||||
shx *= mm0;
|
||||
tx *= mm0;
|
||||
shy *= mm3;
|
||||
sy *= mm3;
|
||||
ty *= mm3;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_affine& trans_affine::scale(double s)
|
||||
{
|
||||
double m = s; // Possible hint for the optimizer
|
||||
sx *= m;
|
||||
shx *= m;
|
||||
tx *= m;
|
||||
shy *= m;
|
||||
sy *= m;
|
||||
ty *= m;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
|
||||
{
|
||||
|
@ -321,8 +387,7 @@ namespace agg
|
|||
{
|
||||
trans_affine t = m;
|
||||
t.invert();
|
||||
multiply(t);
|
||||
return *this;
|
||||
return multiply(t);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -333,6 +398,16 @@ namespace agg
|
|||
return *this = t.multiply(*this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_affine::scaling_abs(double* x, double* y) const
|
||||
{
|
||||
// Used to calculate scaling coefficients in image resampling.
|
||||
// When there is considerable shear this method gives us much
|
||||
// better estimation than just sx, sy.
|
||||
*x = sqrt(sx * sx + shx * shx);
|
||||
*y = sqrt(shy * shy + sy * sy);
|
||||
}
|
||||
|
||||
//====================================================trans_affine_rotation
|
||||
// Rotation matrix. sin() and cos() are calculated twice for the same angle.
|
||||
// There's no harm because the performance of sin()/cos() is very good on all
|
||||
|
@ -347,12 +422,12 @@ namespace agg
|
|||
};
|
||||
|
||||
//====================================================trans_affine_scaling
|
||||
// Scaling matrix. sx, sy - scale coefficients by X and Y respectively
|
||||
// Scaling matrix. x, y - scale coefficients by X and Y respectively
|
||||
class trans_affine_scaling : public trans_affine
|
||||
{
|
||||
public:
|
||||
trans_affine_scaling(double sx, double sy) :
|
||||
trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0)
|
||||
trans_affine_scaling(double x, double y) :
|
||||
trans_affine(x, 0.0, 0.0, y, 0.0, 0.0)
|
||||
{}
|
||||
|
||||
trans_affine_scaling(double s) :
|
||||
|
@ -365,8 +440,8 @@ namespace agg
|
|||
class trans_affine_translation : public trans_affine
|
||||
{
|
||||
public:
|
||||
trans_affine_translation(double tx, double ty) :
|
||||
trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty)
|
||||
trans_affine_translation(double x, double y) :
|
||||
trans_affine(1.0, 0.0, 0.0, 1.0, x, y)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -375,8 +450,8 @@ namespace agg
|
|||
class trans_affine_skewing : public trans_affine
|
||||
{
|
||||
public:
|
||||
trans_affine_skewing(double sx, double sy) :
|
||||
trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0)
|
||||
trans_affine_skewing(double x, double y) :
|
||||
trans_affine(1.0, tan(y), tan(x), 1.0, 0.0, 0.0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -402,6 +477,40 @@ namespace agg
|
|||
};
|
||||
|
||||
|
||||
//============================================trans_affine_reflection_unit
|
||||
// Reflection matrix. Reflect coordinates across the line through
|
||||
// the origin containing the unit vector (ux, uy).
|
||||
// Contributed by John Horigan
|
||||
class trans_affine_reflection_unit : public trans_affine
|
||||
{
|
||||
public:
|
||||
trans_affine_reflection_unit(double ux, double uy) :
|
||||
trans_affine(2.0 * ux * ux - 1.0,
|
||||
2.0 * ux * uy,
|
||||
2.0 * ux * uy,
|
||||
2.0 * uy * uy - 1.0,
|
||||
0.0, 0.0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
//=================================================trans_affine_reflection
|
||||
// Reflection matrix. Reflect coordinates across the line through
|
||||
// the origin at the angle a or containing the non-unit vector (x, y).
|
||||
// Contributed by John Horigan
|
||||
class trans_affine_reflection : public trans_affine_reflection_unit
|
||||
{
|
||||
public:
|
||||
trans_affine_reflection(double a) :
|
||||
trans_affine_reflection_unit(cos(a), sin(a))
|
||||
{}
|
||||
|
||||
|
||||
trans_affine_reflection(double x, double y) :
|
||||
trans_affine_reflection_unit(x / sqrt(x * x + y * y), y / sqrt(x * x + y * y))
|
||||
{}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,125 +19,212 @@
|
|||
#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED
|
||||
#define AGG_TRANS_PERSPECTIVE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_simul_eq.h"
|
||||
#include "agg_trans_affine.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//=======================================================trans_perspective
|
||||
class trans_perspective
|
||||
struct trans_perspective
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
trans_perspective() : m_valid(false) {}
|
||||
double sx, shy, w0, shx, sy, w1, tx, ty, w2;
|
||||
|
||||
//------------------------------------------------------- Construction
|
||||
// Identity matrix
|
||||
trans_perspective() :
|
||||
sx (1), shy(0), w0(0),
|
||||
shx(0), sy (1), w1(0),
|
||||
tx (0), ty (0), w2(1) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Arbitrary quadrangle transformations
|
||||
trans_perspective(const double* src, const double* dst)
|
||||
{
|
||||
quad_to_quad(src, dst);
|
||||
}
|
||||
// Custom matrix
|
||||
trans_perspective(double v0, double v1, double v2,
|
||||
double v3, double v4, double v5,
|
||||
double v6, double v7, double v8) :
|
||||
sx (v0), shy(v1), w0(v2),
|
||||
shx(v3), sy (v4), w1(v5),
|
||||
tx (v6), ty (v7), w2(v8) {}
|
||||
|
||||
// Custom matrix from m[9]
|
||||
explicit trans_perspective(const double* m) :
|
||||
sx (m[0]), shy(m[1]), w0(m[2]),
|
||||
shx(m[3]), sy (m[4]), w1(m[5]),
|
||||
tx (m[6]), ty (m[7]), w2(m[8]) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Direct transformations
|
||||
// From affine
|
||||
explicit trans_perspective(const trans_affine& a) :
|
||||
sx (a.sx ), shy(a.shy), w0(0),
|
||||
shx(a.shx), sy (a.sy ), w1(0),
|
||||
tx (a.tx ), ty (a.ty ), w2(1) {}
|
||||
|
||||
// Rectangle to quadrilateral
|
||||
trans_perspective(double x1, double y1, double x2, double y2,
|
||||
const double* quad)
|
||||
{
|
||||
rect_to_quad(x1, y1, x2, y2, quad);
|
||||
}
|
||||
const double* quad);
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Reverse transformations
|
||||
// Quadrilateral to rectangle
|
||||
trans_perspective(const double* quad,
|
||||
double x1, double y1, double x2, double y2)
|
||||
double x1, double y1, double x2, double y2);
|
||||
|
||||
// Arbitrary quadrilateral transformations
|
||||
trans_perspective(const double* src, const double* dst);
|
||||
|
||||
//-------------------------------------- Quadrilateral transformations
|
||||
// The arguments are double[8] that are mapped to quadrilaterals:
|
||||
// x1,y1, x2,y2, x3,y3, x4,y4
|
||||
bool quad_to_quad(const double* qs, const double* qd);
|
||||
|
||||
bool rect_to_quad(double x1, double y1,
|
||||
double x2, double y2,
|
||||
const double* q);
|
||||
|
||||
bool quad_to_rect(const double* q,
|
||||
double x1, double y1,
|
||||
double x2, double y2);
|
||||
|
||||
// Map square (0,0,1,1) to the quadrilateral and vice versa
|
||||
bool square_to_quad(const double* q);
|
||||
bool quad_to_square(const double* q);
|
||||
|
||||
|
||||
//--------------------------------------------------------- Operations
|
||||
// Reset - load an identity matrix
|
||||
const trans_perspective& reset();
|
||||
|
||||
// Invert matrix. Returns false in degenerate case
|
||||
bool invert();
|
||||
|
||||
// Direct transformations operations
|
||||
const trans_perspective& translate(double x, double y);
|
||||
const trans_perspective& rotate(double a);
|
||||
const trans_perspective& scale(double s);
|
||||
const trans_perspective& scale(double x, double y);
|
||||
|
||||
// Multiply the matrix by another one
|
||||
const trans_perspective& multiply(const trans_perspective& m);
|
||||
|
||||
// Multiply "m" by "this" and assign the result to "this"
|
||||
const trans_perspective& premultiply(const trans_perspective& m);
|
||||
|
||||
// Multiply matrix to inverse of another one
|
||||
const trans_perspective& multiply_inv(const trans_perspective& m);
|
||||
|
||||
// Multiply inverse of "m" by "this" and assign the result to "this"
|
||||
const trans_perspective& premultiply_inv(const trans_perspective& m);
|
||||
|
||||
// Multiply the matrix by another one
|
||||
const trans_perspective& multiply(const trans_affine& m);
|
||||
|
||||
// Multiply "m" by "this" and assign the result to "this"
|
||||
const trans_perspective& premultiply(const trans_affine& m);
|
||||
|
||||
// Multiply the matrix by inverse of another one
|
||||
const trans_perspective& multiply_inv(const trans_affine& m);
|
||||
|
||||
// Multiply inverse of "m" by "this" and assign the result to "this"
|
||||
const trans_perspective& premultiply_inv(const trans_affine& m);
|
||||
|
||||
//--------------------------------------------------------- Load/Store
|
||||
void store_to(double* m) const;
|
||||
const trans_perspective& load_from(const double* m);
|
||||
|
||||
//---------------------------------------------------------- Operators
|
||||
// Multiply the matrix by another one
|
||||
const trans_perspective& operator *= (const trans_perspective& m)
|
||||
{
|
||||
quad_to_rect(quad, x1, y1, x2, y2);
|
||||
return multiply(m);
|
||||
}
|
||||
const trans_perspective& operator *= (const trans_affine& m)
|
||||
{
|
||||
return multiply(m);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the transformations using two arbitrary quadrangles.
|
||||
void quad_to_quad(const double* src, const double* dst)
|
||||
// Multiply the matrix by inverse of another one
|
||||
const trans_perspective& operator /= (const trans_perspective& m)
|
||||
{
|
||||
|
||||
double left[8][8];
|
||||
double right[8][1];
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
unsigned ix = i * 2;
|
||||
unsigned iy = ix + 1;
|
||||
|
||||
left[ix][0] = 1.0;
|
||||
left[ix][1] = src[ix];
|
||||
left[ix][2] = src[iy];
|
||||
left[ix][3] = 0.0;
|
||||
left[ix][4] = 0.0;
|
||||
left[ix][5] = 0.0;
|
||||
left[ix][6] = -src[ix] * dst[ix];
|
||||
left[ix][7] = -src[iy] * dst[ix];
|
||||
right[ix][0] = dst[ix];
|
||||
|
||||
left[iy][0] = 0.0;
|
||||
left[iy][1] = 0.0;
|
||||
left[iy][2] = 0.0;
|
||||
left[iy][3] = 1.0;
|
||||
left[iy][4] = src[ix];
|
||||
left[iy][5] = src[iy];
|
||||
left[iy][6] = -src[ix] * dst[iy];
|
||||
left[iy][7] = -src[iy] * dst[iy];
|
||||
right[iy][0] = dst[iy];
|
||||
return multiply_inv(m);
|
||||
}
|
||||
m_valid = simul_eq<8, 1>::solve(left, right, m_mtx);
|
||||
const trans_perspective& operator /= (const trans_affine& m)
|
||||
{
|
||||
return multiply_inv(m);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the direct transformations, i.e., rectangle -> quadrangle
|
||||
void rect_to_quad(double x1, double y1, double x2, double y2,
|
||||
const double* quad)
|
||||
// Multiply the matrix by another one and return
|
||||
// the result in a separete matrix.
|
||||
trans_perspective operator * (const trans_perspective& m)
|
||||
{
|
||||
double src[8];
|
||||
src[0] = src[6] = x1;
|
||||
src[2] = src[4] = x2;
|
||||
src[1] = src[3] = y1;
|
||||
src[5] = src[7] = y2;
|
||||
quad_to_quad(src, quad);
|
||||
return trans_perspective(*this).multiply(m);
|
||||
}
|
||||
trans_perspective operator * (const trans_affine& m)
|
||||
{
|
||||
return trans_perspective(*this).multiply(m);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Set the reverse transformations, i.e., quadrangle -> rectangle
|
||||
void quad_to_rect(const double* quad,
|
||||
double x1, double y1, double x2, double y2)
|
||||
// Multiply the matrix by inverse of another one
|
||||
// and return the result in a separete matrix.
|
||||
trans_perspective operator / (const trans_perspective& m)
|
||||
{
|
||||
double dst[8];
|
||||
dst[0] = dst[6] = x1;
|
||||
dst[2] = dst[4] = x2;
|
||||
dst[1] = dst[3] = y1;
|
||||
dst[5] = dst[7] = y2;
|
||||
quad_to_quad(quad, dst);
|
||||
return trans_perspective(*this).multiply_inv(m);
|
||||
}
|
||||
trans_perspective operator / (const trans_affine& m)
|
||||
{
|
||||
return trans_perspective(*this).multiply_inv(m);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Check if the equations were solved successfully
|
||||
bool is_valid() const { return m_valid; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Transform a point (x, y)
|
||||
void transform(double* x, double* y) const
|
||||
// Calculate and return the inverse matrix
|
||||
trans_perspective operator ~ () const
|
||||
{
|
||||
double tx = *x;
|
||||
double ty = *y;
|
||||
double d = 1.0 / (m_mtx[6][0] * tx + m_mtx[7][0] * ty + 1.0);
|
||||
*x = (m_mtx[0][0] + m_mtx[1][0] * tx + m_mtx[2][0] * ty) * d;
|
||||
*y = (m_mtx[3][0] + m_mtx[4][0] * tx + m_mtx[5][0] * ty) * d;
|
||||
trans_perspective ret = *this;
|
||||
ret.invert();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Equal operator with default epsilon
|
||||
bool operator == (const trans_perspective& m) const
|
||||
{
|
||||
return is_equal(m, affine_epsilon);
|
||||
}
|
||||
|
||||
// Not Equal operator with default epsilon
|
||||
bool operator != (const trans_perspective& m) const
|
||||
{
|
||||
return !is_equal(m, affine_epsilon);
|
||||
}
|
||||
|
||||
//---------------------------------------------------- Transformations
|
||||
// Direct transformation of x and y
|
||||
void transform(double* x, double* y) const;
|
||||
|
||||
// Direct transformation of x and y, affine part only
|
||||
void transform_affine(double* x, double* y) const;
|
||||
|
||||
// Direct transformation of x and y, 2x2 matrix only, no translation
|
||||
void transform_2x2(double* x, double* y) const;
|
||||
|
||||
// Inverse transformation of x and y. It works slow because
|
||||
// it explicitly inverts the matrix on every call. For massive
|
||||
// operations it's better to invert() the matrix and then use
|
||||
// direct transformations.
|
||||
void inverse_transform(double* x, double* y) const;
|
||||
|
||||
|
||||
//---------------------------------------------------------- Auxiliary
|
||||
const trans_perspective& from_affine(const trans_affine& a);
|
||||
double determinant() const;
|
||||
double determinant_reciprocal() const;
|
||||
|
||||
bool is_valid(double epsilon = affine_epsilon) const;
|
||||
bool is_identity(double epsilon = affine_epsilon) const;
|
||||
bool is_equal(const trans_perspective& m,
|
||||
double epsilon = affine_epsilon) const;
|
||||
|
||||
// Determine the major affine parameters. Use with caution
|
||||
// considering possible degenerate cases.
|
||||
double scale() const;
|
||||
double rotation() const;
|
||||
void translation(double* dx, double* dy) const;
|
||||
void scaling(double* x, double* y) const;
|
||||
void scaling_abs(double* x, double* y) const;
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class iterator_x
|
||||
{
|
||||
|
@ -153,17 +240,16 @@ namespace agg
|
|||
double y;
|
||||
|
||||
iterator_x() {}
|
||||
iterator_x(double tx, double ty, double step, const double m[8][1]) :
|
||||
den(m[6][0] * tx + m[7][0] * ty + 1.0),
|
||||
den_step(m[6][0] * step),
|
||||
nom_x(m[0][0] + m[1][0] * tx + m[2][0] * ty),
|
||||
nom_x_step(m[1][0] * step),
|
||||
nom_y(m[3][0] + m[4][0] * tx + m[5][0] * ty),
|
||||
nom_y_step(m[4][0] * step),
|
||||
iterator_x(double px, double py, double step, const trans_perspective& m) :
|
||||
den(px * m.w0 + py * m.w1 + m.w2),
|
||||
den_step(m.w0 * step),
|
||||
nom_x(px * m.sx + py * m.shx + m.tx),
|
||||
nom_x_step(step * m.sx),
|
||||
nom_y(px * m.shy + py * m.sy + m.ty),
|
||||
nom_y_step(step * m.shy),
|
||||
x(nom_x / den),
|
||||
y(nom_y / den)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
|
@ -179,14 +265,467 @@ namespace agg
|
|||
//--------------------------------------------------------------------
|
||||
iterator_x begin(double x, double y, double step) const
|
||||
{
|
||||
return iterator_x(x, y, step, m_mtx);
|
||||
return iterator_x(x, y, step, *this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::square_to_quad(const double* q)
|
||||
{
|
||||
double dx = q[0] - q[2] + q[4] - q[6];
|
||||
double dy = q[1] - q[3] + q[5] - q[7];
|
||||
if(dx == 0.0 && dy == 0.0)
|
||||
{
|
||||
// Affine case (parallelogram)
|
||||
//---------------
|
||||
sx = q[2] - q[0];
|
||||
shy = q[3] - q[1];
|
||||
w0 = 0.0;
|
||||
shx = q[4] - q[2];
|
||||
sy = q[5] - q[3];
|
||||
w1 = 0.0;
|
||||
tx = q[0];
|
||||
ty = q[1];
|
||||
w2 = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double dx1 = q[2] - q[4];
|
||||
double dy1 = q[3] - q[5];
|
||||
double dx2 = q[6] - q[4];
|
||||
double dy2 = q[7] - q[5];
|
||||
double den = dx1 * dy2 - dx2 * dy1;
|
||||
if(den == 0.0)
|
||||
{
|
||||
// Singular case
|
||||
//---------------
|
||||
sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
|
||||
return false;
|
||||
}
|
||||
// General case
|
||||
//---------------
|
||||
double u = (dx * dy2 - dy * dx2) / den;
|
||||
double v = (dy * dx1 - dx * dy1) / den;
|
||||
sx = q[2] - q[0] + u * q[2];
|
||||
shy = q[3] - q[1] + u * q[3];
|
||||
w0 = u;
|
||||
shx = q[6] - q[0] + v * q[6];
|
||||
sy = q[7] - q[1] + v * q[7];
|
||||
w1 = v;
|
||||
tx = q[0];
|
||||
ty = q[1];
|
||||
w2 = 1.0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::invert()
|
||||
{
|
||||
double d0 = sy * w2 - w1 * ty;
|
||||
double d1 = w0 * ty - shy * w2;
|
||||
double d2 = shy * w1 - w0 * sy;
|
||||
double d = sx * d0 + shx * d1 + tx * d2;
|
||||
if(d == 0.0)
|
||||
{
|
||||
sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
|
||||
return false;
|
||||
}
|
||||
d = 1.0 / d;
|
||||
trans_perspective a = *this;
|
||||
sx = d * d0;
|
||||
shy = d * d1;
|
||||
w0 = d * d2;
|
||||
shx = d * (a.w1 *a.tx - a.shx*a.w2);
|
||||
sy = d * (a.sx *a.w2 - a.w0 *a.tx);
|
||||
w1 = d * (a.w0 *a.shx - a.sx *a.w1);
|
||||
tx = d * (a.shx*a.ty - a.sy *a.tx);
|
||||
ty = d * (a.shy*a.tx - a.sx *a.ty);
|
||||
w2 = d * (a.sx *a.sy - a.shy*a.shx);
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::quad_to_square(const double* q)
|
||||
{
|
||||
if(!square_to_quad(q)) return false;
|
||||
invert();
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::quad_to_quad(const double* qs,
|
||||
const double* qd)
|
||||
{
|
||||
trans_perspective p;
|
||||
if(! quad_to_square(qs)) return false;
|
||||
if(!p.square_to_quad(qd)) return false;
|
||||
multiply(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::rect_to_quad(double x1, double y1,
|
||||
double x2, double y2,
|
||||
const double* q)
|
||||
{
|
||||
double r[8];
|
||||
r[0] = r[6] = x1;
|
||||
r[2] = r[4] = x2;
|
||||
r[1] = r[3] = y1;
|
||||
r[5] = r[7] = y2;
|
||||
return quad_to_quad(r, q);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::quad_to_rect(const double* q,
|
||||
double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
double r[8];
|
||||
r[0] = r[6] = x1;
|
||||
r[2] = r[4] = x2;
|
||||
r[1] = r[3] = y1;
|
||||
r[5] = r[7] = y2;
|
||||
return quad_to_quad(q, r);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline trans_perspective::trans_perspective(double x1, double y1,
|
||||
double x2, double y2,
|
||||
const double* quad)
|
||||
{
|
||||
rect_to_quad(x1, y1, x2, y2, quad);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline trans_perspective::trans_perspective(const double* quad,
|
||||
double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
quad_to_rect(quad, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline trans_perspective::trans_perspective(const double* src,
|
||||
const double* dst)
|
||||
{
|
||||
quad_to_quad(src, dst);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective& trans_perspective::reset()
|
||||
{
|
||||
sx = 1; shy = 0; w0 = 0;
|
||||
shx = 0; sy = 1; w1 = 0;
|
||||
tx = 0; ty = 0; w2 = 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective&
|
||||
trans_perspective::multiply(const trans_perspective& a)
|
||||
{
|
||||
trans_perspective b = *this;
|
||||
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
|
||||
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
|
||||
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
|
||||
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
|
||||
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
|
||||
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
|
||||
w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
|
||||
w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
|
||||
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective&
|
||||
trans_perspective::multiply(const trans_affine& a)
|
||||
{
|
||||
trans_perspective b = *this;
|
||||
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
|
||||
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
|
||||
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
|
||||
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
|
||||
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
|
||||
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective&
|
||||
trans_perspective::premultiply(const trans_perspective& b)
|
||||
{
|
||||
trans_perspective a = *this;
|
||||
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
|
||||
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
|
||||
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
|
||||
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
|
||||
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
|
||||
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
|
||||
w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
|
||||
w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
|
||||
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective&
|
||||
trans_perspective::premultiply(const trans_affine& b)
|
||||
{
|
||||
trans_perspective a = *this;
|
||||
sx = a.sx *b.sx + a.shx*b.shy;
|
||||
shx = a.sx *b.shx + a.shx*b.sy;
|
||||
tx = a.sx *b.tx + a.shx*b.ty + a.tx;
|
||||
shy = a.shy*b.sx + a.sy *b.shy;
|
||||
sy = a.shy*b.shx + a.sy *b.sy;
|
||||
ty = a.shy*b.tx + a.sy *b.ty + a.ty;
|
||||
w0 = a.w0 *b.sx + a.w1 *b.shy;
|
||||
w1 = a.w0 *b.shx + a.w1 *b.sy;
|
||||
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_perspective&
|
||||
trans_perspective::multiply_inv(const trans_perspective& m)
|
||||
{
|
||||
trans_perspective t = m;
|
||||
t.invert();
|
||||
return multiply(t);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_perspective&
|
||||
trans_perspective::multiply_inv(const trans_affine& m)
|
||||
{
|
||||
trans_affine t = m;
|
||||
t.invert();
|
||||
return multiply(t);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_perspective&
|
||||
trans_perspective::premultiply_inv(const trans_perspective& m)
|
||||
{
|
||||
trans_perspective t = m;
|
||||
t.invert();
|
||||
return *this = t.multiply(*this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_perspective&
|
||||
trans_perspective::premultiply_inv(const trans_affine& m)
|
||||
{
|
||||
trans_perspective t(m);
|
||||
t.invert();
|
||||
return *this = t.multiply(*this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective&
|
||||
trans_perspective::translate(double x, double y)
|
||||
{
|
||||
tx += x;
|
||||
ty += y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective& trans_perspective::rotate(double a)
|
||||
{
|
||||
multiply(trans_affine_rotation(a));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective& trans_perspective::scale(double s)
|
||||
{
|
||||
multiply(trans_affine_scaling(s));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective& trans_perspective::scale(double x, double y)
|
||||
{
|
||||
multiply(trans_affine_scaling(x, y));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_perspective::transform(double* px, double* py) const
|
||||
{
|
||||
double x = *px;
|
||||
double y = *py;
|
||||
double m = 1.0 / (x*w0 + y*w1 + w2);
|
||||
*px = m * (x*sx + y*shx + tx);
|
||||
*py = m * (x*shy + y*sy + ty);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_perspective::transform_affine(double* x, double* y) const
|
||||
{
|
||||
double tmp = *x;
|
||||
*x = tmp * sx + *y * shx + tx;
|
||||
*y = tmp * shy + *y * sy + ty;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_perspective::transform_2x2(double* x, double* y) const
|
||||
{
|
||||
double tmp = *x;
|
||||
*x = tmp * sx + *y * shx;
|
||||
*y = tmp * shy + *y * sy;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_perspective::inverse_transform(double* x, double* y) const
|
||||
{
|
||||
trans_perspective t(*this);
|
||||
if(t.invert()) t.transform(x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void trans_perspective::store_to(double* m) const
|
||||
{
|
||||
*m++ = sx; *m++ = shy; *m++ = w0;
|
||||
*m++ = shx; *m++ = sy; *m++ = w1;
|
||||
*m++ = tx; *m++ = ty; *m++ = w2;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective& trans_perspective::load_from(const double* m)
|
||||
{
|
||||
sx = *m++; shy = *m++; w0 = *m++;
|
||||
shx = *m++; sy = *m++; w1 = *m++;
|
||||
tx = *m++; ty = *m++; w2 = *m++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const trans_perspective&
|
||||
trans_perspective::from_affine(const trans_affine& a)
|
||||
{
|
||||
sx = a.sx; shy = a.shy; w0 = 0;
|
||||
shx = a.shx; sy = a.sy; w1 = 0;
|
||||
tx = a.tx; ty = a.ty; w2 = 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline double trans_perspective::determinant() const
|
||||
{
|
||||
return sx * (sy * w2 - ty * w1) +
|
||||
shx * (ty * w0 - shy * w2) +
|
||||
tx * (shy * w1 - sy * w0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline double trans_perspective::determinant_reciprocal() const
|
||||
{
|
||||
return 1.0 / determinant();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::is_valid(double epsilon) const
|
||||
{
|
||||
return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::is_identity(double epsilon) const
|
||||
{
|
||||
return is_equal_eps(sx, 1.0, epsilon) &&
|
||||
is_equal_eps(shy, 0.0, epsilon) &&
|
||||
is_equal_eps(w0, 0.0, epsilon) &&
|
||||
is_equal_eps(shx, 0.0, epsilon) &&
|
||||
is_equal_eps(sy, 1.0, epsilon) &&
|
||||
is_equal_eps(w1, 0.0, epsilon) &&
|
||||
is_equal_eps(tx, 0.0, epsilon) &&
|
||||
is_equal_eps(ty, 0.0, epsilon) &&
|
||||
is_equal_eps(w2, 1.0, epsilon);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool trans_perspective::is_equal(const trans_perspective& m,
|
||||
double epsilon) const
|
||||
{
|
||||
return is_equal_eps(sx, m.sx, epsilon) &&
|
||||
is_equal_eps(shy, m.shy, epsilon) &&
|
||||
is_equal_eps(w0, m.w0, epsilon) &&
|
||||
is_equal_eps(shx, m.shx, epsilon) &&
|
||||
is_equal_eps(sy, m.sy, epsilon) &&
|
||||
is_equal_eps(w1, m.w1, epsilon) &&
|
||||
is_equal_eps(tx, m.tx, epsilon) &&
|
||||
is_equal_eps(ty, m.ty, epsilon) &&
|
||||
is_equal_eps(w2, m.w2, epsilon);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline double trans_perspective::scale() const
|
||||
{
|
||||
double x = 0.707106781 * sx + 0.707106781 * shx;
|
||||
double y = 0.707106781 * shy + 0.707106781 * sy;
|
||||
return sqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline double trans_perspective::rotation() const
|
||||
{
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 1.0;
|
||||
double y2 = 0.0;
|
||||
transform(&x1, &y1);
|
||||
transform(&x2, &y2);
|
||||
return atan2(y2-y1, x2-x1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_perspective::translation(double* dx, double* dy) const
|
||||
{
|
||||
*dx = tx;
|
||||
*dy = ty;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_perspective::scaling(double* x, double* y) const
|
||||
{
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 1.0;
|
||||
double y2 = 1.0;
|
||||
trans_perspective t(*this);
|
||||
t *= trans_affine_rotation(-rotation());
|
||||
t.transform(&x1, &y1);
|
||||
t.transform(&x2, &y2);
|
||||
*x = x2 - x1;
|
||||
*y = y2 - y1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_perspective::scaling_abs(double* x, double* y) const
|
||||
{
|
||||
*x = sqrt(sx * sx + shx * shx);
|
||||
*y = sqrt(shy * shy + sy * sy);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_mtx[8][1];
|
||||
bool m_valid;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@ namespace agg
|
|||
void magnification(double m) { m_magn = m; }
|
||||
void radius(double r) { m_radius = r; }
|
||||
|
||||
double xc() const { return m_xc; }
|
||||
double yc() const { return m_yc; }
|
||||
double magnification() const { return m_magn; }
|
||||
double radius() const { return m_radius; }
|
||||
|
||||
void transform(double* x, double* y) const;
|
||||
void inverse_transform(double* x, double* y) const;
|
||||
|
||||
|
|
|
@ -43,21 +43,26 @@ namespace agg
|
|||
|
||||
vcgen_contour();
|
||||
|
||||
void line_join(line_join_e lj) { m_line_join = lj; }
|
||||
void inner_join(inner_join_e ij) { m_inner_join = ij; }
|
||||
void width(double w) { m_width = w * 0.5; }
|
||||
void miter_limit(double ml) { m_miter_limit = ml; }
|
||||
void miter_limit_theta(double t);
|
||||
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
|
||||
void approximation_scale(double as) { m_approx_scale = as; }
|
||||
void auto_detect_orientation(bool v) { m_auto_detect = v; }
|
||||
void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
|
||||
void line_join(line_join_e lj) { m_stroker.line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
|
||||
|
||||
line_join_e line_join() const { return m_line_join; }
|
||||
inner_join_e inner_join() const { return m_inner_join; }
|
||||
double width() const { return m_width * 2.0; }
|
||||
double miter_limit() const { return m_miter_limit; }
|
||||
double inner_miter_limit() const { return m_inner_miter_limit; }
|
||||
double approximation_scale() const { return m_approx_scale; }
|
||||
line_cap_e line_cap() const { return m_stroker.line_cap(); }
|
||||
line_join_e line_join() const { return m_stroker.line_join(); }
|
||||
inner_join_e inner_join() const { return m_stroker.inner_join(); }
|
||||
|
||||
void width(double w) { m_stroker.width(m_width = w); }
|
||||
void miter_limit(double ml) { m_stroker.miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { m_stroker.approximation_scale(as); }
|
||||
|
||||
double width() const { return m_width; }
|
||||
double miter_limit() const { return m_stroker.miter_limit(); }
|
||||
double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
|
||||
double approximation_scale() const { return m_stroker.approximation_scale(); }
|
||||
|
||||
void auto_detect_orientation(bool v) { m_auto_detect = v; }
|
||||
bool auto_detect_orientation() const { return m_auto_detect; }
|
||||
|
||||
// Generator interface
|
||||
|
@ -72,16 +77,10 @@ namespace agg
|
|||
vcgen_contour(const vcgen_contour&);
|
||||
const vcgen_contour& operator = (const vcgen_contour&);
|
||||
|
||||
math_stroke<coord_storage> m_stroker;
|
||||
double m_width;
|
||||
vertex_storage m_src_vertices;
|
||||
coord_storage m_out_vertices;
|
||||
double m_width;
|
||||
line_join_e m_line_join;
|
||||
inner_join_e m_inner_join;
|
||||
double m_approx_scale;
|
||||
double m_abs_width;
|
||||
double m_signed_width;
|
||||
double m_miter_limit;
|
||||
double m_inner_miter_limit;
|
||||
status_e m_status;
|
||||
unsigned m_src_vertex;
|
||||
unsigned m_out_vertex;
|
||||
|
|
|
@ -51,24 +51,24 @@ namespace agg
|
|||
|
||||
vcgen_stroke();
|
||||
|
||||
void line_cap(line_cap_e lc) { m_line_cap = lc; }
|
||||
void line_join(line_join_e lj) { m_line_join = lj; }
|
||||
void inner_join(inner_join_e ij) { m_inner_join = ij; }
|
||||
void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
|
||||
void line_join(line_join_e lj) { m_stroker.line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
|
||||
|
||||
line_cap_e line_cap() const { return m_line_cap; }
|
||||
line_join_e line_join() const { return m_line_join; }
|
||||
inner_join_e inner_join() const { return m_inner_join; }
|
||||
line_cap_e line_cap() const { return m_stroker.line_cap(); }
|
||||
line_join_e line_join() const { return m_stroker.line_join(); }
|
||||
inner_join_e inner_join() const { return m_stroker.inner_join(); }
|
||||
|
||||
void width(double w) { m_width = w * 0.5; }
|
||||
void miter_limit(double ml) { m_miter_limit = ml; }
|
||||
void miter_limit_theta(double t);
|
||||
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
|
||||
void approximation_scale(double as) { m_approx_scale = as; }
|
||||
void width(double w) { m_stroker.width(w); }
|
||||
void miter_limit(double ml) { m_stroker.miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { m_stroker.approximation_scale(as); }
|
||||
|
||||
double width() const { return m_width * 2.0; }
|
||||
double miter_limit() const { return m_miter_limit; }
|
||||
double inner_miter_limit() const { return m_inner_miter_limit; }
|
||||
double approximation_scale() const { return m_approx_scale; }
|
||||
double width() const { return m_stroker.width(); }
|
||||
double miter_limit() const { return m_stroker.miter_limit(); }
|
||||
double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
|
||||
double approximation_scale() const { return m_stroker.approximation_scale(); }
|
||||
|
||||
void shorten(double s) { m_shorten = s; }
|
||||
double shorten() const { return m_shorten; }
|
||||
|
@ -85,16 +85,10 @@ namespace agg
|
|||
vcgen_stroke(const vcgen_stroke&);
|
||||
const vcgen_stroke& operator = (const vcgen_stroke&);
|
||||
|
||||
math_stroke<coord_storage> m_stroker;
|
||||
vertex_storage m_src_vertices;
|
||||
coord_storage m_out_vertices;
|
||||
double m_width;
|
||||
double m_miter_limit;
|
||||
double m_inner_miter_limit;
|
||||
double m_approx_scale;
|
||||
double m_shorten;
|
||||
line_cap_e m_line_cap;
|
||||
line_join_e m_line_join;
|
||||
inner_join_e m_inner_join;
|
||||
unsigned m_closed;
|
||||
status_e m_status;
|
||||
status_e m_prev_status;
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace agg
|
|||
// Modified agg::pod_bvector. The data is interpreted as a sequence
|
||||
// of vertices. It means that the type T must expose:
|
||||
//
|
||||
// bool operator() (const T& val)
|
||||
// bool T::operator() (const T& val)
|
||||
//
|
||||
// that is called every time new vertex is being added. The main purpose
|
||||
// of this operator is the possibility to calculate some values during
|
||||
|
|
|
@ -17,26 +17,16 @@
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "agg_bspline.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bspline::~bspline()
|
||||
{
|
||||
delete [] m_am;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bspline::bspline() :
|
||||
m_max(0),
|
||||
m_num(0),
|
||||
m_x(0),
|
||||
m_y(0),
|
||||
m_am(0),
|
||||
m_last_idx(-1)
|
||||
{
|
||||
}
|
||||
|
@ -47,7 +37,6 @@ namespace agg
|
|||
m_num(0),
|
||||
m_x(0),
|
||||
m_y(0),
|
||||
m_am(0),
|
||||
m_last_idx(-1)
|
||||
{
|
||||
init(num);
|
||||
|
@ -59,7 +48,6 @@ namespace agg
|
|||
m_num(0),
|
||||
m_x(0),
|
||||
m_y(0),
|
||||
m_am(0),
|
||||
m_last_idx(-1)
|
||||
{
|
||||
init(num, x, y);
|
||||
|
@ -71,11 +59,10 @@ namespace agg
|
|||
{
|
||||
if(max > 2 && max > m_max)
|
||||
{
|
||||
delete [] m_am;
|
||||
m_am = new double[max * 3];
|
||||
m_am.resize(max * 3);
|
||||
m_max = max;
|
||||
m_x = m_am + m_max;
|
||||
m_y = m_am + m_max * 2;
|
||||
m_x = &m_am[m_max];
|
||||
m_y = &m_am[m_max * 2];
|
||||
}
|
||||
m_num = 0;
|
||||
m_last_idx = -1;
|
||||
|
@ -103,7 +90,6 @@ namespace agg
|
|||
double* temp;
|
||||
double* r;
|
||||
double* s;
|
||||
double* al;
|
||||
double h, p, d, f, e;
|
||||
|
||||
for(k = 0; k < m_num; k++)
|
||||
|
@ -113,8 +99,8 @@ namespace agg
|
|||
|
||||
n1 = 3 * m_num;
|
||||
|
||||
al = new double[n1];
|
||||
temp = al;
|
||||
pod_array<double> al(n1);
|
||||
temp = &al[0];
|
||||
|
||||
for(k = 0; k < n1; k++)
|
||||
{
|
||||
|
@ -155,7 +141,6 @@ namespace agg
|
|||
al[k] = al[k] * al[k + 1] + s[k];
|
||||
m_am[k] = al[k];
|
||||
}
|
||||
delete [] al;
|
||||
}
|
||||
m_last_idx = -1;
|
||||
}
|
||||
|
|
|
@ -82,9 +82,6 @@ namespace agg
|
|||
m_step = m_num_steps;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_inc::rewind(unsigned)
|
||||
{
|
||||
|
@ -100,9 +97,6 @@ namespace agg
|
|||
m_dfy = m_saved_dfy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
unsigned curve3_inc::vertex(double* x, double* y)
|
||||
{
|
||||
|
@ -131,7 +125,6 @@ namespace agg
|
|||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_div::init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
|
@ -140,12 +133,10 @@ namespace agg
|
|||
m_points.remove_all();
|
||||
m_distance_tolerance_square = 0.5 / m_approximation_scale;
|
||||
m_distance_tolerance_square *= m_distance_tolerance_square;
|
||||
m_distance_tolerance_manhattan = 4.0 / m_approximation_scale;
|
||||
bezier(x1, y1, x2, y2, x3, y3);
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_div::recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
|
@ -169,10 +160,11 @@ namespace agg
|
|||
double dx = x3-x1;
|
||||
double dy = y3-y1;
|
||||
double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx));
|
||||
double da;
|
||||
|
||||
if(d > curve_collinearity_epsilon)
|
||||
{
|
||||
// Regular care
|
||||
// Regular case
|
||||
//-----------------
|
||||
if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
|
@ -187,7 +179,7 @@ namespace agg
|
|||
|
||||
// Angle & Cusp Condition
|
||||
//----------------------
|
||||
double da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
|
||||
da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
|
||||
if(da >= pi) da = 2*pi - da;
|
||||
|
||||
if(da < m_angle_tolerance)
|
||||
|
@ -201,10 +193,29 @@ namespace agg
|
|||
}
|
||||
else
|
||||
{
|
||||
if(fabs(x1 + x3 - x2 - x2) +
|
||||
fabs(y1 + y3 - y2 - y2) <= m_distance_tolerance_manhattan)
|
||||
// Collinear case
|
||||
//------------------
|
||||
da = dx*dx + dy*dy;
|
||||
if(da == 0)
|
||||
{
|
||||
m_points.add(point_d(x123, y123));
|
||||
d = calc_sq_distance(x1, y1, x2, y2);
|
||||
}
|
||||
else
|
||||
{
|
||||
d = ((x2 - x1)*dx + (y2 - y1)*dy) / da;
|
||||
if(d > 0 && d < 1)
|
||||
{
|
||||
// Simple collinear case, 1---2---3
|
||||
// We can leave just two endpoints
|
||||
return;
|
||||
}
|
||||
if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1);
|
||||
else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3);
|
||||
else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy);
|
||||
}
|
||||
if(d < m_distance_tolerance_square)
|
||||
{
|
||||
m_points.add(point_d(x2, y2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -307,9 +318,6 @@ namespace agg
|
|||
m_step = m_num_steps;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve4_inc::rewind(unsigned)
|
||||
{
|
||||
|
@ -327,10 +335,6 @@ namespace agg
|
|||
m_ddfy = m_saved_ddfy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
unsigned curve4_inc::vertex(double* x, double* y)
|
||||
{
|
||||
|
@ -376,12 +380,10 @@ namespace agg
|
|||
m_points.remove_all();
|
||||
m_distance_tolerance_square = 0.5 / m_approximation_scale;
|
||||
m_distance_tolerance_square *= m_distance_tolerance_square;
|
||||
m_distance_tolerance_manhattan = 4.0 / m_approximation_scale;
|
||||
bezier(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve4_div::recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
|
@ -409,6 +411,7 @@ namespace agg
|
|||
double x1234 = (x123 + x234) / 2;
|
||||
double y1234 = (y123 + y234) / 2;
|
||||
|
||||
|
||||
// Try to approximate the full cubic curve by a single straight line
|
||||
//------------------
|
||||
double dx = x4-x1;
|
||||
|
@ -416,7 +419,7 @@ namespace agg
|
|||
|
||||
double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx));
|
||||
double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx));
|
||||
double da1, da2;
|
||||
double da1, da2, k;
|
||||
|
||||
switch((int(d2 > curve_collinearity_epsilon) << 1) +
|
||||
int(d3 > curve_collinearity_epsilon))
|
||||
|
@ -424,18 +427,55 @@ namespace agg
|
|||
case 0:
|
||||
// All collinear OR p1==p4
|
||||
//----------------------
|
||||
if(fabs(x1 + x3 - x2 - x2) +
|
||||
fabs(y1 + y3 - y2 - y2) +
|
||||
fabs(x2 + x4 - x3 - x3) +
|
||||
fabs(y2 + y4 - y3 - y3) <= m_distance_tolerance_manhattan)
|
||||
k = dx*dx + dy*dy;
|
||||
if(k == 0)
|
||||
{
|
||||
m_points.add(point_d(x1234, y1234));
|
||||
d2 = calc_sq_distance(x1, y1, x2, y2);
|
||||
d3 = calc_sq_distance(x4, y4, x3, y3);
|
||||
}
|
||||
else
|
||||
{
|
||||
k = 1 / k;
|
||||
da1 = x2 - x1;
|
||||
da2 = y2 - y1;
|
||||
d2 = k * (da1*dx + da2*dy);
|
||||
da1 = x3 - x1;
|
||||
da2 = y3 - y1;
|
||||
d3 = k * (da1*dx + da2*dy);
|
||||
if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
|
||||
{
|
||||
// Simple collinear case, 1---2---3---4
|
||||
// We can leave just two endpoints
|
||||
return;
|
||||
}
|
||||
if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1);
|
||||
else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4);
|
||||
else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy);
|
||||
|
||||
if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1);
|
||||
else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4);
|
||||
else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy);
|
||||
}
|
||||
if(d2 > d3)
|
||||
{
|
||||
if(d2 < m_distance_tolerance_square)
|
||||
{
|
||||
m_points.add(point_d(x2, y2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(d3 < m_distance_tolerance_square)
|
||||
{
|
||||
m_points.add(point_d(x3, y3));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// p1,p2,p4 are collinear, p3 is considerable
|
||||
// p1,p2,p4 are collinear, p3 is significant
|
||||
//----------------------
|
||||
if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
|
@ -469,7 +509,7 @@ namespace agg
|
|||
break;
|
||||
|
||||
case 2:
|
||||
// p1,p3,p4 are collinear, p2 is considerable
|
||||
// p1,p3,p4 are collinear, p2 is significant
|
||||
//----------------------
|
||||
if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
|
@ -503,7 +543,7 @@ namespace agg
|
|||
break;
|
||||
|
||||
case 3:
|
||||
// Regular care
|
||||
// Regular case
|
||||
//-----------------
|
||||
if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
|
@ -518,9 +558,9 @@ namespace agg
|
|||
|
||||
// Angle & Cusp Condition
|
||||
//----------------------
|
||||
double a23 = atan2(y3 - y2, x3 - x2);
|
||||
da1 = fabs(a23 - atan2(y2 - y1, x2 - x1));
|
||||
da2 = fabs(atan2(y4 - y3, x4 - x3) - a23);
|
||||
k = atan2(y3 - y2, x3 - x2);
|
||||
da1 = fabs(k - atan2(y2 - y1, x2 - x1));
|
||||
da2 = fabs(atan2(y4 - y3, x4 - x3) - k);
|
||||
if(da1 >= pi) da1 = 2*pi - da1;
|
||||
if(da2 >= pi) da2 = 2*pi - da2;
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "agg_gsv_text.h"
|
||||
#include "agg_bounding_rect.h"
|
||||
|
||||
|
||||
|
||||
namespace agg
|
||||
|
@ -480,16 +482,6 @@ namespace agg
|
|||
0xf6,0xfa,0x04,0x06,0x08,0xfa
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
gsv_text::~gsv_text()
|
||||
{
|
||||
if(m_loaded_font) delete [] m_loaded_font;
|
||||
if(m_text_buf) delete [] m_text_buf;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
gsv_text::gsv_text() :
|
||||
m_x(0.0),
|
||||
|
@ -500,11 +492,10 @@ namespace agg
|
|||
m_space(0.0),
|
||||
m_line_space(0.0),
|
||||
m_text(m_chr),
|
||||
m_text_buf(0),
|
||||
m_buf_size(0),
|
||||
m_text_buf(),
|
||||
m_cur_chr(m_chr),
|
||||
m_font(gsv_default_font),
|
||||
m_loaded_font(0),
|
||||
m_loaded_font(),
|
||||
m_status(initial),
|
||||
m_big_endian(false),
|
||||
m_flip(false)
|
||||
|
@ -515,13 +506,11 @@ namespace agg
|
|||
if(*(char*)&t == 0) m_big_endian = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void gsv_text::font(const void* font)
|
||||
{
|
||||
m_font = font;
|
||||
if(m_font == 0) m_font = m_loaded_font;
|
||||
if(m_font == 0) m_font = &m_loaded_font[0];
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -551,13 +540,10 @@ namespace agg
|
|||
//if(m_flip) m_y += m_height;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void gsv_text::load_font(const char* file)
|
||||
{
|
||||
if(m_loaded_font) delete [] m_loaded_font;
|
||||
m_loaded_font = 0;
|
||||
|
||||
m_loaded_font.resize(0);
|
||||
FILE* fd = fopen(file, "rb");
|
||||
if(fd)
|
||||
{
|
||||
|
@ -568,15 +554,14 @@ namespace agg
|
|||
fseek(fd, 0l, SEEK_SET);
|
||||
if(len > 0)
|
||||
{
|
||||
m_loaded_font = new char [len];
|
||||
fread(m_loaded_font, 1, len, fd);
|
||||
m_font = m_loaded_font;
|
||||
m_loaded_font.resize(len);
|
||||
fread(&m_loaded_font[0], 1, len, fd);
|
||||
m_font = &m_loaded_font[0];
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void gsv_text::text(const char* text)
|
||||
{
|
||||
|
@ -587,17 +572,14 @@ namespace agg
|
|||
return;
|
||||
}
|
||||
unsigned new_size = strlen(text) + 1;
|
||||
if(new_size > m_buf_size)
|
||||
if(new_size > m_text_buf.size())
|
||||
{
|
||||
if(m_text_buf) delete [] m_text_buf;
|
||||
m_text_buf = new char [m_buf_size = new_size];
|
||||
m_text_buf.resize(new_size);
|
||||
}
|
||||
memcpy(m_text_buf, text, new_size);
|
||||
m_text = m_text_buf;
|
||||
memcpy(&m_text_buf[0], text, new_size);
|
||||
m_text = &m_text_buf[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void gsv_text::rewind(unsigned)
|
||||
{
|
||||
|
@ -614,7 +596,6 @@ namespace agg
|
|||
m_cur_chr = m_text;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
unsigned gsv_text::vertex(double* x, double* y)
|
||||
{
|
||||
|
@ -623,7 +604,6 @@ namespace agg
|
|||
int dx, dy;
|
||||
bool quit = false;
|
||||
|
||||
|
||||
while(!quit)
|
||||
{
|
||||
switch(m_status)
|
||||
|
@ -683,6 +663,13 @@ namespace agg
|
|||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
double gsv_text::text_width()
|
||||
{
|
||||
double x1, y1, x2, y2;
|
||||
bounding_rect_single(*this, 0, &x1, &y1, &x2, &y2);
|
||||
return x2 - x1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -23,20 +23,6 @@
|
|||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
image_filter_lut::~image_filter_lut()
|
||||
{
|
||||
delete [] m_weight_array;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
image_filter_lut::image_filter_lut() :
|
||||
m_weight_array(0),
|
||||
m_max_size(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void image_filter_lut::realloc_lut(double radius)
|
||||
{
|
||||
|
@ -44,11 +30,9 @@ namespace agg
|
|||
m_diameter = uceil(radius) * 2;
|
||||
m_start = -int(m_diameter / 2 - 1);
|
||||
unsigned size = m_diameter << image_subpixel_shift;
|
||||
if(size > m_max_size)
|
||||
if(size > m_weight_array.size())
|
||||
{
|
||||
delete [] m_weight_array;
|
||||
m_weight_array = new int16 [size];
|
||||
m_max_size = size;
|
||||
m_weight_array.resize(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ namespace agg
|
|||
// [2] | [3]
|
||||
// <3>
|
||||
// 0,1,2,3,4,5,6,7
|
||||
int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 };
|
||||
int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 };
|
||||
const int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 };
|
||||
const int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 };
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,12 +44,11 @@ namespace agg
|
|||
{
|
||||
m_subpixel_width = uround(w * subpixel_scale);
|
||||
unsigned size = m_subpixel_width + subpixel_scale * 6;
|
||||
if(size > m_size)
|
||||
if(size > m_profile.size())
|
||||
{
|
||||
delete [] m_profile;
|
||||
m_profile = new value_type[m_size = size];
|
||||
m_profile.resize(size);
|
||||
}
|
||||
return m_profile;
|
||||
return &m_profile[0];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
namespace agg
|
||||
{
|
||||
int16u g_sqrt_table[1024] =
|
||||
int16u g_sqrt_table[1024] = //----------g_sqrt_table
|
||||
{
|
||||
0,
|
||||
2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444,
|
||||
|
@ -100,7 +100,7 @@ namespace agg
|
|||
};
|
||||
|
||||
|
||||
int8 g_elder_bit_table[256] =
|
||||
int8 g_elder_bit_table[256] = //---------g_elder_bit_table
|
||||
{
|
||||
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
|
|
|
@ -27,12 +27,12 @@ namespace agg
|
|||
const trans_affine& trans_affine::parl_to_parl(const double* src,
|
||||
const double* dst)
|
||||
{
|
||||
m0 = src[2] - src[0];
|
||||
m1 = src[3] - src[1];
|
||||
m2 = src[4] - src[0];
|
||||
m3 = src[5] - src[1];
|
||||
m4 = src[0];
|
||||
m5 = src[1];
|
||||
sx = src[2] - src[0];
|
||||
shy = src[3] - src[1];
|
||||
shx = src[4] - src[0];
|
||||
sy = src[5] - src[1];
|
||||
tx = src[0];
|
||||
ty = src[1];
|
||||
invert();
|
||||
multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1],
|
||||
dst[4] - dst[0], dst[5] - dst[1],
|
||||
|
@ -69,15 +69,15 @@ namespace agg
|
|||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::multiply(const trans_affine& m)
|
||||
{
|
||||
double t0 = m0 * m.m0 + m1 * m.m2;
|
||||
double t2 = m2 * m.m0 + m3 * m.m2;
|
||||
double t4 = m4 * m.m0 + m5 * m.m2 + m.m4;
|
||||
m1 = m0 * m.m1 + m1 * m.m3;
|
||||
m3 = m2 * m.m1 + m3 * m.m3;
|
||||
m5 = m4 * m.m1 + m5 * m.m3 + m.m5;
|
||||
m0 = t0;
|
||||
m2 = t2;
|
||||
m4 = t4;
|
||||
double t0 = sx * m.sx + shy * m.shx;
|
||||
double t2 = shx * m.sx + sy * m.shx;
|
||||
double t4 = tx * m.sx + ty * m.shx + m.tx;
|
||||
shy = sx * m.shy + shy * m.sy;
|
||||
sy = shx * m.shy + sy * m.sy;
|
||||
ty = tx * m.shy + ty * m.sy + m.ty;
|
||||
sx = t0;
|
||||
shx = t2;
|
||||
tx = t4;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -85,18 +85,18 @@ namespace agg
|
|||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::invert()
|
||||
{
|
||||
double d = determinant();
|
||||
double d = determinant_reciprocal();
|
||||
|
||||
double t0 = m3 * d;
|
||||
m3 = m0 * d;
|
||||
m1 = -m1 * d;
|
||||
m2 = -m2 * d;
|
||||
double t0 = sy * d;
|
||||
sy = sx * d;
|
||||
shy = -shy * d;
|
||||
shx = -shx * d;
|
||||
|
||||
double t4 = -m4 * t0 - m5 * m2;
|
||||
m5 = -m4 * m1 - m5 * m3;
|
||||
double t4 = -tx * t0 - ty * shx;
|
||||
ty = -tx * shy - ty * sy;
|
||||
|
||||
m0 = t0;
|
||||
m4 = t4;
|
||||
sx = t0;
|
||||
tx = t4;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -104,55 +104,55 @@ namespace agg
|
|||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::flip_x()
|
||||
{
|
||||
m0 = -m0;
|
||||
m1 = -m1;
|
||||
m4 = -m4;
|
||||
sx = -sx;
|
||||
shy = -shy;
|
||||
tx = -tx;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::flip_y()
|
||||
{
|
||||
m2 = -m2;
|
||||
m3 = -m3;
|
||||
m5 = -m5;
|
||||
shx = -shx;
|
||||
sy = -sy;
|
||||
ty = -ty;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::reset()
|
||||
{
|
||||
m0 = m3 = 1.0;
|
||||
m1 = m2 = m4 = m5 = 0.0;
|
||||
sx = sy = 1.0;
|
||||
shy = shx = tx = ty = 0.0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool is_equal_eps(double v1, double v2, double epsilon)
|
||||
{
|
||||
return fabs(v1 - v2) < epsilon;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool trans_affine::is_identity(double epsilon) const
|
||||
{
|
||||
return is_equal_eps(m0, 1.0, epsilon) &&
|
||||
is_equal_eps(m1, 0.0, epsilon) &&
|
||||
is_equal_eps(m2, 0.0, epsilon) &&
|
||||
is_equal_eps(m3, 1.0, epsilon) &&
|
||||
is_equal_eps(m4, 0.0, epsilon) &&
|
||||
is_equal_eps(m5, 0.0, epsilon);
|
||||
return is_equal_eps(sx, 1.0, epsilon) &&
|
||||
is_equal_eps(shy, 0.0, epsilon) &&
|
||||
is_equal_eps(shx, 0.0, epsilon) &&
|
||||
is_equal_eps(sy, 1.0, epsilon) &&
|
||||
is_equal_eps(tx, 0.0, epsilon) &&
|
||||
is_equal_eps(ty, 0.0, epsilon);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool trans_affine::is_valid(double epsilon) const
|
||||
{
|
||||
return fabs(sx) > epsilon && fabs(sy) > epsilon;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool trans_affine::is_equal(const trans_affine& m, double epsilon) const
|
||||
{
|
||||
return is_equal_eps(m0, m.m0, epsilon) &&
|
||||
is_equal_eps(m1, m.m1, epsilon) &&
|
||||
is_equal_eps(m2, m.m2, epsilon) &&
|
||||
is_equal_eps(m3, m.m3, epsilon) &&
|
||||
is_equal_eps(m4, m.m4, epsilon) &&
|
||||
is_equal_eps(m5, m.m5, epsilon);
|
||||
return is_equal_eps(sx, m.sx, epsilon) &&
|
||||
is_equal_eps(shy, m.shy, epsilon) &&
|
||||
is_equal_eps(shx, m.shx, epsilon) &&
|
||||
is_equal_eps(sy, m.sy, epsilon) &&
|
||||
is_equal_eps(tx, m.tx, epsilon) &&
|
||||
is_equal_eps(ty, m.ty, epsilon);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -170,13 +170,12 @@ namespace agg
|
|||
//------------------------------------------------------------------------
|
||||
void trans_affine::translation(double* dx, double* dy) const
|
||||
{
|
||||
trans_affine t(*this);
|
||||
t *= trans_affine_rotation(-rotation());
|
||||
t.transform(dx, dy);
|
||||
*dx = tx;
|
||||
*dy = ty;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_affine::scaling(double* sx, double* sy) const
|
||||
void trans_affine::scaling(double* x, double* y) const
|
||||
{
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
|
@ -186,8 +185,8 @@ namespace agg
|
|||
t *= trans_affine_rotation(-rotation());
|
||||
t.transform(&x1, &y1);
|
||||
t.transform(&x2, &y2);
|
||||
*sx = x2 - x1;
|
||||
*sy = y2 - y1;
|
||||
*x = x2 - x1;
|
||||
*y = y2 - y1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,10 +40,30 @@ namespace agg
|
|||
//------------------------------------------------------------------------
|
||||
void trans_warp_magnifier::inverse_transform(double* x, double* y) const
|
||||
{
|
||||
trans_warp_magnifier t(*this);
|
||||
t.magnification(1.0 / m_magn);
|
||||
t.radius(m_radius * m_magn);
|
||||
t.transform(x, y);
|
||||
// New version by Andrew Skalkin
|
||||
//-----------------
|
||||
double dx = *x - m_xc;
|
||||
double dy = *y - m_yc;
|
||||
double r = sqrt(dx * dx + dy * dy);
|
||||
|
||||
if(r < m_radius * m_magn)
|
||||
{
|
||||
*x = m_xc + dx / m_magn;
|
||||
*y = m_yc + dy / m_magn;
|
||||
}
|
||||
else
|
||||
{
|
||||
double rnew = r - m_radius * (m_magn - 1.0);
|
||||
*x = m_xc + rnew * dx / r;
|
||||
*y = m_yc + rnew * dy / r;
|
||||
}
|
||||
|
||||
// Old version
|
||||
//-----------------
|
||||
//trans_warp_magnifier t(*this);
|
||||
//t.magnification(1.0 / m_magn);
|
||||
//t.radius(m_radius * m_magn);
|
||||
//t.transform(x, y);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,16 +25,10 @@ namespace agg
|
|||
|
||||
//------------------------------------------------------------------------
|
||||
vcgen_contour::vcgen_contour() :
|
||||
m_stroker(),
|
||||
m_width(1),
|
||||
m_src_vertices(),
|
||||
m_out_vertices(),
|
||||
m_width(1.0),
|
||||
m_line_join(bevel_join),
|
||||
m_inner_join(inner_miter),
|
||||
m_approx_scale(1.0),
|
||||
m_abs_width(1.0),
|
||||
m_signed_width(1.0),
|
||||
m_miter_limit(4.0),
|
||||
m_inner_miter_limit(1.0 + 1.0/64.0),
|
||||
m_status(initial),
|
||||
m_src_vertex(0),
|
||||
m_closed(0),
|
||||
|
@ -43,26 +37,15 @@ namespace agg
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_contour::remove_all()
|
||||
{
|
||||
m_src_vertices.remove_all();
|
||||
m_closed = 0;
|
||||
m_orientation = 0;
|
||||
m_abs_width = fabs(m_width);
|
||||
m_signed_width = m_width;
|
||||
m_status = initial;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_contour::miter_limit_theta(double t)
|
||||
{
|
||||
m_miter_limit = 1.0 / sin(t * 0.5) ;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_contour::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
|
@ -91,14 +74,12 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_contour::rewind(unsigned)
|
||||
{
|
||||
if(m_status == initial)
|
||||
{
|
||||
m_src_vertices.close(true);
|
||||
m_signed_width = m_width;
|
||||
if(m_auto_detect)
|
||||
{
|
||||
if(!is_oriented(m_orientation))
|
||||
|
@ -110,14 +91,13 @@ namespace agg
|
|||
}
|
||||
if(is_oriented(m_orientation))
|
||||
{
|
||||
m_signed_width = is_ccw(m_orientation) ? m_width : -m_width;
|
||||
m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width);
|
||||
}
|
||||
}
|
||||
m_status = ready;
|
||||
m_src_vertex = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
unsigned vcgen_contour::vertex(double* x, double* y)
|
||||
{
|
||||
|
@ -146,18 +126,12 @@ namespace agg
|
|||
m_status = end_poly;
|
||||
break;
|
||||
}
|
||||
stroke_calc_join(m_out_vertices,
|
||||
m_stroker.calc_join(m_out_vertices,
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_src_vertices.curr(m_src_vertex).dist,
|
||||
m_signed_width,
|
||||
m_line_join,
|
||||
m_inner_join,
|
||||
m_miter_limit,
|
||||
m_inner_miter_limit,
|
||||
m_approx_scale);
|
||||
m_src_vertices.curr(m_src_vertex).dist);
|
||||
++m_src_vertex;
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
|
|
|
@ -25,16 +25,10 @@ namespace agg
|
|||
|
||||
//------------------------------------------------------------------------
|
||||
vcgen_stroke::vcgen_stroke() :
|
||||
m_stroker(),
|
||||
m_src_vertices(),
|
||||
m_out_vertices(),
|
||||
m_width(0.5),
|
||||
m_miter_limit(4.0),
|
||||
m_inner_miter_limit(1.01),
|
||||
m_approx_scale(1.0),
|
||||
m_shorten(0.0),
|
||||
m_line_cap(butt_cap),
|
||||
m_line_join(miter_join),
|
||||
m_inner_join(inner_miter),
|
||||
m_closed(0),
|
||||
m_status(initial),
|
||||
m_src_vertex(0),
|
||||
|
@ -42,14 +36,6 @@ namespace agg
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::miter_limit_theta(double t)
|
||||
{
|
||||
m_miter_limit = 1.0 / sin(t * 0.5) ;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::remove_all()
|
||||
{
|
||||
|
@ -80,22 +66,6 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static inline void calc_butt_cap(double* cap,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len,
|
||||
double width)
|
||||
{
|
||||
double dx = (v1.y - v0.y) * width / len;
|
||||
double dy = (v1.x - v0.x) * width / len;
|
||||
cap[0] = v0.x - dx;
|
||||
cap[1] = v0.y + dy;
|
||||
cap[2] = v0.x + dx;
|
||||
cap[3] = v0.y - dy;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::rewind(unsigned)
|
||||
{
|
||||
|
@ -135,13 +105,10 @@ namespace agg
|
|||
break;
|
||||
|
||||
case cap1:
|
||||
stroke_calc_cap(m_out_vertices,
|
||||
m_stroker.calc_cap(m_out_vertices,
|
||||
m_src_vertices[0],
|
||||
m_src_vertices[1],
|
||||
m_src_vertices[0].dist,
|
||||
m_line_cap,
|
||||
m_width,
|
||||
m_approx_scale);
|
||||
m_src_vertices[0].dist);
|
||||
m_src_vertex = 1;
|
||||
m_prev_status = outline1;
|
||||
m_status = out_vertices;
|
||||
|
@ -149,13 +116,10 @@ namespace agg
|
|||
break;
|
||||
|
||||
case cap2:
|
||||
stroke_calc_cap(m_out_vertices,
|
||||
m_stroker.calc_cap(m_out_vertices,
|
||||
m_src_vertices[m_src_vertices.size() - 1],
|
||||
m_src_vertices[m_src_vertices.size() - 2],
|
||||
m_src_vertices[m_src_vertices.size() - 2].dist,
|
||||
m_line_cap,
|
||||
m_width,
|
||||
m_approx_scale);
|
||||
m_src_vertices[m_src_vertices.size() - 2].dist);
|
||||
m_prev_status = outline2;
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
|
@ -179,18 +143,12 @@ namespace agg
|
|||
break;
|
||||
}
|
||||
}
|
||||
stroke_calc_join(m_out_vertices,
|
||||
m_stroker.calc_join(m_out_vertices,
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_src_vertices.curr(m_src_vertex).dist,
|
||||
m_width,
|
||||
m_line_join,
|
||||
m_inner_join,
|
||||
m_miter_limit,
|
||||
m_inner_miter_limit,
|
||||
m_approx_scale);
|
||||
m_src_vertices.curr(m_src_vertex).dist);
|
||||
++m_src_vertex;
|
||||
m_prev_status = m_status;
|
||||
m_status = out_vertices;
|
||||
|
@ -210,18 +168,12 @@ namespace agg
|
|||
}
|
||||
|
||||
--m_src_vertex;
|
||||
stroke_calc_join(m_out_vertices,
|
||||
m_stroker.calc_join(m_out_vertices,
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex).dist,
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_width,
|
||||
m_line_join,
|
||||
m_inner_join,
|
||||
m_miter_limit,
|
||||
m_inner_miter_limit,
|
||||
m_approx_scale);
|
||||
m_src_vertices.prev(m_src_vertex).dist);
|
||||
|
||||
m_prev_status = m_status;
|
||||
m_status = out_vertices;
|
||||
|
|
|
@ -290,7 +290,6 @@ popplaces_text_symbolizer.set_label_placement=label_placement.POINT_PLACEMENT
|
|||
popplaces_text_symbolizer.halo_fill = Color('white')
|
||||
popplaces_text_symbolizer.halo_radius = 1
|
||||
popplaces_rule.symbols.append(popplaces_text_symbolizer)
|
||||
popplaces_rule.symbols.append(PointSymbolizer("/home/artem/dot.png","png",10,10))
|
||||
|
||||
popplaces_style.rules.append(popplaces_rule)
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ namespace mapnik
|
|||
unsigned width = pixmap_.width();
|
||||
unsigned height = pixmap_.height();
|
||||
path_type path(t_,*geom,prj_trans);
|
||||
agg::row_ptr_cache<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
|
||||
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
|
||||
agg::pixfmt_rgba32 pixf(buf);
|
||||
ren_base renb(pixf);
|
||||
|
||||
|
@ -179,7 +179,7 @@ namespace mapnik
|
|||
if (geom && geom->num_points() > 1)
|
||||
{
|
||||
path_type path(t_,*geom,prj_trans);
|
||||
agg::row_ptr_cache<agg::int8u> buf(pixmap_.raw_data(),
|
||||
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(),
|
||||
pixmap_.width(),
|
||||
pixmap_.height(),
|
||||
pixmap_.width()*4);
|
||||
|
@ -389,7 +389,7 @@ namespace mapnik
|
|||
unsigned height = pixmap_.height();
|
||||
ImageData32 const& pat = sym.get_pattern();
|
||||
path_type path(t_,*geom,prj_trans);
|
||||
agg::row_ptr_cache<agg::int8u> buf(pixmap_.raw_data(), width, height,width*4);
|
||||
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(), width, height,width*4);
|
||||
agg::pixfmt_rgba32 pixf(buf);
|
||||
renderer_base ren_base(pixf);
|
||||
agg::pattern_filter_bilinear_rgba8 filter;
|
||||
|
@ -429,13 +429,13 @@ namespace mapnik
|
|||
unsigned height = pixmap_.height();
|
||||
path_type path(t_,*geom,prj_trans);
|
||||
|
||||
agg::row_ptr_cache<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
|
||||
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
|
||||
agg::pixfmt_rgba32 pixf(buf);
|
||||
ren_base renb(pixf);
|
||||
|
||||
unsigned w=pattern.width();
|
||||
unsigned h=pattern.height();
|
||||
agg::row_ptr_cache<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4);
|
||||
agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4);
|
||||
|
||||
double x0,y0;
|
||||
path.vertex(&x0,&y0);
|
||||
|
@ -445,7 +445,8 @@ namespace mapnik
|
|||
unsigned offset_y = unsigned(height - y0);
|
||||
|
||||
agg::span_allocator<agg::rgba8> sa;
|
||||
img_source_type img_src(pattern_rbuf);
|
||||
agg::pixfmt_rgba32 pixf_pattern(pattern_rbuf);
|
||||
img_source_type img_src(pixf_pattern);
|
||||
span_gen_type sg(img_src, offset_x, offset_y);
|
||||
renderer_type rp(renb,sa, sg);
|
||||
|
||||
|
|
|
@ -126,16 +126,23 @@ namespace mapnik
|
|||
|
||||
if ( sym.first == "PointSymbolizer")
|
||||
{
|
||||
std::string file =
|
||||
sym.second.get<std::string>("<xmlattr>.file");
|
||||
std::string type =
|
||||
sym.second.get<std::string>("<xmlattr>.type");
|
||||
unsigned width =
|
||||
sym.second.get<unsigned>("<xmlattr>.width");
|
||||
unsigned height =
|
||||
sym.second.get<unsigned>("<xmlattr>.height");
|
||||
boost::optional<std::string> file =
|
||||
sym.second.get_optional<std::string>("<xmlattr>.file");
|
||||
boost::optional<std::string> type =
|
||||
sym.second.get_optional<std::string>("<xmlattr>.type");
|
||||
boost::optional<unsigned> width =
|
||||
sym.second.get_optional<unsigned>("<xmlattr>.width");
|
||||
boost::optional<unsigned> height =
|
||||
sym.second.get_optional<unsigned>("<xmlattr>.height");
|
||||
|
||||
rule.append(point_symbolizer(file,type,width,height));
|
||||
if (file && type && width && height)
|
||||
{
|
||||
rule.append(point_symbolizer(*file,*type,*width,*height));
|
||||
}
|
||||
else
|
||||
{
|
||||
rule.append(point_symbolizer());
|
||||
}
|
||||
}
|
||||
else if ( sym.first == "LinePatternSymbolizer")
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue