diff --git a/agg/include/agg_alpha_mask_u8.h b/agg/include/agg_alpha_mask_u8.h index b325c5492..e301c1008 100644 --- a/agg/include/agg_alpha_mask_u8.h +++ b/agg/include/agg_alpha_mask_u8.h @@ -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; } diff --git a/agg/include/agg_array.h b/agg/include/agg_array.h index cabdb93d6..8d5668384 100644 --- a/agg/include/agg_array.h +++ b/agg/include/agg_array.h @@ -109,20 +109,27 @@ namespace agg typedef T value_type; typedef pod_array self_type; - ~pod_array() { delete [] m_array; } + ~pod_array() { pod_allocator::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::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::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::deallocate(m_array, m_size); + m_array = pod_allocator::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::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::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::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::allocate(new_size); memcpy(data, m_array, m_size * sizeof(T)); - delete [] m_array; + pod_allocator::deallocate(m_array, m_capacity); m_array = data; } } @@ -252,13 +259,15 @@ namespace agg //------------------------------------------------------------------------ template pod_vector::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::allocate(m_capacity)) {} //------------------------------------------------------------------------ template pod_vector::pod_vector(const pod_vector& 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::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::deallocate(*blk, block_size); --blk; } - delete [] m_blocks; } + pod_allocator::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::deallocate(m_blocks[--m_num_blocks], block_size); + } + if(m_num_blocks == 0) + { + pod_allocator::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::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::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::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::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::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::deallocate(blk->data, blk->size); --blk; } - delete [] m_blocks; + pod_allocator::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,31 +860,36 @@ 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::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::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::allocate(size); + m_num_blocks++; m_rest = size; } - unsigned m_block_size; - unsigned m_block_ptr_inc; - unsigned m_num_blocks; - unsigned m_max_blocks; - int8u** m_blocks; - int8u* m_buf_ptr; - unsigned m_rest; + unsigned m_block_size; + unsigned m_block_ptr_inc; + unsigned m_num_blocks; + unsigned m_max_blocks; + block_type* m_blocks; + int8u* m_buf_ptr; + unsigned m_rest; }; @@ -1014,7 +1044,6 @@ namespace agg return j; } - //--------------------------------------------------------invert_container template void invert_container(Array& arr) { @@ -1026,7 +1055,6 @@ namespace agg } } - //------------------------------------------------------binary_search_pos template unsigned binary_search_pos(const Array& arr, const Value& val, Less less) @@ -1052,6 +1080,40 @@ namespace agg return end; } + //----------------------------------------------------------range_adaptor + template 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 diff --git a/agg/include/agg_basics.h b/agg/include/agg_basics.h index 58edd2eb4..cb9583815 100644 --- a/agg/include/agg_basics.h +++ b/agg/include/agg_basics.h @@ -19,6 +19,43 @@ #include #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 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 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 struct rect_base { + typedef T value_type; typedef rect_base 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 vertex_f; //-----vertex_f typedef vertex_base vertex_d; //-----vertex_d + //----------------------------------------------------------------row_info + template 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 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 inline bool is_equal_eps(T v1, T v2, T epsilon) + { + return fabs(v1 - v2) <= double(epsilon); + } + } diff --git a/agg/include/agg_bspline.h b/agg/include/agg_bspline.h index 19a153f31..2c1ed9a38 100644 --- a/agg/include/agg_bspline.h +++ b/agg/include/agg_bspline.h @@ -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); @@ -63,12 +62,12 @@ namespace agg double extrapolation_right(double x) const; double interpolation(double x, int i) const; - int m_max; - int m_num; - double* m_x; - double* m_y; - double* m_am; - mutable int m_last_idx; + int m_max; + int m_num; + double* m_x; + double* m_y; + pod_array m_am; + mutable int m_last_idx; }; diff --git a/agg/include/agg_color_gray.h b/agg/include/agg_color_gray.h index 0fb11cc87..8e782ef2c 100644 --- a/agg/include/agg_color_gray.h +++ b/agg/include/agg_color_gray.h @@ -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); } }; diff --git a/agg/include/agg_color_rgba.h b/agg/include/agg_color_rgba.h index befa1650f..7c088c695 100644 --- a/agg/include/agg_color_rgba.h +++ b/agg/include/agg_color_rgba.h @@ -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 + 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 + 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 + 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 + 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); + } + + } diff --git a/agg/include/agg_config.h b/agg/include/agg_config.h index 32bf946f5..5095172ad 100644 --- a/agg/include/agg_config.h +++ b/agg/include/agg_config.h @@ -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 +// +// Provides cheaper creation and destruction (no mem allocs): +#define AGG_RENDERING_BUFFER row_accessor +// +// 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 diff --git a/agg/include/agg_conv_adaptor_vcgen.h b/agg/include/agg_conv_adaptor_vcgen.h index 45811e6b3..a79f2208c 100644 --- a/agg/include/agg_conv_adaptor_vcgen.h +++ b/agg/include/agg_conv_adaptor_vcgen.h @@ -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; } diff --git a/agg/include/agg_conv_adaptor_vpgen.h b/agg/include/agg_conv_adaptor_vpgen.h index 37d973008..d6b545ef1 100644 --- a/agg/include/agg_conv_adaptor_vpgen.h +++ b/agg/include/agg_conv_adaptor_vpgen.h @@ -25,9 +25,8 @@ namespace agg template 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; } diff --git a/agg/include/agg_conv_close_polygon.h b/agg/include/agg_conv_close_polygon.h index d8f054ccf..c46594fdf 100644 --- a/agg/include/agg_conv_close_polygon.h +++ b/agg/include/agg_conv_close_polygon.h @@ -25,9 +25,8 @@ namespace agg template 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); diff --git a/agg/include/agg_conv_concat.h b/agg/include/agg_conv_concat.h index fd243b484..745d349c6 100644 --- a/agg/include/agg_conv_concat.h +++ b/agg/include/agg_conv_concat.h @@ -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) diff --git a/agg/include/agg_conv_curve.h b/agg/include/agg_conv_curve.h index 510e281db..d5b475de7 100644 --- a/agg/include/agg_conv_curve.h +++ b/agg/include/agg_conv_curve.h @@ -60,10 +60,9 @@ namespace agg typedef Curve4 curve4_type; typedef conv_curve 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) { diff --git a/agg/include/agg_conv_gpc.h b/agg/include/agg_conv_gpc.h index 7d4d65deb..2acada342 100644 --- a/agg/include/agg_conv_gpc.h +++ b/agg/include/agg_conv_gpc.h @@ -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::deallocate(p.contour[i].vertex, + p.contour[i].num_vertices); } - delete [] p.hole; - delete [] p.contour; + pod_allocator::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::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::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; diff --git a/agg/include/agg_conv_transform.h b/agg/include/agg_conv_transform.h index 1203e6c80..171087748 100644 --- a/agg/include/agg_conv_transform.h +++ b/agg/include/agg_conv_transform.h @@ -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) { diff --git a/agg/include/agg_conv_unclose_polygon.h b/agg/include/agg_conv_unclose_polygon.h index 5474ce2d4..fe5c26381 100644 --- a/agg/include/agg_conv_unclose_polygon.h +++ b/agg/include/agg_conv_unclose_polygon.h @@ -24,9 +24,8 @@ namespace agg template 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) { diff --git a/agg/include/agg_curves.h b/agg/include/agg_curves.h index 1cb69c310..1ef02e878 100644 --- a/agg/include/agg_curves.h +++ b/agg/include/agg_curves.h @@ -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 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; diff --git a/agg/include/agg_font_cache_manager.h b/agg/include/agg_font_cache_manager.h index 4585465b6..fe9a9280f 100644 --- a/agg/include/agg_font_cache_manager.h +++ b/agg/include/agg_font_cache_manager.h @@ -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); @@ -103,18 +107,18 @@ namespace agg (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), sizeof(double)); - glyph->glyph_index = glyph_index; - glyph->data = m_allocator.allocate(data_size); - glyph->data_size = data_size; - glyph->data_type = data_type; - glyph->bounds = bounds; - glyph->advance_x = advance_x; - glyph->advance_y = advance_y; + glyph->glyph_index = glyph_index; + glyph->data = m_allocator.allocate(data_size); + glyph->data_size = data_size; + glyph->data_type = data_type; + glyph->bounds = bounds; + glyph->advance_x = advance_x; + glyph->advance_y = advance_y; return m_glyphs[msb][lsb] = glyph; } 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::deallocate(m_fonts[i]); } - delete [] m_fonts; + pod_allocator::deallocate(m_fonts, m_max_fonts); } //-------------------------------------------------------------------- font_cache_pool(unsigned max_fonts=32) : - m_fonts(new font_cache* [max_fonts]), + m_fonts(pod_allocator::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::deallocate(m_fonts[idx]); + m_fonts[idx] = obj_allocator::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::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::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) { diff --git a/agg/include/agg_gamma_lut.h b/agg/include/agg_gamma_lut.h index cef878828..c3e8dfc13 100644 --- a/agg/include/agg_gamma_lut.h +++ b/agg/include/agg_gamma_lut.h @@ -45,14 +45,14 @@ namespace agg ~gamma_lut() { - delete [] m_inv_gamma; - delete [] m_dir_gamma; + pod_allocator::deallocate(m_inv_gamma, hi_res_size); + pod_allocator::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::allocate(gamma_size)), + m_inv_gamma(pod_allocator::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::allocate(gamma_size)), + m_inv_gamma(pod_allocator::allocate(hi_res_size)) { gamma(g); } diff --git a/agg/include/agg_gsv_text.h b/agg/include/agg_gsv_text.h index cbfdc1161..73e4ec888 100644 --- a/agg/include/agg_gsv_text.h +++ b/agg/include/agg_gsv_text.h @@ -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); @@ -54,6 +53,8 @@ namespace agg void line_space(double line_space); 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); @@ -80,30 +81,28 @@ namespace agg } private: - double m_x; - double m_y; - double m_start_x; - double m_width; - double m_height; - double m_space; - double m_line_space; - char m_chr[2]; - char* m_text; - char* m_text_buf; - unsigned m_buf_size; - char* m_cur_chr; - const void* m_font; - char* m_loaded_font; - status m_status; - bool m_big_endian; - bool m_flip; - - int8u* m_indices; - int8* m_glyphs; - int8* m_bglyph; - int8* m_eglyph; - double m_w; - double m_h; + double m_x; + double m_y; + double m_start_x; + double m_width; + double m_height; + double m_space; + double m_line_space; + char m_chr[2]; + char* m_text; + pod_array m_text_buf; + char* m_cur_chr; + const void* m_font; + pod_array m_loaded_font; + status m_status; + bool m_big_endian; + bool m_flip; + int8u* m_indices; + int8* m_glyphs; + int8* m_bglyph; + int8* m_eglyph; + double m_w; + double m_h; }; diff --git a/agg/include/agg_image_accessors.h b/agg/include/agg_image_accessors.h index 7e19a6990..baaef9c5b 100644 --- a/agg/include/agg_image_accessors.h +++ b/agg/include/agg_image_accessors.h @@ -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; } diff --git a/agg/include/agg_image_filters.h b/agg/include/agg_image_filters.h index 2738cadac..8e1bc8f0d 100644 --- a/agg/include/agg_image_filters.h +++ b/agg/include/agg_image_filters.h @@ -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 void calculate(const FilterF& filter, bool normalization=true) { @@ -71,18 +69,18 @@ namespace agg } } + image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {} + template image_filter_lut(const FilterF& filter, - bool normalization=true) : - m_weight_array(0), - m_max_size(0) + bool normalization=true) { calculate(filter, normalization); } - 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; } + 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[0]; } void normalize(); private: @@ -90,11 +88,10 @@ namespace agg image_filter_lut(const image_filter_lut&); const image_filter_lut& operator = (const image_filter_lut&); - double m_radius; - unsigned m_diameter; - int m_start; - int16* m_weight_array; - unsigned m_max_size; + double m_radius; + unsigned m_diameter; + int m_start; + pod_array m_weight_array; }; diff --git a/agg/include/agg_line_aa_basics.h b/agg/include/agg_line_aa_basics.h index 1fafb984c..c5acb18e7 100644 --- a/agg/include/agg_line_aa_basics.h +++ b/agg/include/agg_line_aa_basics.h @@ -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]; }; diff --git a/agg/include/agg_math.h b/agg/include/agg_math.h index 9306aa5af..2ec49cf3f 100644 --- a/agg/include/agg_math.h +++ b/agg/include/agg_math.h @@ -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, @@ -132,11 +182,10 @@ namespace agg double dx = x2 - x1; double dy = y2 - y1; double d = sqrt(dx*dx + dy*dy); - *x = thickness * dy / d; - *y = thickness * dx / d; + *x = thickness * dy / 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 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) { diff --git a/agg/include/agg_math_stroke.h b/agg/include/agg_math_stroke.h index d06959590..4806dcd4b 100644 --- a/agg/include/agg_math_stroke.h +++ b/agg/include/agg_math_stroke.h @@ -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 - 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 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 math_stroke::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 void math_stroke::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 void math_stroke::miter_limit_theta(double t) + { + m_miter_limit = 1.0 / sin(t * 0.5) ; + } + + //----------------------------------------------------------------------- + template + void math_stroke::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 - void stroke_calc_miter(VertexConsumer& out_vertices, - 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) + //----------------------------------------------------------------------- + template + void math_stroke::calc_miter(VC& 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) { - typedef typename VertexConsumer::value_type coord_type; - - double xi = v1.x; - double yi = v1.y; + 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 - void stroke_calc_cap(VertexConsumer& out_vertices, - const vertex_dist& v0, - const vertex_dist& v1, - double len, - line_cap_e line_cap, - double width, - double approximation_scale) + template + void math_stroke::calc_cap(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + 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 - void stroke_calc_join(VertexConsumer& out_vertices, - 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) + //----------------------------------------------------------------------- + template + void math_stroke::calc_join(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double len1, + 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, - v0, v1, v2, dx1, dy1, dx2, dy2, - width, - miter_join_revert, - inner_miter_limit, - 1.0); + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + 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) + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + limit, 0); + } + else + { + if(m_inner_join == inner_jag) { - stroke_calc_miter(out_vertices, - v0, v1, v2, dx1, dy1, dx2, dy2, - width, - miter_join_revert, - inner_miter_limit, - 1.0); + 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 { - if(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)); - } - 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, - v0, v1, v2, dx1, dy1, dx2, dy2, - width, - line_join, - miter_limit, - approximation_scale); + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + 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; } } diff --git a/agg/include/agg_path_storage.h b/agg/include/agg_path_storage.h index 6a001afce..f4f754746 100644 --- a/agg/include/agg_path_storage.h +++ b/agg/include/agg_path_storage.h @@ -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::deallocate( + *coord_blk, + block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); --coord_blk; } - delete [] m_coord_blocks; + pod_allocator::deallocate(m_coord_blocks, m_max_blocks * 2); m_total_blocks = 0; m_max_blocks = 0; m_coord_blocks = 0; @@ -145,7 +148,7 @@ namespace agg unsigned cmd = v.vertex(i, &x, &y); add_vertex(x, y, cmd); } - return *this; + return *this; } //------------------------------------------------------------------------ @@ -298,7 +301,7 @@ namespace agg if(nb >= m_max_blocks) { T** new_coords = - new T* [(m_max_blocks + block_pool) * 2]; + pod_allocator::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::deallocate(m_coord_blocks, m_max_blocks * 2); } m_coord_blocks = new_coords; - m_cmd_blocks = new_cmds; - m_max_blocks += block_pool; + 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::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 + 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 + 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 unsigned path_base::perceive_polygon_orientation(unsigned start, @@ -1188,7 +1230,6 @@ namespace agg return (area < 0.0) ? path_flags_cw : path_flags_ccw; } - //------------------------------------------------------------------------ template void path_base::invert_polygon(unsigned start, unsigned end) @@ -1232,10 +1273,7 @@ namespace agg while(end < m_vertices.total_vertices() && !is_next_poly(m_vertices.command(end))) ++end; - if(end - start > 2) - { - invert_polygon(start, end); - } + invert_polygon(start, end); } //------------------------------------------------------------------------ @@ -1276,7 +1314,6 @@ namespace agg return end; } - //------------------------------------------------------------------------ template unsigned path_base::arrange_orientations(unsigned start, @@ -1297,7 +1334,6 @@ namespace agg return start; } - //------------------------------------------------------------------------ template void path_base::arrange_orientations_all_paths(path_flags_e orientation) @@ -1312,7 +1348,6 @@ namespace agg } } - //------------------------------------------------------------------------ template void path_base::flip_x(double x1, double x2) @@ -1329,7 +1364,6 @@ namespace agg } } - //------------------------------------------------------------------------ template void path_base::flip_y(double y1, double y2) @@ -1346,9 +1380,42 @@ namespace agg } } + //------------------------------------------------------------------------ + template + void path_base::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 + void path_base::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 vertex_stl_storage diff --git a/agg/include/agg_pixfmt_amask_adaptor.h b/agg/include/agg_pixfmt_amask_adaptor.h index 0c7b0e3c5..b30014fc4 100644 --- a/agg/include/agg_pixfmt_amask_adaptor.h +++ b/agg/include/agg_pixfmt_amask_adaptor.h @@ -18,6 +18,7 @@ #include +#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 + 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; + pixfmt_type* m_pixf; + const amask_type* m_mask; + pod_array m_span; }; } diff --git a/agg/include/agg_pixfmt_gray.h b/agg/include/agg_pixfmt_gray.h index 64fc9a958..dd4f2469d 100644 --- a/agg/include/agg_pixfmt_gray.h +++ b/agg/include/agg_pixfmt_gray.h @@ -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 + 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 + 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 + 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; }; diff --git a/agg/include/agg_pixfmt_rgb.h b/agg/include/agg_pixfmt_rgb.h index 9a9685152..4025fa5ab 100644 --- a/agg/include/agg_pixfmt_rgb.h +++ b/agg/include/agg_pixfmt_rgb.h @@ -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 + 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); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; } - //-------------------------------------------------------------------- - 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); + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + 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 + 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 + 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; diff --git a/agg/include/agg_pixfmt_rgb_packed.h b/agg/include/agg_pixfmt_rgb_packed.h index ec2fbd41d..4bb11cf19 100644 --- a/agg/include/agg_pixfmt_rgb_packed.h +++ b/agg/include/agg_pixfmt_rgb_packed.h @@ -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 + 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 + 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 + 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; diff --git a/agg/include/agg_pixfmt_rgba.h b/agg/include/agg_pixfmt_rgba.h index 00adc233c..7d89b4905 100644 --- a/agg/include/agg_pixfmt_rgba.h +++ b/agg/include/agg_pixfmt_rgba.h @@ -614,12 +614,15 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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); - p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); + 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); + p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); + } } }; @@ -649,14 +652,17 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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; + 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) ? (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; } - 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)); + 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)(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,15 +732,18 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - calc_type s1a = base_mask - sa; - calc_type d1a = base_mask - p[Order::A]; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } } }; @@ -760,14 +773,17 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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 - ((sr * dr + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + 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 - ((sr * dr + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } } }; @@ -801,27 +817,30 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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]; - calc_type sada = sa * p[Order::A]; + 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]; + calc_type sada = sa * p[Order::A]; - 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); + 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_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); + 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_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); + 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_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } } }; @@ -855,17 +874,20 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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]; + 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)((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::A] = (value_type)(sa + da - ((sa * da + base_mask) >> 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)); + } } }; @@ -895,17 +917,20 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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]; + 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)((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::A] = (value_type)(sa + da - ((sa * da + base_mask) >> 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)); + } } }; @@ -940,33 +965,36 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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]; - long_type drsa = dr * sa; - long_type dgsa = dg * sa; - long_type dbsa = db * sa; - long_type srda = sr * da; - long_type sgda = sg * da; - long_type sbda = sb * da; - long_type sada = sa * da; + 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]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + 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)); + p[Order::R] = (value_type)((srda + drsa >= sada) ? + (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)); + p[Order::G] = (value_type)((sgda + dgsa >= sada) ? + (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)); + p[Order::B] = (value_type)((sbda + dbsa >= sada) ? + (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)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } } }; @@ -1001,33 +1029,36 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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]; - long_type drsa = dr * sa; - long_type dgsa = dg * sa; - long_type dbsa = db * sa; - long_type srda = sr * da; - long_type sgda = sg * da; - long_type sbda = sb * da; - long_type sada = sa * da; + 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]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; - p[Order::R] = (value_type)(((srda + drsa <= sada) ? - sr * d1a + dr * s1a : - sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a) >> base_shift); + p[Order::R] = (value_type)(((srda + drsa <= sada) ? + sr * d1a + dr * s1a : + 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); + p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? + sg * d1a + dg * s1a : + 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); + p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? + sb * d1a + db * s1a : + sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } } }; @@ -1062,27 +1093,30 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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]; - calc_type sada = sa * da; + 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]; + calc_type sada = sa * da; - 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); + 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_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); + 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_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); + 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_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } } }; @@ -1117,31 +1151,34 @@ 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); - double dr = double(p[Order::R]) / base_mask; - double dg = double(p[Order::G]) / base_mask; - double db = double(p[Order::B]) / base_mask; - double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; - if(cover < 255) + if(sa > 0) { - a = (a * cover + 255) >> 8; + double dr = double(p[Order::R]) / base_mask; + double dg = double(p[Order::G]) / base_mask; + double db = double(p[Order::B]) / base_mask; + double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; + if(cover < 255) + { + a = (a * cover + 255) >> 8; + } + + if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); + else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + + if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); + else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + + if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); + else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + + p[Order::R] = (value_type)uround(dr * base_mask); + p[Order::G] = (value_type)uround(dg * base_mask); + p[Order::B] = (value_type)uround(db * base_mask); + p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); } - - if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); - else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); - else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); - - if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); - else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); - else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); - - if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); - else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); - else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); - - p[Order::R] = (value_type)uround(dr * base_mask); - p[Order::G] = (value_type)uround(dg * base_mask); - p[Order::B] = (value_type)uround(db * base_mask); - p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); } }; @@ -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,14 +1210,17 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + 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_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)); + } } }; @@ -1210,16 +1251,19 @@ namespace agg sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } - 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::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + 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_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)); + } } }; @@ -1270,11 +1314,83 @@ namespace agg } }; + //=====================================================comp_op_rgba_invert + template 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 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 ::blend_pix, comp_op_rgba_exclusion ::blend_pix, comp_op_rgba_contrast ::blend_pix, + comp_op_rgba_invert ::blend_pix, + comp_op_rgba_invert_rgb ::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 + 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 + 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 + 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 + 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 + 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 + 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; diff --git a/agg/include/agg_rasterizer_cells_aa.h b/agg/include/agg_rasterizer_cells_aa.h index 5455e55b7..502765f08 100755 --- a/agg/include/agg_rasterizer_cells_aa.h +++ b/agg/include/agg_rasterizer_cells_aa.h @@ -103,21 +103,21 @@ namespace agg void allocate_block(); private: - unsigned m_num_blocks; - unsigned m_max_blocks; - unsigned m_curr_block; - unsigned m_num_cells; - cell_type** m_cells; - cell_type* m_curr_cell_ptr; - pod_vector m_sorted_cells; - pod_vector m_sorted_y; - cell_type m_curr_cell; - cell_type m_style_cell; - int m_min_x; - int m_min_y; - int m_max_x; - int m_max_y; - bool m_sorted; + unsigned m_num_blocks; + unsigned m_max_blocks; + unsigned m_curr_block; + unsigned m_num_cells; + cell_type** m_cells; + cell_type* m_curr_cell_ptr; + pod_vector m_sorted_cells; + pod_vector m_sorted_y; + cell_type m_curr_cell; + cell_type m_style_cell; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + bool m_sorted; }; @@ -132,10 +132,10 @@ namespace agg cell_type** ptr = m_cells + m_num_blocks - 1; while(m_num_blocks--) { - delete [] *ptr; + pod_allocator::deallocate(*ptr, cell_block_size); ptr--; } - delete [] m_cells; + pod_allocator::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::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::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::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 diff --git a/agg/include/agg_rasterizer_compound_aa.h b/agg/include/agg_rasterizer_compound_aa.h index 2e301d753..15b88b545 100755 --- a/agg/include/agg_rasterizer_compound_aa.h +++ b/agg/include/agg_rasterizer_compound_aa.h @@ -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 rasterizer_compound_aa { @@ -86,8 +95,9 @@ namespace agg }; public: - typedef Clip clip_type; - typedef typename Clip::conv_type conv_type; + 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 m_outline; clip_type m_clipper; filling_rule_e m_filling_rule; + layer_order_e m_layer_order; pod_vector m_styles; // Active Styles pod_vector m_ast; // Active Style Table (unique values) pod_vector m_asm; // Active Style Mask pod_vector m_cells; + pod_vector m_cover_buf; + pod_bvector m_master_alpha; - int m_min_style; - int m_max_style; - int m_scan_y; + 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 + void rasterizer_compound_aa::layer_order(layer_order_e order) + { + m_layer_order = order; + } + //------------------------------------------------------------------------ template void rasterizer_compound_aa::clip_box(double x1, double y1, @@ -316,7 +370,8 @@ namespace agg void rasterizer_compound_aa::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::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)) { - if(is_vertex(cmd)) - { - line_to_d(x, y); - } + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); } } @@ -407,6 +466,7 @@ namespace agg } m_scan_y = m_outline.min_y(); m_styles.allocate(m_max_style - m_min_style + 2, 128); + allocate_master_alpha(); return true; } @@ -453,83 +513,96 @@ namespace agg m_asm.allocate((num_styles + 7) >> 3, 8); m_asm.zero(); - // 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; - m_ast.add(0); - style = &m_styles[0]; - style->start_cell = 0; - style->num_cells = 0; - style->last_x = -0x7FFFFFFF; - - while(num_cells--) + if(num_cells) { - curr_cell = *cells++; - add_style(curr_cell->left); - add_style(curr_cell->right); - } + // 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; + m_ast.add(0); + style = &m_styles[0]; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = -0x7FFFFFFF; - // Convert the Y-histogram into the array of starting indexes - unsigned i; - unsigned start_cell = 0; - for(i = 0; i < m_ast.size(); i++) - { - style_info& st = m_styles[m_ast[i]]; - unsigned v = st.start_cell; - st.start_cell = start_cell; - start_cell += v; - } - - cells = m_outline.scanline_cells(m_scan_y); - num_cells = m_outline.scanline_num_cells(m_scan_y); - - while(num_cells--) - { - curr_cell = *cells++; - style_id = (curr_cell->left < 0) ? 0 : - curr_cell->left - m_min_style + 1; - - style = &m_styles[style_id]; - if(curr_cell->x == style->last_x) + m_sl_start = cells[0]->x; + m_sl_len = cells[num_cells-1]->x - m_sl_start + 1; + while(num_cells--) { - cell = &m_cells[style->start_cell + style->num_cells - 1]; - cell->area += curr_cell->area; - cell->cover += curr_cell->cover; - } - else - { - cell = &m_cells[style->start_cell + style->num_cells]; - cell->x = curr_cell->x; - cell->area = curr_cell->area; - cell->cover = curr_cell->cover; - style->last_x = curr_cell->x; - style->num_cells++; + curr_cell = *cells++; + add_style(curr_cell->left); + add_style(curr_cell->right); } - style_id = (curr_cell->right < 0) ? 0 : - curr_cell->right - m_min_style + 1; - - style = &m_styles[style_id]; - if(curr_cell->x == style->last_x) + // Convert the Y-histogram into the array of starting indexes + unsigned i; + unsigned start_cell = 0; + for(i = 0; i < m_ast.size(); i++) { - cell = &m_cells[style->start_cell + style->num_cells - 1]; - cell->area -= curr_cell->area; - cell->cover -= curr_cell->cover; + style_info& st = m_styles[m_ast[i]]; + unsigned v = st.start_cell; + st.start_cell = start_cell; + start_cell += v; } - else + + cells = m_outline.scanline_cells(m_scan_y); + num_cells = m_outline.scanline_num_cells(m_scan_y); + + while(num_cells--) { - cell = &m_cells[style->start_cell + style->num_cells]; - cell->x = curr_cell->x; - cell->area = -curr_cell->area; - cell->cover = -curr_cell->cover; - style->last_x = curr_cell->x; - style->num_cells++; + curr_cell = *cells++; + style_id = (curr_cell->left < 0) ? 0 : + curr_cell->left - m_min_style + 1; + + style = &m_styles[style_id]; + if(curr_cell->x == style->last_x) + { + cell = &m_cells[style->start_cell + style->num_cells - 1]; + cell->area += curr_cell->area; + cell->cover += curr_cell->cover; + } + else + { + cell = &m_cells[style->start_cell + style->num_cells]; + cell->x = curr_cell->x; + cell->area = curr_cell->area; + cell->cover = curr_cell->cover; + style->last_x = curr_cell->x; + style->num_cells++; + } + + style_id = (curr_cell->right < 0) ? 0 : + curr_cell->right - m_min_style + 1; + + style = &m_styles[style_id]; + if(curr_cell->x == style->last_x) + { + cell = &m_cells[style->start_cell + style->num_cells - 1]; + cell->area -= curr_cell->area; + cell->cover -= curr_cell->cover; + } + else + { + cell = &m_cells[style->start_cell + style->num_cells]; + cell->x = curr_cell->x; + cell->area = -curr_cell->area; + cell->cover = -curr_cell->cover; + style->last_x = curr_cell->x; + style->num_cells++; + } } } if(m_ast.size() > 1) break; ++m_scan_y; } ++m_scan_y; + + if(m_layer_order != layer_unsorted) + { + range_adaptor > 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 + AGG_INLINE bool rasterizer_compound_aa::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 + bool rasterizer_compound_aa::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 + cover_type* rasterizer_compound_aa::allocate_cover_buffer(unsigned len) + { + m_cover_buf.allocate(len, 256); + return &m_cover_buf[0]; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::allocate_master_alpha() + { + while((int)m_master_alpha.size() <= m_max_style) + { + m_master_alpha.add(aa_mask); + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::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); + } + } } diff --git a/agg/include/agg_rasterizer_outline.h b/agg/include/agg_rasterizer_outline.h index e2dea2aa2..65203e34c 100644 --- a/agg/include/agg_rasterizer_outline.h +++ b/agg/include/agg_rasterizer_outline.h @@ -23,13 +23,14 @@ namespace agg template 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) diff --git a/agg/include/agg_rasterizer_outline_aa.h b/agg/include/agg_rasterizer_outline_aa.h index d06a80fff..a06bd1e84 100644 --- a/agg/include/agg_rasterizer_outline_aa.h +++ b/agg/include/agg_rasterizer_outline_aa.h @@ -85,21 +85,21 @@ namespace agg typedef line_aa_vertex vertex_type; typedef vertex_sequence 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& operator = (const rasterizer_outline_aa&); - Renderer& m_ren; + Renderer* m_ren; vertex_storage_type m_src_vertices; outline_aa_join_e m_line_join; bool m_round_cap; @@ -245,19 +245,19 @@ 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, - 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), - dv.curr.y2 - (dv.next.x2 - dv.next.x1)); + 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), + dv.curr.y2 - (dv.next.x2 - dv.next.x1)); } dv.x1 = dv.x2; @@ -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, - x1 + (y2 - y1), - y1 - (x2 - x1), - x2 + (y2 - y1), - y2 - (x2 - x1)); + 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), - x2 + (y2 - y1), y2 - (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), - x2 + (y3 - y2), y2 - (x3 - x2)); + 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), - x3 + (y3 - y2), y3 - (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), - dv.xb1, dv.yb1); + m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); - m_ren.line3(lp2, dv.xb1, dv.yb1, - x3 + (y3 - y2), y3 - (x3 - x2)); + 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,31 +521,31 @@ 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), - x2 + (y2 - y1), y2 - (x2 - x1)); - 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)); + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + x2 + (y2 - y1), y2 - (x2 - x1)); + 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)); } else { bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); - m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), - dv.xb1, dv.yb1); + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); } } else { - m_ren.line1(prev, - x1 + (y2 - y1), - y1 - (x2 - x1)); + m_ren->line1(prev, + x1 + (y2 - y1), + y1 - (x2 - x1)); } if((dv.flags & 2) == 0 && m_line_join != outline_round_join) { @@ -558,30 +558,30 @@ namespace agg { if(m_line_join == outline_round_join) { - 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), - dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + 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), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); } else { - 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)); + 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, - dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), - dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + 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, - dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), - dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + 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)); } } diff --git a/agg/include/agg_rasterizer_scanline_aa.h b/agg/include/agg_rasterizer_scanline_aa.h index 04b516fd7..77bc41bc7 100644 --- a/agg/include/agg_rasterizer_scanline_aa.h +++ b/agg/include/agg_rasterizer_scanline_aa.h @@ -357,7 +357,7 @@ namespace agg template void rasterizer_scanline_aa::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::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::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)) { - if(is_vertex(cmd)) - { - line_to_d(x, y); - } + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + close_polygon(); } } @@ -452,6 +455,7 @@ namespace agg template void rasterizer_scanline_aa::sort() { + if(m_auto_close) close_polygon(); m_outline.sort_cells(); } @@ -459,7 +463,7 @@ namespace agg template AGG_INLINE bool rasterizer_scanline_aa::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 AGG_INLINE bool rasterizer_scanline_aa::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 bool rasterizer_scanline_aa::hit_test(int tx, int ty) diff --git a/agg/include/agg_renderer_base.h b/agg/include/agg_renderer_base.h index 19fd6de4e..ad7915a2a 100644 --- a/agg/include/agg_renderer_base.h +++ b/agg/include/agg_renderer_base.h @@ -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 + 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 + 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; diff --git a/agg/include/agg_renderer_markers.h b/agg/include/agg_renderer_markers.h index 6673e18e7..820f75307 100644 --- a/agg/include/agg_renderer_markers.h +++ b/agg/include/agg_renderer_markers.h @@ -65,8 +65,7 @@ namespace agg //-------------------------------------------------------------------- renderer_markers(base_ren_type& rbuf) : base_type(rbuf) - { - } + {} //-------------------------------------------------------------------- bool visible(int x, int y, int r) const diff --git a/agg/include/agg_renderer_mclip.h b/agg/include/agg_renderer_mclip.h index 2c8eb0fe6..96a7d4e09 100644 --- a/agg/include/agg_renderer_mclip.h +++ b/agg/include/agg_renderer_mclip.h @@ -37,11 +37,15 @@ namespace agg typedef renderer_base 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); } //-------------------------------------------------------------------- diff --git a/agg/include/agg_renderer_outline_aa.h b/agg/include/agg_renderer_outline_aa.h index bcb8b92ef..e3629db72 100644 --- a/agg/include/agg_renderer_outline_aa.h +++ b/agg/include/agg_renderer_outline_aa.h @@ -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 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,12 +1332,11 @@ namespace agg void set(double center_width, double smoother_width); //--------------------------------------------------------------------- - unsigned m_size; - value_type* m_profile; - value_type m_gamma[aa_scale]; - int m_subpixel_width; - double m_min_width; - double m_smoother_width; + pod_array m_profile; + value_type m_gamma[aa_scale]; + int m_subpixel_width; + double m_min_width; + double m_smoother_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; diff --git a/agg/include/agg_renderer_outline_image.h b/agg/include/agg_renderer_outline_image.h index 8376979bd..dd48450ed 100644 --- a/agg/include/agg_renderer_outline_image.h +++ b/agg/include/agg_renderer_outline_image.h @@ -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,12 +112,11 @@ 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_height + m_dilation * 2, - 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; color_type* d1; color_type* d2; @@ -195,7 +189,7 @@ namespace agg const filter_type* m_filter; unsigned m_dilation; int m_dilation_hr; - color_type* m_data; + pod_array 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 li(*this, lp, sx, sy, ex, ey, diff --git a/agg/include/agg_renderer_primitives.h b/agg/include/agg_renderer_primitives.h index a9d841094..f008db7c9 100644 --- a/agg/include/agg_renderer_primitives.h +++ b/agg/include/agg_renderer_primitives.h @@ -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) diff --git a/agg/include/agg_renderer_raster_text.h b/agg/include/agg_renderer_raster_text.h index d1de29807..87b43f960 100644 --- a/agg/include/agg_renderer_raster_text.h +++ b/agg/include/agg_renderer_raster_text.h @@ -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; } diff --git a/agg/include/agg_renderer_scanline.h b/agg/include/agg_renderer_scanline.h index 506c63560..6d65056c5 100644 --- a/agg/include/agg_renderer_scanline.h +++ b/agg/include/agg_renderer_scanline.h @@ -52,7 +52,6 @@ namespace agg } } - //===============================================render_scanlines_aa_solid template @@ -103,7 +102,6 @@ namespace agg } } - //==============================================renderer_scanline_aa_solid template 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 @@ -195,8 +191,6 @@ namespace agg } } - - //====================================================renderer_scanline_aa template class renderer_scanline_aa @@ -244,318 +238,6 @@ namespace agg - - - - - - - - - -/* - //===================================================renderer_scanline_bin - template 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 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 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 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 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 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 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 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 void render_scanline_bin_solid(const Scanline& sl, @@ -578,7 +260,6 @@ namespace agg } } - //==============================================render_scanlines_bin_solid template @@ -621,7 +302,6 @@ namespace agg } } - //=============================================renderer_scanline_bin_solid template 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 + 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 + 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 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 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 @@ -707,6 +472,7 @@ namespace agg + //=============================================render_scanlines_compound templatecovers; do { - colors->add(c, *covers); + if(*covers == cover_full) + { + *colors = c; + } + else + { + colors->add(c, *covers); + } ++colors; ++covers; } @@ -847,7 +620,14 @@ namespace agg covers = span_aa->covers; do { - colors->add(*cspan, *covers); + 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 + 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()) + } } diff --git a/agg/include/agg_rendering_buffer.h b/agg/include/agg_rendering_buffer.h index 399c554b6..14d3e5397 100644 --- a/agg/include/agg_rendering_buffer.h +++ b/agg/include/agg_rendering_buffer.h @@ -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 row_ptr_cache + //===========================================================row_accessor + template 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 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_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_buf = m_start = buf; + m_width = width; + m_height = height; + m_stride = stride; + if(stride < 0) + { + 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 @@ -154,27 +126,173 @@ namespace agg } } - private: //-------------------------------------------------------------------- - // Prohibit copying - row_ptr_cache(const row_ptr_cache&); - const row_ptr_cache& operator = (const row_ptr_cache&); - - private: - //-------------------------------------------------------------------- - T* m_buf; // Pointer to renrdering buffer - 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 - unsigned m_max_height; // The maximal height (currently allocated) + T* m_buf; // Pointer to renrdering 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 }; + + //==========================================================row_ptr_cache + template class row_ptr_cache + { + public: + typedef const_row_info 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 + 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 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 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 rendering_buffer; + typedef row_accessor rendering_buffer; +#endif } diff --git a/agg/include/agg_rendering_buffer_dynarow.h b/agg/include/agg_rendering_buffer_dynarow.h index f7a913409..188746f3d 100644 --- a/agg/include/agg_rendering_buffer_dynarow.h +++ b/agg/include/agg_rendering_buffer_dynarow.h @@ -20,8 +20,7 @@ #ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED #define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED -#include -#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 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::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::allocate(m_byte_width); r->ptr = p; r->x1 = x; r->x2 = x2; @@ -128,10 +124,10 @@ namespace agg private: //-------------------------------------------------------------------- - 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 + pod_array 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 }; diff --git a/agg/include/agg_scanline_bin.h b/agg/include/agg_scanline_bin.h index e0584d071..660292b61 100644 --- a/agg/include/agg_scanline_bin.h +++ b/agg/include/agg_scanline_bin.h @@ -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,23 +121,22 @@ 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; - span* m_cur_span; + int m_last_x; + int m_y; + pod_array m_spans; + span* m_cur_span; }; diff --git a/agg/include/agg_scanline_p.h b/agg/include/agg_scanline_p.h index e93bbd588..1d1cbe72f 100644 --- a/agg/include/agg_scanline_p.h +++ b/agg/include/agg_scanline_p.h @@ -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,27 +149,26 @@ 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; - cover_type* m_cover_ptr; - span* m_spans; - span* m_cur_span; + int m_last_x; + int m_y; + pod_array m_covers; + cover_type* m_cover_ptr; + pod_array 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(); } @@ -332,12 +313,12 @@ namespace agg scanline32_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; - cover_type* m_cover_ptr; - span_array_type m_spans; + unsigned m_max_len; + int m_last_x; + int m_y; + pod_array m_covers; + cover_type* m_cover_ptr; + span_array_type m_spans; }; diff --git a/agg/include/agg_scanline_storage_aa.h b/agg/include/agg_scanline_storage_aa.h index 033e3291e..be452a88f 100644 --- a/agg/include/agg_scanline_storage_aa.h +++ b/agg/include/agg_scanline_storage_aa.h @@ -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::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::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::allocate(dst.len); memcpy(dst.ptr, src.ptr, dst.len * sizeof(T)); m_extra_storage.add(dst); } diff --git a/agg/include/agg_scanline_u.h b/agg/include/agg_scanline_u.h index 11513067b..5a28ed17e 100644 --- a/agg/include/agg_scanline_u.h +++ b/agg/include/agg_scanline_u.h @@ -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_last_x = 0x7FFFFFF0; + m_min_x = min_x; + 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,27 +212,26 @@ 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&); const self_type& operator = (const self_type&); private: - int m_min_x; - unsigned m_max_len; - int m_last_x; - int m_y; - cover_type* m_covers; - span* m_spans; - span* m_cur_span; + int m_min_x; + int m_last_x; + int m_y; + pod_array m_covers; + pod_array 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; } @@ -456,12 +439,11 @@ namespace agg const self_type& operator = (const self_type&); private: - int m_min_x; - unsigned m_max_len; - int m_last_x; - int m_y; - cover_type* m_covers; - span_array_type m_spans; + int m_min_x; + int m_last_x; + int m_y; + pod_array m_covers; + span_array_type m_spans; }; diff --git a/agg/include/agg_span_allocator.h b/agg/include/agg_span_allocator.h index 4cbc3cc05..201b69bb0 100644 --- a/agg/include/agg_span_allocator.h +++ b/agg/include/agg_span_allocator.h @@ -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&); - const span_allocator& operator = (const span_allocator&); - - unsigned m_max_span_len; - color_type* m_span; + pod_array m_span; }; } diff --git a/agg/include/agg_span_converter.h b/agg/include/agg_span_converter.h index 27b78e1c3..91d0f87c2 100644 --- a/agg/include/agg_span_converter.h +++ b/agg/include/agg_span_converter.h @@ -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() { diff --git a/agg/include/agg_span_gradient.h b/agg/include/agg_span_gradient.h index 6047bf874..e30d42b1a 100644 --- a/agg/include/agg_span_gradient.h +++ b/agg/include/agg_span_gradient.h @@ -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) - { - // 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)); + // 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) + { + 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)); } - - // Calculate the solution to be used in the case where x == focus_x - //------------------------------ - m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x)); + m_mul = m_r / d; } - 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 gradient_repeat_adaptor { @@ -390,7 +338,6 @@ namespace agg const GradientF* m_gradient; }; - //================================================gradient_reflect_adaptor template class gradient_reflect_adaptor { diff --git a/agg/include/agg_span_image_filter.h b/agg/include/agg_span_image_filter.h index 4832917b9..47e2f44e3 100644 --- a/agg/include/agg_span_image_filter.h +++ b/agg/include/agg_span_image_filter.h @@ -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,33 +136,29 @@ 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 > m_scale_limit) scale_x = m_scale_limit; - m_rx = uround( scale_x * double(image_subpixel_scale)); - m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale)); - } + if(scale_x < 1) scale_x = 1; + if(scale_y < 1) scale_y = 1; - 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)); - } + 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)); + + m_ry = uround( scale_y * double(image_subpixel_scale)); + m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); } protected: @@ -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; diff --git a/agg/include/agg_span_image_filter_gray.h b/agg/include/agg_span_image_filter_gray.h index 002234498..9f3ede78f 100644 --- a/agg/include/agg_span_image_filter_gray.h +++ b/agg/include/agg_span_image_filter_gray.h @@ -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; - } + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; int radius_x = (diameter * rx) >> 1; int radius_y = (diameter * ry) >> 1; diff --git a/agg/include/agg_span_image_filter_rgb.h b/agg/include/agg_span_image_filter_rgb.h index bd6143606..a72ffd240 100644 --- a/agg/include/agg_span_image_filter_rgb.h +++ b/agg/include/agg_span_image_filter_rgb.h @@ -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; - } + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; int radius_x = (diameter * rx) >> 1; int radius_y = (diameter * ry) >> 1; diff --git a/agg/include/agg_span_image_filter_rgba.h b/agg/include/agg_span_image_filter_rgba.h index 6d86fcb70..134a80255 100644 --- a/agg/include/agg_span_image_filter_rgba.h +++ b/agg/include/agg_span_image_filter_rgba.h @@ -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; - } + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; int radius_x = (diameter * rx) >> 1; int radius_y = (diameter * ry) >> 1; diff --git a/agg/include/agg_span_pattern_gray.h b/agg/include/agg_span_pattern_gray.h index 83ae9c4bc..ae1a49f87 100644 --- a/agg/include/agg_span_pattern_gray.h +++ b/agg/include/agg_span_pattern_gray.h @@ -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; } diff --git a/agg/include/agg_span_pattern_rgb.h b/agg/include/agg_span_pattern_rgb.h index d401cb657..4850508af 100644 --- a/agg/include/agg_span_pattern_rgb.h +++ b/agg/include/agg_span_pattern_rgb.h @@ -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; } diff --git a/agg/include/agg_span_pattern_rgba.h b/agg/include/agg_span_pattern_rgba.h index 2725f8394..d47d2a6c0 100644 --- a/agg/include/agg_span_pattern_rgba.h +++ b/agg/include/agg_span_pattern_rgba.h @@ -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); diff --git a/agg/include/agg_trans_affine.h b/agg/include/agg_trans_affine.h index 0f9b21e36..cbed7c86d 100644 --- a/agg/include/agg_trans_affine.h +++ b/agg/include/agg_trans_affine.h @@ -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)) + {} + }; + } diff --git a/agg/include/agg_trans_perspective.h b/agg/include/agg_trans_perspective.h index 0937494a1..20a9aa66d 100644 --- a/agg/include/agg_trans_perspective.h +++ b/agg/include/agg_trans_perspective.h @@ -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]; - } - m_valid = simul_eq<8, 1>::solve(left, right, m_mtx); + return multiply_inv(m); + } + 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); } - - private: - double m_mtx[8][1]; - bool m_valid; }; + + + + + + + + + + + + + + //------------------------------------------------------------------------ + 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); + } + + } #endif + diff --git a/agg/include/agg_trans_warp_magnifier.h b/agg/include/agg_trans_warp_magnifier.h index fe8de000f..38a92dbec 100644 --- a/agg/include/agg_trans_warp_magnifier.h +++ b/agg/include/agg_trans_warp_magnifier.h @@ -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; diff --git a/agg/include/agg_vcgen_contour.h b/agg/include/agg_vcgen_contour.h index c56f02636..8c25da13f 100644 --- a/agg/include/agg_vcgen_contour.h +++ b/agg/include/agg_vcgen_contour.h @@ -43,22 +43,27 @@ 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; } - bool auto_detect_orientation() const { return m_auto_detect; } + 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 void remove_all(); @@ -72,22 +77,16 @@ namespace agg vcgen_contour(const vcgen_contour&); const vcgen_contour& operator = (const vcgen_contour&); - 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; - unsigned m_closed; - unsigned m_orientation; - bool m_auto_detect; + math_stroke m_stroker; + double m_width; + vertex_storage m_src_vertices; + coord_storage m_out_vertices; + status_e m_status; + unsigned m_src_vertex; + unsigned m_out_vertex; + unsigned m_closed; + unsigned m_orientation; + bool m_auto_detect; }; } diff --git a/agg/include/agg_vcgen_stroke.h b/agg/include/agg_vcgen_stroke.h index e0d9dc515..778223fe4 100644 --- a/agg/include/agg_vcgen_stroke.h +++ b/agg/include/agg_vcgen_stroke.h @@ -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,21 +85,15 @@ namespace agg vcgen_stroke(const vcgen_stroke&); const vcgen_stroke& operator = (const vcgen_stroke&); - 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; - unsigned m_src_vertex; - unsigned m_out_vertex; + math_stroke m_stroker; + vertex_storage m_src_vertices; + coord_storage m_out_vertices; + double m_shorten; + unsigned m_closed; + status_e m_status; + status_e m_prev_status; + unsigned m_src_vertex; + unsigned m_out_vertex; }; diff --git a/agg/include/agg_vertex_sequence.h b/agg/include/agg_vertex_sequence.h index f9bc915d4..2ad0701b3 100644 --- a/agg/include/agg_vertex_sequence.h +++ b/agg/include/agg_vertex_sequence.h @@ -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 diff --git a/agg/src/agg_bspline.cpp b/agg/src/agg_bspline.cpp index 2dc4e1b48..e1fda9f51 100644 --- a/agg/src/agg_bspline.cpp +++ b/agg/src/agg_bspline.cpp @@ -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 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; } diff --git a/agg/src/agg_curves.cpp b/agg/src/agg_curves.cpp index ae8cb5b9e..cb7a8d7ae 100644 --- a/agg/src/agg_curves.cpp +++ b/agg/src/agg_curves.cpp @@ -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,12 +193,31 @@ 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; - } + } } // Continue subdivision @@ -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)); - return; - } + 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; diff --git a/agg/src/agg_gsv_text.cpp b/agg/src/agg_gsv_text.cpp index 0ccc64b7e..ffb24eb9b 100644 --- a/agg/src/agg_gsv_text.cpp +++ b/agg/src/agg_gsv_text.cpp @@ -19,6 +19,8 @@ #include #include #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) { @@ -622,7 +603,6 @@ namespace agg int8 yc, yf; int dx, dy; bool quit = false; - while(!quit) { @@ -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; + } } diff --git a/agg/src/agg_image_filters.cpp b/agg/src/agg_image_filters.cpp index 531a056d7..549d9adbf 100644 --- a/agg/src/agg_image_filters.cpp +++ b/agg/src/agg_image_filters.cpp @@ -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); } } diff --git a/agg/src/agg_line_aa_basics.cpp b/agg/src/agg_line_aa_basics.cpp index ec6e854f2..018d65366 100644 --- a/agg/src/agg_line_aa_basics.cpp +++ b/agg/src/agg_line_aa_basics.cpp @@ -41,9 +41,9 @@ namespace agg // (7)111 | 101(5) // [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 }; + // 0,1,2,3,4,5,6,7 + 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 }; diff --git a/agg/src/agg_line_profile_aa.cpp b/agg/src/agg_line_profile_aa.cpp index 6646dede9..6066662cb 100644 --- a/agg/src/agg_line_profile_aa.cpp +++ b/agg/src/agg_line_profile_aa.cpp @@ -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]; } diff --git a/agg/src/agg_sqrt_tables.cpp b/agg/src/agg_sqrt_tables.cpp index 5b3827c93..19a1bd8cb 100644 --- a/agg/src/agg_sqrt_tables.cpp +++ b/agg/src/agg_sqrt_tables.cpp @@ -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, diff --git a/agg/src/agg_trans_affine.cpp b/agg/src/agg_trans_affine.cpp index 4c8bba199..99febc953 100644 --- a/agg/src/agg_trans_affine.cpp +++ b/agg/src/agg_trans_affine.cpp @@ -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; } diff --git a/agg/src/agg_trans_warp_magnifier.cpp b/agg/src/agg_trans_warp_magnifier.cpp index 99ee2b8a2..e65afabba 100644 --- a/agg/src/agg_trans_warp_magnifier.cpp +++ b/agg/src/agg_trans_warp_magnifier.cpp @@ -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); } diff --git a/agg/src/agg_vcgen_contour.cpp b/agg/src/agg_vcgen_contour.cpp index ae8f14aa3..a6a99405a 100644 --- a/agg/src/agg_vcgen_contour.cpp +++ b/agg/src/agg_vcgen_contour.cpp @@ -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_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_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_src_vertex; m_status = out_vertices; m_out_vertex = 0; diff --git a/agg/src/agg_vcgen_stroke.cpp b/agg/src/agg_vcgen_stroke.cpp index c505f0fe8..2dae3e122 100644 --- a/agg/src/agg_vcgen_stroke.cpp +++ b/agg/src/agg_vcgen_stroke.cpp @@ -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_src_vertices[0], - m_src_vertices[1], - m_src_vertices[0].dist, - m_line_cap, - m_width, - m_approx_scale); + m_stroker.calc_cap(m_out_vertices, + m_src_vertices[0], + m_src_vertices[1], + 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_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_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_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_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_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_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_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_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_prev_status = m_status; m_status = out_vertices; diff --git a/demo/python/rundemo.py b/demo/python/rundemo.py index 44dda9187..1f994d171 100644 --- a/demo/python/rundemo.py +++ b/demo/python/rundemo.py @@ -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) diff --git a/src/agg_renderer.cpp b/src/agg_renderer.cpp index 3b51e5b27..8b00b1536 100644 --- a/src/agg_renderer.cpp +++ b/src/agg_renderer.cpp @@ -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 buf(pixmap_.raw_data(),width,height,width * 4); + agg::row_accessor buf(pixmap_.raw_data(),width,height,width * 4); agg::pixfmt_rgba32 pixf(buf); ren_base renb(pixf); @@ -179,13 +179,13 @@ namespace mapnik if (geom && geom->num_points() > 1) { path_type path(t_,*geom,prj_trans); - agg::row_ptr_cache buf(pixmap_.raw_data(), + agg::row_accessor buf(pixmap_.raw_data(), pixmap_.width(), pixmap_.height(), pixmap_.width()*4); agg::pixfmt_rgba32 pixf(buf); ren_base renb(pixf); - + mapnik::stroke const& stroke_ = sym.get_stroke(); Color const& col = stroke_.get_color(); @@ -241,7 +241,7 @@ namespace mapnik prof.width(stroke_.get_width()); renderer_oaa ren_oaa(renb, prof); rasterizer_outline_aa ras_oaa(ren_oaa); - + ren_oaa.color(agg::rgba8(r, g, b, int(255*stroke_.get_opacity()))); ren_oaa.clip_box(0,0,pixmap_.width(),pixmap_.height()); ras_oaa.add_path(path); @@ -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 buf(pixmap_.raw_data(), width, height,width*4); + agg::row_accessor 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 buf(pixmap_.raw_data(),width,height,width * 4); + agg::row_accessor 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 pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4); + agg::row_accessor pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4); double x0,y0; path.vertex(&x0,&y0); @@ -443,12 +443,13 @@ namespace mapnik unsigned offset_x = unsigned(width - x0); unsigned offset_y = unsigned(height - y0); - + agg::span_allocator 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); - + agg::rasterizer_scanline_aa<> ras; agg::scanline_u8 sl; ras.clip_box(0,0,width,height); diff --git a/src/load_map.cpp b/src/load_map.cpp index bf614e15d..f54eed2d7 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -126,16 +126,23 @@ namespace mapnik if ( sym.first == "PointSymbolizer") { - std::string file = - sym.second.get(".file"); - std::string type = - sym.second.get(".type"); - unsigned width = - sym.second.get(".width"); - unsigned height = - sym.second.get(".height"); + boost::optional file = + sym.second.get_optional(".file"); + boost::optional type = + sym.second.get_optional(".type"); + boost::optional width = + sym.second.get_optional(".width"); + boost::optional height = + sym.second.get_optional(".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") {